Example #1
0
        public Http3LoopbackServer(Http3Options options = null)
        {
            options ??= new Http3Options();

            _cert = Configuration.Certificates.GetServerCertificate();

            var listenerOptions = new QuicListenerOptions()
            {
                ListenEndPoint = new IPEndPoint(options.Address, 0),
                ServerAuthenticationOptions = new SslServerAuthenticationOptions
                {
                    EnabledSslProtocols  = options.SslProtocols,
                    ApplicationProtocols = new List <SslApplicationProtocol>
                    {
                        new SslApplicationProtocol(options.Alpn)
                    },
                    ServerCertificate         = _cert,
                    ClientCertificateRequired = false
                },
                MaxUnidirectionalStreams = options.MaxUnidirectionalStreams,
                MaxBidirectionalStreams  = options.MaxBidirectionalStreams,
            };

            ValueTask <QuicListener> valueTask = QuicListener.ListenAsync(listenerOptions);

            Debug.Assert(valueTask.IsCompleted);
            _listener = valueTask.Result;
        }
Example #2
0
        protected override async Task <StreamPair> CreateConnectedStreamsAsync()
        {
            var listener = await QuicListener.ListenAsync(new QuicListenerOptions()
            {
                ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0),
                ServerAuthenticationOptions = GetSslServerAuthenticationOptions()
            });

            byte[] buffer = new byte[1] {
                42
            };
            QuicConnection connection1 = null, connection2 = null;
            QuicStream     stream1 = null, stream2 = null;

            await WhenAllOrAnyFailed(
                Task.Run(async() =>
            {
                connection1 = await listener.AcceptConnectionAsync();
                stream1     = await connection1.AcceptStreamAsync();
                Assert.Equal(1, await stream1.ReadAsync(buffer));
            }),
                Task.Run(async() =>
            {
                try
                {
                    connection2 = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions()
                    {
                        RemoteEndPoint = listener.ListenEndPoint,
                        ClientAuthenticationOptions = GetSslClientAuthenticationOptions()
                    });
                    await connection2.ConnectAsync();
                    stream2 = await connection2.OpenBidirectionalStreamAsync();
                    // OpenBidirectionalStream only allocates ID. We will force stream opening
                    // by Writing there and receiving data on the other side.
                    await stream2.WriteAsync(buffer);
                }
                catch (Exception ex)
                {
                    _output?.WriteLine($"Failed to {ex.Message}");
                    throw;
                }
            }));

            // No need to keep the listener once we have connected connection and streams
            listener.Dispose();

            var result = new StreamPairWithOtherDisposables(stream1, stream2);

            result.Disposables.Add(connection1);
            result.Disposables.Add(connection2);

            return(result);
        }
    public async ValueTask CreateListenerAsync()
    {
        QuicLog.ConnectionListenerStarting(_log, _quicListenerOptions.ListenEndPoint);

        try
        {
            _listener = await QuicListener.ListenAsync(_quicListenerOptions);
        }
        catch (QuicException ex) when(ex.QuicError == QuicError.AddressInUse)
        {
            throw new AddressInUseException(ex.Message, ex);
        }

        // EndPoint could be configured with an ephemeral port of 0.
        // Listener endpoint will resolve an ephemeral port, e.g. 127.0.0.1:0, into the actual port
        // so we need to update the public listener endpoint property.
        EndPoint = _listener.LocalEndPoint;
    }
Example #4
0
        public Http3LoopbackServer(Http3Options options = null)
        {
            options ??= new Http3Options();

            _cert = options.Certificate ?? Configuration.Certificates.GetServerCertificate();

            var listenerOptions = new QuicListenerOptions()
            {
                ListenEndPoint       = new IPEndPoint(options.Address, 0),
                ApplicationProtocols = new List <SslApplicationProtocol>
                {
                    new SslApplicationProtocol(options.Alpn)
                },
                ConnectionOptionsCallback = (_, _, _) =>
                {
                    var serverOptions = new QuicServerConnectionOptions()
                    {
                        DefaultStreamErrorCode          = Http3LoopbackConnection.H3_REQUEST_CANCELLED,
                        DefaultCloseErrorCode           = Http3LoopbackConnection.H3_NO_ERROR,
                        MaxInboundBidirectionalStreams  = options.MaxInboundBidirectionalStreams,
                        MaxInboundUnidirectionalStreams = options.MaxInboundUnidirectionalStreams,
                        ServerAuthenticationOptions     = new SslServerAuthenticationOptions
                        {
                            EnabledSslProtocols  = options.SslProtocols,
                            ApplicationProtocols = new List <SslApplicationProtocol>
                            {
                                new SslApplicationProtocol(options.Alpn)
                            },
                            ServerCertificate         = _cert,
                            ClientCertificateRequired = false
                        }
                    };
                    return(ValueTask.FromResult(serverOptions));
                }
            };

            ValueTask <QuicListener> valueTask = QuicListener.ListenAsync(listenerOptions);

            Debug.Assert(valueTask.IsCompleted);
            _listener = valueTask.Result;
        }
        protected override async Task <StreamPair> CreateConnectedStreamsAsync()
        {
            var listener = await QuicListener.ListenAsync(new QuicListenerOptions()
            {
                ListenEndPoint       = new IPEndPoint(IPAddress.Loopback, 0),
                ApplicationProtocols = new List <SslApplicationProtocol>()
                {
                    new SslApplicationProtocol("quictest")
                },
                ConnectionOptionsCallback = (_, _, _) => ValueTask.FromResult(new QuicServerConnectionOptions()
                {
                    DefaultStreamErrorCode      = QuicTestBase.DefaultStreamErrorCodeServer,
                    DefaultCloseErrorCode       = QuicTestBase.DefaultCloseErrorCodeServer,
                    ServerAuthenticationOptions = GetSslServerAuthenticationOptions()
                })
            });

            byte[] buffer = new byte[1] {
                42
            };
            QuicConnection connection1 = null, connection2 = null;
            QuicStream     stream1 = null, stream2 = null;

            try
            {
                await WhenAllOrAnyFailed(
                    Task.Run(async() =>
                {
                    connection1 = await listener.AcceptConnectionAsync();
                    stream1     = await connection1.AcceptInboundStreamAsync();
                    Assert.Equal(1, await stream1.ReadAsync(buffer));
                }),
                    Task.Run(async() =>
                {
                    try
                    {
                        connection2 = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions()
                        {
                            DefaultStreamErrorCode      = QuicTestBase.DefaultStreamErrorCodeClient,
                            DefaultCloseErrorCode       = QuicTestBase.DefaultCloseErrorCodeClient,
                            RemoteEndPoint              = listener.LocalEndPoint,
                            ClientAuthenticationOptions = GetSslClientAuthenticationOptions()
                        });
                        stream2 = await connection2.OpenOutboundStreamAsync(QuicStreamType.Bidirectional);
                        // OpenBidirectionalStream only allocates ID. We will force stream opening
                        // by Writing there and receiving data on the other side.
                        await stream2.WriteAsync(buffer);
                    }
                    catch (Exception ex)
                    {
                        _output?.WriteLine($"Failed to {ex.Message}");
                        throw;
                    }
                }));

                // No need to keep the listener once we have connected connection and streams
                await listener.DisposeAsync();

                var result = new StreamPairWithOtherDisposables(stream1, stream2);
                result.Disposables.Add(connection1);
                result.Disposables.Add(connection2);

                return(result);
            }
            catch
            {
                if (stream1 is not null)
                {
                    await stream1.DisposeAsync();
                }
                if (stream2 is not null)
                {
                    await stream2.DisposeAsync();
                }
                if (connection1 is not null)
                {
                    await connection1.DisposeAsync();
                }
                if (connection2 is not null)
                {
                    await connection2.DisposeAsync();
                }
                throw;
            }
        }