Exemplo n.º 1
0
        public override async Task <GenericLoopbackConnection> EstablishGenericConnectionAsync()
        {
            Socket socket = await _listenSocket.AcceptAsync().ConfigureAwait(false);

            Stream stream = new NetworkStream(socket, ownsSocket: true);

            var options = new GenericLoopbackOptions()
            {
                Address       = _options.Address,
                SslProtocols  = _options.SslProtocols,
                UseSsl        = false,
                ListenBacklog = _options.ListenBacklog
            };

            GenericLoopbackConnection connection = null;

            try
            {
                if (_options.UseSsl)
                {
                    var sslStream = new SslStream(stream, false, delegate { return(true); });

                    using (X509Certificate2 cert = Configuration.Certificates.GetServerCertificate())
                    {
                        SslServerAuthenticationOptions sslOptions = new SslServerAuthenticationOptions();

                        sslOptions.EnabledSslProtocols  = _options.SslProtocols;
                        sslOptions.ApplicationProtocols = _options.SslApplicationProtocols;
                        sslOptions.ServerCertificate    = cert;

                        await sslStream.AuthenticateAsServerAsync(sslOptions, CancellationToken.None).ConfigureAwait(false);
                    }

                    stream = sslStream;
                    if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2)
                    {
                        // Do not pass original options so the CreateConnectionAsync won't try to do ALPN again.
                        return(connection = await Http2LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream, options).ConfigureAwait(false));
                    }
                    if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http11 ||
                        sslStream.NegotiatedApplicationProtocol == default)
                    {
                        // Do not pass original options so the CreateConnectionAsync won't try to do ALPN again.
                        return(connection = await Http11LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream, options).ConfigureAwait(false));
                    }
                    else
                    {
                        throw new Exception($"Unsupported negotiated protocol {sslStream.NegotiatedApplicationProtocol}");
                    }
                }

                if (_options.ClearTextVersion is null)
                {
                    throw new Exception($"HTTP server does not accept clear text connections, either set '{nameof(HttpAgnosticOptions.UseSsl)}' or set up '{nameof(HttpAgnosticOptions.ClearTextVersion)}' in server options.");
                }

                var buffer   = new byte[24];
                var position = 0;
                while (position < buffer.Length)
                {
                    var readBytes = await stream.ReadAsync(buffer, position, buffer.Length - position).ConfigureAwait(false);

                    if (readBytes == 0)
                    {
                        break;
                    }
                    position += readBytes;
                }

                var memory = new Memory <byte>(buffer, 0, position);
                stream = new ReturnBufferStream(stream, memory);

                var prefix = Text.Encoding.ASCII.GetString(memory.Span);
                if (prefix == Http2LoopbackConnection.Http2Prefix)
                {
                    if (_options.ClearTextVersion == HttpVersion.Version20 || _options.ClearTextVersion == HttpVersion.Unknown)
                    {
                        return(connection = await Http2LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream, options).ConfigureAwait(false));
                    }
                }
                else
                {
                    if (_options.ClearTextVersion == HttpVersion.Version11 || _options.ClearTextVersion == HttpVersion.Unknown)
                    {
                        return(connection = await Http11LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream, options).ConfigureAwait(false));
                    }
                }

                throw new Exception($"HTTP/{_options.ClearTextVersion} server cannot establish connection due to unexpected data: '{prefix}'");
            }
            catch
            {
                connection?.Dispose();
                connection = null;
                stream.Dispose();
                throw;
            }
            finally
            {
                if (connection != null)
                {
                    await connection.InitializeConnectionAsync().ConfigureAwait(false);
                }
            }
        }
Exemplo n.º 2
0
        public override async Task <GenericLoopbackConnection> EstablishGenericConnectionAsync()
        {
            Socket socket = await _listenSocket.AcceptAsync().ConfigureAwait(false);

            Stream stream = new NetworkStream(socket, ownsSocket: true);

            if (_options.UseSsl)
            {
                var sslStream = new SslStream(stream, false, delegate { return(true); });

                using (X509Certificate2 cert = Configuration.Certificates.GetServerCertificate())
                {
                    SslServerAuthenticationOptions options = new SslServerAuthenticationOptions();

                    options.EnabledSslProtocols = _options.SslProtocols;

                    var protocols = new List <SslApplicationProtocol>();
                    protocols.Add(SslApplicationProtocol.Http11);
                    protocols.Add(SslApplicationProtocol.Http2);
                    options.ApplicationProtocols = protocols;

                    options.ServerCertificate = cert;

                    await sslStream.AuthenticateAsServerAsync(options, CancellationToken.None).ConfigureAwait(false);
                }

                stream = sslStream;
                if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http2)
                {
                    // Do not pass original options so the CreateConnectionAsync won't try to do ALPN again.
                    return(await Http2LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream));
                }
                if (sslStream.NegotiatedApplicationProtocol == SslApplicationProtocol.Http11)
                {
                    // Do not pass original options so the CreateConnectionAsync won't try to do ALPN again.
                    return(await Http11LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream));
                }
                throw new Exception($"Unsupported negotiated protocol {sslStream.NegotiatedApplicationProtocol}");
            }

            var buffer   = new byte[24];
            var position = 0;

            while (position < buffer.Length)
            {
                var readBytes = await stream.ReadAsync(buffer, position, buffer.Length - position).ConfigureAwait(false);

                if (readBytes == 0)
                {
                    break;
                }
                position += readBytes;
            }

            var memory = new Memory <byte>(buffer, 0, position);

            stream = new ReturnBufferStream(stream, memory);

            var prefix = Text.Encoding.ASCII.GetString(memory.Span);

            if (prefix == Http2LoopbackConnection.Http2Prefix)
            {
                if (_options.ClearTextVersion == HttpVersion.Version20 || _options.ClearTextVersion == HttpVersion.Unknown)
                {
                    return(await Http2LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream));
                }
            }
            else
            {
                if (_options.ClearTextVersion == HttpVersion.Version11 || _options.ClearTextVersion == HttpVersion.Unknown)
                {
                    return(await Http11LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream));
                }
            }

            throw new Exception($"HTTP/{_options.ClearTextVersion} server cannot establish connection due to unexpected data: '{prefix}'");
        }