예제 #1
0
        private async Task <WebSocket> AcceptWebSocketAsync(WebSocketAcceptContext context)
        {
            IDictionary <string, object> options = null;

            if (context is OwinWebSocketAcceptContext)
            {
                var acceptContext = context as OwinWebSocketAcceptContext;
                options      = acceptContext.Options;
                _subProtocol = acceptContext.SubProtocol;
            }
            else if (context?.SubProtocol != null)
            {
                options = new Dictionary <string, object>(1)
                {
                    { OwinConstants.WebSocket.SubProtocol, context.SubProtocol }
                };
                _subProtocol = context.SubProtocol;
            }

            // Accept may have been called synchronously on the original request thread, we might not have a task yet. Go async.
            await _upstreamWentAsync.Task;

            _owinWebSocketAccept(options, OwinAcceptCallback);
            _requestTcs.TrySetResult(0); // Let the pipeline unwind.

            return(await _acceptTcs.Task);
        }
        public ValueTask <IWebSocketConnection> AcceptWebSocketConnectionAsync(WebSocketAcceptContext acceptContext)
        {
            if (!IsWebSocketRequest)
            {
                throw new InvalidOperationException("Not a WebSocket request."); // TODO: LOC
            }

            string subProtocol = null;

            if (acceptContext != null)
            {
                subProtocol = acceptContext.SubProtocol;
            }

            _logger.LogDebug("WebSocket Handshake completed. SubProtocol: {0}", subProtocol);

            var key = string.Join(", ", _context.Request.Headers[Constants.Headers.SecWebSocketKey]);

            var responseHeaders = HandshakeHelpers.GenerateResponseHeaders(key, subProtocol);

            foreach (var headerPair in responseHeaders)
            {
                _context.Response.Headers[headerPair.Key] = headerPair.Value;
            }

            // TODO: Avoid task allocation if there's a ValueTask-based UpgradeAsync?
            return(new ValueTask <IWebSocketConnection>(AcceptWebSocketConnectionCoreAsync(subProtocol)));
        }
예제 #3
0
            public async Task <WebSocket> AcceptAsync(WebSocketAcceptContext acceptContext)
            {
                if (!IsWebSocketRequest)
                {
                    throw new InvalidOperationException("Not a WebSocket request."); // TODO: LOC
                }

                string?subProtocol = null;

                if (acceptContext != null)
                {
                    subProtocol = acceptContext.SubProtocol;
                }

                TimeSpan keepAliveInterval     = _options.KeepAliveInterval;
                var      advancedAcceptContext = acceptContext as ExtendedWebSocketAcceptContext;

                if (advancedAcceptContext != null)
                {
                    if (advancedAcceptContext.KeepAliveInterval.HasValue)
                    {
                        keepAliveInterval = advancedAcceptContext.KeepAliveInterval.Value;
                    }
                }

                string key = _context.Request.Headers[HeaderNames.SecWebSocketKey];

                HandshakeHelpers.GenerateResponseHeaders(key, subProtocol, _context.Response.Headers);

                Stream opaqueTransport = await _upgradeFeature.UpgradeAsync(); // Sets status code to 101

                return(WebSocket.CreateFromStream(opaqueTransport, isServer: true, subProtocol: subProtocol, keepAliveInterval: keepAliveInterval));
            }
예제 #4
0
 public override Task <WebSocket> AcceptWebSocketAsync(WebSocketAcceptContext acceptContext)
 {
     if (WebSocketFeature == null)
     {
         throw new NotSupportedException("WebSockets are not supported");
     }
     return(WebSocketFeature.AcceptAsync(acceptContext));
 }
        private async Task <WebSocket> CreateCompressionWebSocket(WebSocketAcceptContext acceptContext, string subProtocol)
        {
            WebSocketCompressionAcceptContext compressionAcceptContext = acceptContext as WebSocketCompressionAcceptContext;

            return(new CompressionWebSocket(await _upgradeFeature.UpgradeAsync(), subProtocol,
                                            compressionAcceptContext?.KeepAliveInterval ?? _options.KeepAliveInterval,
                                            compressionAcceptContext?.ReceiveBufferSize ?? _options.ReceiveBufferSize
                                            ));
        }
예제 #6
0
            Task <WebSocket> IHttpWebSocketFeature.AcceptAsync(WebSocketAcceptContext context)
            {
                HttpContext.Response.StatusCode = 101; // Switching Protocols

                var websockets = TestWebSocket.CreatePair(context.SubProtocol);

                _clientWebSocketTcs.SetResult(websockets.Item1);
                _serverWebSocket = websockets.Item2;
                return(Task.FromResult <WebSocket>(_serverWebSocket));
            }
        public Task <WebSocket> AcceptAsync(WebSocketAcceptContext context)
        {
            var clientToServer = Channel.CreateUnbounded <WebSocketMessage>();
            var serverToClient = Channel.CreateUnbounded <WebSocketMessage>();

            var clientSocket = new WebSocketChannel(serverToClient.In, clientToServer.Out);
            var serverSocket = new WebSocketChannel(clientToServer.In, serverToClient.Out);

            Client = clientSocket;
            return(Task.FromResult <WebSocket>(serverSocket));
        }
예제 #8
0
        Task <WebSocket> IHttpWebSocketFeature.AcceptAsync(WebSocketAcceptContext context)
        {
            // TODO: Advanced params
            string subProtocol = null;

            if (context != null)
            {
                subProtocol = context.SubProtocol;
            }
            return(_requestContext.AcceptWebSocketAsync(subProtocol));
        }
예제 #9
0
        Task <WebSocket> IHttpWebSocketFeature.AcceptAsync(WebSocketAcceptContext context)
        {
            object obj;

            if (!Environment.TryGetValue(OwinConstants.WebSocket.AcceptAlt, out obj))
            {
                throw new NotSupportedException("WebSockets are not supported"); // TODO: LOC
            }
            var accept = (Func <WebSocketAcceptContext, Task <WebSocket> >)obj;

            return(accept(context));
        }
예제 #10
0
 public async Task<WebSocket> AcceptAsync(WebSocketAcceptContext context)
 {
     try
     {
         WebSocket ws = await _session.AcceptWebSocket();
         return ws;
     }
     finally
     {
         _acceptedTcs.SetResult(true);
     }
 }
        public Task <WebSocket> AcceptAsync(WebSocketAcceptContext acceptContext)
        {
            string subProtocol = acceptContext?.SubProtocol;

            if (!IsWebSocketRequest)
            {
                throw new InvalidOperationException("The current request is not a supported WebSocket handshake request.");
            }

            SetAcceptWebSocketHandshakeHeaders(_context, subProtocol);

            return(CreateCompressionWebSocket(acceptContext, subProtocol));
        }
예제 #12
0
        public async Task <WebSocket> AcceptAsync(WebSocketAcceptContext context)
        {
            try
            {
                WebSocket ws = await _session.AcceptWebSocket();

                return(ws);
            }
            finally
            {
                _acceptedTcs.SetResult(true);
            }
        }
        public Task <WebSocket> AcceptAsync(WebSocketAcceptContext context)
        {
            var clientToServer = Channel.CreateUnbounded <WebSocketMessage>();
            var serverToClient = Channel.CreateUnbounded <WebSocketMessage>();

            var clientSocket = new WebSocketChannel(serverToClient.Reader, clientToServer.Writer);
            var serverSocket = new WebSocketChannel(clientToServer.Reader, serverToClient.Writer);

            Client      = clientSocket;
            SubProtocol = context.SubProtocol;

            _accepted.TrySetResult(null);
            return(Task.FromResult <WebSocket>(serverSocket));
        }
예제 #14
0
            async Task <WebSocket> IHttpWebSocketFeature.AcceptAsync(WebSocketAcceptContext context)
            {
                var websockets = TestWebSocket.CreatePair(context.SubProtocol);

                if (_httpContext.Response.HasStarted)
                {
                    throw new InvalidOperationException("The response has already started");
                }

                _httpContext.Response.StatusCode = StatusCodes.Status101SwitchingProtocols;
                ClientWebSocket = websockets.Item1;
                ServerWebSocket = websockets.Item2;
                await _httpContext.Response.Body.FlushAsync(_httpContext.RequestAborted); // Send headers to the client

                return(ServerWebSocket);
            }
예제 #15
0
            public async Task <WebSocket> AcceptAsync(WebSocketAcceptContext acceptContext)
            {
                if (!IsWebSocketRequest)
                {
                    throw new InvalidOperationException("Not a WebSocket request."); // TODO: LOC
                }

                string subProtocol = null;

                if (acceptContext != null)
                {
                    subProtocol = acceptContext.SubProtocol;
                }

                TimeSpan keepAliveInterval     = _options.KeepAliveInterval;
                int      receiveBufferSize     = _options.ReceiveBufferSize;
                var      advancedAcceptContext = acceptContext as ExtendedWebSocketAcceptContext;

                if (advancedAcceptContext != null)
                {
                    if (advancedAcceptContext.ReceiveBufferSize.HasValue)
                    {
                        receiveBufferSize = advancedAcceptContext.ReceiveBufferSize.Value;
                    }
                    if (advancedAcceptContext.KeepAliveInterval.HasValue)
                    {
                        keepAliveInterval = advancedAcceptContext.KeepAliveInterval.Value;
                    }
                }

                string key = string.Join(", ", _context.Request.Headers[Constants.Headers.SecWebSocketKey]);

                var responseHeaders = HandshakeHelpers.GenerateResponseHeaders(key, subProtocol);

                foreach (var headerPair in responseHeaders)
                {
                    _context.Response.Headers[headerPair.Key] = headerPair.Value;
                }

                Stream opaqueTransport = await _upgradeFeature.UpgradeAsync(); // Sets status code to 101

                // Allocate a buffer for receive (default is 4k)
                var buffer = new byte[receiveBufferSize];

                return(WebSocketProtocol.CreateFromStream(opaqueTransport, isServer: true, subProtocol: subProtocol, keepAliveInterval: keepAliveInterval, buffer: buffer));
            }
예제 #16
0
            Task <WebSocket> IHttpWebSocketFeature.AcceptAsync(WebSocketAcceptContext context)
            {
                var websockets = TestWebSocket.CreatePair(context.SubProtocol);

                if (_clientWebSocketTcs.TrySetResult(websockets.Item1))
                {
                    Context.HttpContext.Response.StatusCode = StatusCodes.Status101SwitchingProtocols;
                    _serverWebSocket = websockets.Item2;
                    return(Task.FromResult(_serverWebSocket));
                }
                else
                {
                    Context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
                    websockets.Item1.Dispose();
                    websockets.Item2.Dispose();
                    return(_clientWebSocketTcs.Task); // Canceled or Faulted - no result
                }
            }
        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)
                    {
                        WebSocketAcceptContext acceptContext = null;
                        object obj;
                        if (adapter._options != null && adapter._options.TryGetValue(typeof(WebSocketAcceptContext).FullName, out obj))
                        {
                            acceptContext = obj as WebSocketAcceptContext;
                        }
                        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);
                }
            });
        }
예제 #18
0
        public async Task <WebSocket> AcceptAsync(WebSocketAcceptContext context)
        {
            Debug.Assert(IsWebSocketRequest);

            var response = Context.Response;

            var deflateOptions = ParseDeflateOptions(Context.Request.Headers[WebSocketHeaders.SecWebSocketExtensions].FirstOrDefault() ?? string.Empty, out var responseExtensions);

            if (deflateOptions is not null)
            {
                response.Headers[WebSocketHeaders.SecWebSocketExtensions] = responseExtensions;
            }
            response.Headers[WebSocketHeaders.Connection]         = "Upgrade";
            response.Headers[WebSocketHeaders.ConnectionUpgrade]  = "websocket";
            response.Headers[WebSocketHeaders.SecWebSocketAccept] = CreateResponseKey();

            // Sets status code to 101
            var stream = await _upgradeFeature.UpgradeAsync();

            if (stream == null)
            {
                Context.Abort();

                throw new WebSocketException("Failed to upgrade websocket connection.");
            }

            s_managedWebSocketType ??= typeof(WebSocket).Assembly.GetType("System.Net.WebSockets.ManagedWebSocket", throwOnError: true);
            s_webSocketCtor ??= s_managedWebSocketType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).First(x => x.GetParameters().Length == 2);
            s_webSocketOptionsType ??= typeof(WebSocket).Assembly.GetType("System.Net.WebSockets.WebSocketCreationOptions", throwOnError: true);

            object options = Activator.CreateInstance(s_webSocketOptionsType);

            ((dynamic)options).IsServer          = true;
            ((dynamic)options).KeepAliveInterval = TimeSpan.Zero;
            options.GetType().GetProperty("DangerousDeflateOptions").SetValue(options, deflateOptions);

            return((WebSocket)s_webSocketCtor.Invoke(new object[] { stream, options }));
        }
예제 #19
0
 public async Task<WebSocket> AcceptAsync(WebSocketAcceptContext context)
 {
     var socket = new SockJSWebSocket(await _feature.AcceptAsync(context));
     await socket.OpenAsync(CancellationToken.None);
     return socket;
 }
예제 #20
0
 Task <WebSocket> IHttpWebSocketFeature.AcceptAsync(WebSocketAcceptContext context)
 {
     throw new NotImplementedException();
 }
 public async Task<WebSocket> AcceptAsync(WebSocketAcceptContext context)
 {
     var socket = new SockJsWebSocket(await _feature.AcceptAsync(context));
     await socket.OpenAsync(CancellationToken.None);
     return socket;
 }
예제 #22
0
 public Task <WebSocket> AcceptAsync(WebSocketAcceptContext context)
 {
     throw new NotImplementedException();
 }
예제 #23
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="acceptContext"></param>
 /// <returns></returns>
 public virtual Task <WebSocket> AcceptWebSocketAsync(WebSocketAcceptContext acceptContext) => throw new NotImplementedException();
예제 #24
0
            public async Task <WebSocket> AcceptAsync(WebSocketAcceptContext acceptContext)
            {
                if (!IsWebSocketRequest)
                {
                    throw new InvalidOperationException("Not a WebSocket request."); // TODO: LOC
                }

                string?  subProtocol           = null;
                bool     enableCompression     = false;
                bool     serverContextTakeover = true;
                int      serverMaxWindowBits   = 15;
                TimeSpan keepAliveInterval     = _options.KeepAliveInterval;

                if (acceptContext != null)
                {
                    subProtocol           = acceptContext.SubProtocol;
                    enableCompression     = acceptContext.DangerousEnableCompression;
                    serverContextTakeover = !acceptContext.DisableServerContextTakeover;
                    serverMaxWindowBits   = acceptContext.ServerMaxWindowBits;
                    keepAliveInterval     = acceptContext.KeepAliveInterval ?? keepAliveInterval;
                }

#pragma warning disable CS0618 // Type or member is obsolete
                if (acceptContext is ExtendedWebSocketAcceptContext advancedAcceptContext)
#pragma warning restore CS0618 // Type or member is obsolete
                {
                    if (advancedAcceptContext.KeepAliveInterval.HasValue)
                    {
                        keepAliveInterval = advancedAcceptContext.KeepAliveInterval.Value;
                    }
                }

                var key = _context.Request.Headers.SecWebSocketKey.ToString();
                HandshakeHelpers.GenerateResponseHeaders(key, subProtocol, _context.Response.Headers);

                WebSocketDeflateOptions?deflateOptions = null;
                if (enableCompression)
                {
                    var ext = _context.Request.Headers.SecWebSocketExtensions;
                    if (ext.Count != 0)
                    {
                        // loop over each extension offer, extensions can have multiple offers, we can accept any
                        foreach (var extension in _context.Request.Headers.GetCommaSeparatedValues(HeaderNames.SecWebSocketExtensions))
                        {
                            if (extension.AsSpan().TrimStart().StartsWith("permessage-deflate", StringComparison.Ordinal))
                            {
                                if (HandshakeHelpers.ParseDeflateOptions(extension.AsSpan().TrimStart(), serverContextTakeover, serverMaxWindowBits, out var parsedOptions, out var response))
                                {
                                    Log.CompressionAccepted(_logger, response);
                                    deflateOptions = parsedOptions;
                                    // If more extension types are added, this would need to be a header append
                                    // and we wouldn't want to break out of the loop
                                    _context.Response.Headers.SecWebSocketExtensions = response;
                                    break;
                                }
                            }
                        }

                        if (deflateOptions is null)
                        {
                            Log.CompressionNotAccepted(_logger);
                        }
                    }
                }

                Stream opaqueTransport = await _upgradeFeature.UpgradeAsync(); // Sets status code to 101

                return(WebSocket.CreateFromStream(opaqueTransport, new WebSocketCreationOptions()
                {
                    IsServer = true,
                    KeepAliveInterval = keepAliveInterval,
                    SubProtocol = subProtocol,
                    DangerousDeflateOptions = deflateOptions
                }));
            }
예제 #25
0
 public Task <System.Net.WebSockets.WebSocket> AcceptAsync(WebSocketAcceptContext context)
 {
     throw new NotSupportedException("Use IWebSocketFeature.AcceptAsync() instead.");
 }
예제 #26
0
            Task<WebSocket> IHttpWebSocketFeature.AcceptAsync(WebSocketAcceptContext context)
            {
                Context.HttpContext.Response.StatusCode = 101; // Switching Protocols

                var websockets = TestWebSocket.CreatePair(context.SubProtocol);
                _clientWebSocketTcs.SetResult(websockets.Item1);
                _serverWebSocket = websockets.Item2;
                return Task.FromResult<WebSocket>(_serverWebSocket);
            }