Exemplo n.º 1
0
 public void CompressionNegotiationProducesCorrectHeaderWithCustomOptions(string clientHeader, string expectedResponse)
 {
     Assert.True(HandshakeHelpers.ParseDeflateOptions(clientHeader.AsSpan(), serverContextTakeover: false, serverMaxWindowBits: 14,
                                                      out var _, out var response));
     Assert.Equal(expectedResponse, response);
 }
Exemplo n.º 2
0
 public void CompressionNegotiateNotAccepted(string clientHeader)
 {
     Assert.False(HandshakeHelpers.ParseDeflateOptions(clientHeader.AsSpan(), serverContextTakeover: true, serverMaxWindowBits: 15,
                                                       out var _, out var response));
 }
Exemplo n.º 3
0
        public async Task <WebSocket> AcceptAsync(WebSocketAcceptContext acceptContext)
        {
            if (!IsWebSocketRequest)
            {
                throw new InvalidOperationException("Not a WebSocket request.");
            }

            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;
                }
            }

            HandshakeHelpers.GenerateResponseHeaders(!_isH2WebSocket, _context.Request.Headers, 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;
            // HTTP/2
            if (_isH2WebSocket)
            {
                // Send the response headers
                opaqueTransport = await _connectFeature !.AcceptAsync();
            }
            // HTTP/1.1
            else
            {
                opaqueTransport = await _upgradeFeature !.UpgradeAsync(); // Sets status code to 101
            }

            return(WebSocket.CreateFromStream(opaqueTransport, new WebSocketCreationOptions()
            {
                IsServer = true,
                KeepAliveInterval = keepAliveInterval,
                SubProtocol = subProtocol,
                DangerousDeflateOptions = deflateOptions
            }));
        }