예제 #1
0
        public override GenericLoopbackServer CreateServer(GenericLoopbackOptions options = null)
        {
            var loopbackServer = new LoopbackServer(CreateOptions(options));

            Task.WaitAll(loopbackServer.ListenAsync());
            return(loopbackServer);
        }
예제 #2
0
        private static Http2Options CreateOptions(GenericLoopbackOptions options)
        {
            Http2Options http2Options = new Http2Options();

            if (options != null)
            {
                http2Options.Address      = options.Address;
                http2Options.UseSsl       = options.UseSsl;
                http2Options.SslProtocols = options.SslProtocols;
            }
            return(http2Options);
        }
예제 #3
0
        public override GenericLoopbackServer CreateServer(GenericLoopbackOptions options = null)
        {
            Http2Options http2Options = new Http2Options();

            if (options != null)
            {
                http2Options.Address      = options.Address;
                http2Options.UseSsl       = options.UseSsl;
                http2Options.SslProtocols = options.SslProtocols;
            }

            return(Http2LoopbackServer.CreateServer(http2Options));
        }
        private static HttpAgnosticOptions CreateOptions(GenericLoopbackOptions options)
        {
            HttpAgnosticOptions httpOptions = new HttpAgnosticOptions();

            if (options != null)
            {
                httpOptions.Address       = options.Address;
                httpOptions.Certificate   = options.Certificate;
                httpOptions.UseSsl        = options.UseSsl;
                httpOptions.SslProtocols  = options.SslProtocols;
                httpOptions.ListenBacklog = options.ListenBacklog;
            }
            return(httpOptions);
        }
예제 #5
0
        private static Http3Options CreateOptions(GenericLoopbackOptions options)
        {
            if (options is Http3Options http3Options)
            {
                return(http3Options);
            }

            http3Options = new Http3Options();
            if (options != null)
            {
                http3Options.Address       = options.Address;
                http3Options.UseSsl        = options.UseSsl;
                http3Options.SslProtocols  = options.SslProtocols;
                http3Options.ListenBacklog = options.ListenBacklog;
            }
            return(http3Options);
        }
예제 #6
0
        public Http3LoopbackServer(GenericLoopbackOptions options = null)
        {
            options ??= new GenericLoopbackOptions();

            _cert = Configuration.Certificates.GetServerCertificate();

            var sslOpts = new SslServerAuthenticationOptions
            {
                EnabledSslProtocols  = options.SslProtocols,
                ApplicationProtocols = new List <SslApplicationProtocol> {
                    SslApplicationProtocol.Http3
                },
                ServerCertificate         = _cert,
                ClientCertificateRequired = false
            };

            _listener = new QuicListener(new IPEndPoint(options.Address, 0), sslOpts);
        }
예제 #7
0
 public override async Task <GenericLoopbackConnection> CreateConnectionAsync(SocketWrapper socket, Stream stream, GenericLoopbackOptions options = null)
 {
     return(await Http2LoopbackConnection.CreateAsync(socket, stream, CreateOptions(options)).ConfigureAwait(false));
 }
예제 #8
0
 public abstract Task <GenericLoopbackConnection> CreateConnectionAsync(Socket socket, Stream stream, GenericLoopbackOptions options = null);
예제 #9
0
 public abstract GenericLoopbackServer CreateServer(GenericLoopbackOptions options = null);
예제 #10
0
 public override Task <GenericLoopbackConnection> CreateConnectionAsync(Socket socket, Stream stream, GenericLoopbackOptions options = null)
 {
     // TODO: make a new overload that takes a MultiplexedConnection.
     // This method is always unacceptable to call for HTTP/3.
     throw new NotImplementedException("HTTP/3 does not operate over a Socket.");
 }
예제 #11
0
 public override async Task CreateServerAsync(Func <GenericLoopbackServer, Uri, Task> funcAsync, int millisecondsTimeout = 60000, GenericLoopbackOptions options = null)
 {
     using GenericLoopbackServer server = CreateServer(options);
     await funcAsync(server, server.Address).TimeoutAfter(millisecondsTimeout).ConfigureAwait(false);
 }
예제 #12
0
 public override Task <GenericLoopbackConnection> CreateConnectionAsync(Socket socket, Stream stream, GenericLoopbackOptions options = null)
 {
     // This method is always unacceptable to call for an agnostic server.
     throw new NotImplementedException("HttpAgnosticLoopbackServerFactory cannot create connection.");
 }
예제 #13
0
        public Http3LoopbackServer(QuicImplementationProvider quicImplementationProvider = null, GenericLoopbackOptions options = null)
        {
            options ??= new GenericLoopbackOptions();

            _cert = Configuration.Certificates.GetSelfSigned13ServerCertificate();

            var sslOpts = new SslServerAuthenticationOptions
            {
                EnabledSslProtocols  = options.SslProtocols,
                ApplicationProtocols = new List <SslApplicationProtocol> {
                    new SslApplicationProtocol("h3-29")
                },
                //ServerCertificate = _cert,
                ClientCertificateRequired = false
            };

            _listener = new QuicListener(quicImplementationProvider ?? QuicImplementationProviders.Default, new IPEndPoint(options.Address, 0), sslOpts);
            _listener.Start();
        }
예제 #14
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 == HttpVersion.Version11)
                {
                    return(connection = await Http11LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream, options).ConfigureAwait(false));
                }
                else if (_options.ClearTextVersion == HttpVersion.Version20)
                {
                    return(connection = await Http2LoopbackServerFactory.Singleton.CreateConnectionAsync(socket, stream, options).ConfigureAwait(false));
                }
                else
                {
                    throw new Exception($"Invalid ClearTextVersion={_options.ClearTextVersion} specified");
                }
            }
            catch
            {
                connection?.Dispose();
                connection = null;
                stream.Dispose();
                throw;
            }
            finally
            {
                if (connection != null)
                {
                    await connection.InitializeConnectionAsync().ConfigureAwait(false);
                }
            }
        }
예제 #15
0
 public override GenericLoopbackServer CreateServer(GenericLoopbackOptions options = null)
 {
     return(new LoopbackServer(CreateOptions(options)));
 }
예제 #16
0
 public override GenericLoopbackServer CreateServer(GenericLoopbackOptions options = null)
 {
     return(HttpAgnosticLoopbackServer.CreateServer(CreateOptions(options)));
 }
예제 #17
0
 public override GenericLoopbackServer CreateServer(GenericLoopbackOptions options = null)
 {
     return(new Http3LoopbackServer(_quicImplementationProvider, CreateOptions(options)));
 }
예제 #18
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);
                }
            }
        }
예제 #19
0
 public override async Task CreateServerAsync(Func <GenericLoopbackServer, Uri, Task> funcAsync, int millisecondsTimeout = 60000, GenericLoopbackOptions options = null)
 {
     using GenericLoopbackServer server = CreateServer(options);
     await funcAsync(server, server.Address).WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout));
 }