aspnetcore/src/Microsoft.AspNet.Owin/WebSockets/WebSocketAcceptAdapter.cs

92 lines
3.5 KiB
C#

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Http.Interfaces;
namespace Microsoft.AspNet.Owin
{
using AppFunc = Func<IDictionary<string, object>, Task>;
using WebSocketAccept =
Action
<
IDictionary<string, object>, // WebSocket Accept parameters
Func // WebSocketFunc callback
<
IDictionary<string, object>, // WebSocket environment
Task // Complete
>
>;
using WebSocketAcceptAlt =
Func
<
IWebSocketAcceptContext, // WebSocket Accept parameters
Task<WebSocket>
>;
/// <summary>
/// This adapts the ASP.NET WebSocket Accept flow to match the OWIN WebSocket accept flow.
/// This enables OWIN based components to use WebSockets on ASP.NET servers.
/// </summary>
public class WebSocketAcceptAdapter
{
private IDictionary<string, object> _env;
private WebSocketAcceptAlt _accept;
private AppFunc _callback;
private IDictionary<string, object> _options;
public WebSocketAcceptAdapter(IDictionary<string, object> env, WebSocketAcceptAlt accept)
{
_env = env;
_accept = accept;
}
private void AcceptWebSocket(IDictionary<string, object> options, AppFunc callback)
{
_options = options;
_callback = callback;
_env[OwinConstants.ResponseStatusCode] = 101;
}
public static AppFunc AdaptWebSockets(AppFunc next)
{
return async environment =>
{
object accept;
if (environment.TryGetValue(OwinConstants.WebSocket.AcceptAlt, out accept) && accept is WebSocketAcceptAlt)
{
var adapter = new WebSocketAcceptAdapter(environment, (WebSocketAcceptAlt)accept);
environment[OwinConstants.WebSocket.Accept] = new WebSocketAccept(adapter.AcceptWebSocket);
await next(environment);
if ((int)environment[OwinConstants.ResponseStatusCode] == 101 && adapter._callback != null)
{
IWebSocketAcceptContext acceptContext = null;
object obj;
if (adapter._options != null && adapter._options.TryGetValue(typeof(IWebSocketAcceptContext).FullName, out obj))
{
acceptContext = obj as IWebSocketAcceptContext;
}
else if (adapter._options != null)
{
acceptContext = new OwinWebSocketAcceptContext(adapter._options);
}
var webSocket = await adapter._accept(acceptContext);
var webSocketAdapter = new WebSocketAdapter(webSocket, (CancellationToken)environment[OwinConstants.CallCancelled]);
await adapter._callback(webSocketAdapter.Environment);
await webSocketAdapter.CleanupAsync();
}
}
else
{
await next(environment);
}
};
}
}
}