Ejemplo n.º 1
0
        public async Task BasicTest()
        {
            using QuicListener listener = CreateQuicListener();

            for (int i = 0; i < 100; i++)
            {
                Task listenTask = Task.Run(async() =>
                {
                    using QuicConnection connection = await listener.AcceptConnectionAsync();
                    await using QuicStream stream   = await connection.AcceptStreamAsync();

                    byte[] buffer = new byte[s_data.Length];
                    int bytesRead = await stream.ReadAsync(buffer);

                    Assert.Equal(s_data.Length, bytesRead);
                    Assert.True(s_data.Span.SequenceEqual(buffer));

                    await stream.WriteAsync(s_data, endStream: true);
                    await stream.ShutdownWriteCompleted();

                    await connection.CloseAsync(errorCode: 0);
                });

                Task clientTask = Task.Run(async() =>
                {
                    using QuicConnection connection = CreateQuicConnection(listener.ListenEndPoint);
                    await connection.ConnectAsync();
                    await using QuicStream stream = connection.OpenBidirectionalStream();

                    await stream.WriteAsync(s_data, endStream: true);

                    byte[] memory = new byte[12];
                    int bytesRead = await stream.ReadAsync(memory);

                    Assert.Equal(s_data.Length, bytesRead);
                    // TODO this failed once...
                    Assert.True(s_data.Span.SequenceEqual(memory));
                    await stream.ShutdownWriteCompleted();

                    await connection.CloseAsync(errorCode: 0);
                });

                await(new[] { listenTask, clientTask }).WhenAllOrAnyFailed(millisecondsTimeout: 10000);
            }
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
    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;
    }
Ejemplo n.º 4
0
        public static async Task <int> RunServer(IPEndPoint listenEp, string certificateFile, string privateKeyFile, CancellationToken token)
        {
            using QuicListener listener = new QuicListener(new QuicListenerOptions
            {
                ListenEndPoint              = listenEp,
                CertificateFilePath         = certificateFile,
                PrivateKeyFilePath          = privateKeyFile,
                ServerAuthenticationOptions = new SslServerAuthenticationOptions
                {
                    ApplicationProtocols = new List <SslApplicationProtocol>
                    {
                        new SslApplicationProtocol("echo")
                    }
                }
            });

            // QuicListener must be started before accepting connections.
            listener.Start();

            // tasks that need to be awaited when trying to exit gracefully
            List <Task> tasks = new List <Task>();

            try
            {
                QuicConnection conn;
                while ((conn = await listener.AcceptConnectionAsync(token)) != null)
                {
                    // copy the connection into a variable with narrower scope so
                    // that it is not shared among multiple lambdas
                    QuicConnection captured = conn;
                    var            task     = Task.Run(
                        () => HandleServerConnection(captured, token));
                    tasks.Add(task);
                }
            }
            finally
            {
                // wait until all connections are closed
                await Task.WhenAll(tasks);
            }

            return(0);
        }
Ejemplo n.º 5
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();
        }
Ejemplo n.º 6
0
    /// <summary>
    /// Creates a new <see cref="QuicListener"/> and starts listening for new connections.
    /// </summary>
    /// <param name="options">Options for the listener.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
    /// <returns>An asynchronous task that completes with the started listener.</returns>
    public static ValueTask <QuicListener> ListenAsync(QuicListenerOptions options, CancellationToken cancellationToken = default)
    {
        if (!IsSupported)
        {
            throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported);
        }

        // Validate and fill in defaults for the options.
        options.Validate(nameof(options));

        QuicListener listener = new QuicListener(options);

        if (NetEventSource.Log.IsEnabled())
        {
            NetEventSource.Info(listener, $"{listener} Listener listens on {listener.LocalEndPoint}");
        }

        return(ValueTask.FromResult(listener));
    }
        protected override async Task <StreamPair> CreateConnectedStreamsAsync()
        {
            QuicImplementationProvider provider = Provider;
            var protocol = new SslApplicationProtocol("quictest");

            var listener = new QuicListener(
                provider,
                new IPEndPoint(IPAddress.Loopback, 0),
                GetSslServerAuthenticationOptions());

            QuicConnection connection1 = null, connection2 = null;
            QuicStream     stream1 = null, stream2 = null;

            await WhenAllOrAnyFailed(
                Task.Run(async() =>
            {
                connection1 = await listener.AcceptConnectionAsync();
                stream1     = await connection1.AcceptStreamAsync();
            }),
                Task.Run(async() =>
            {
                connection2 = new QuicConnection(
                    provider,
                    listener.ListenEndPoint,
                    new SslClientAuthenticationOptions()
                {
                    ApplicationProtocols = new List <SslApplicationProtocol>()
                    {
                        protocol
                    }
                });
                await connection2.ConnectAsync();
                stream2 = connection2.OpenBidirectionalStream();
            }));

            var result = new StreamPairWithOtherDisposables(stream1, stream2);

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

            return(result);
        }
Ejemplo n.º 8
0
        public async Task TestStreams()
        {
            using (QuicListener listener = new QuicListener(
                       QuicImplementationProviders.MsQuic,
                       new IPEndPoint(IPAddress.Loopback, 0),
                       GetSslServerAuthenticationOptions()))
            {
                listener.Start();
                IPEndPoint listenEndPoint = listener.ListenEndPoint;

                using (QuicConnection clientConnection = new QuicConnection(
                           QuicImplementationProviders.MsQuic,
                           listenEndPoint,
                           sslClientAuthenticationOptions: new SslClientAuthenticationOptions {
                    ApplicationProtocols = new List <SslApplicationProtocol>()
                    {
                        new SslApplicationProtocol("quictest")
                    }
                }))
                {
                    Assert.False(clientConnection.Connected);
                    Assert.Equal(listenEndPoint, clientConnection.RemoteEndPoint);

                    ValueTask      connectTask      = clientConnection.ConnectAsync();
                    QuicConnection serverConnection = await listener.AcceptConnectionAsync();

                    await connectTask;

                    Assert.True(clientConnection.Connected);
                    Assert.True(serverConnection.Connected);
                    Assert.Equal(listenEndPoint, serverConnection.LocalEndPoint);
                    Assert.Equal(listenEndPoint, clientConnection.RemoteEndPoint);
                    Assert.Equal(clientConnection.LocalEndPoint, serverConnection.RemoteEndPoint);

                    await CreateAndTestBidirectionalStream(clientConnection, serverConnection);
                    await CreateAndTestBidirectionalStream(serverConnection, clientConnection);
                    await CreateAndTestUnidirectionalStream(serverConnection, clientConnection);
                    await CreateAndTestUnidirectionalStream(clientConnection, serverConnection);

                    await clientConnection.CloseAsync();
                }
            }
        }
Ejemplo n.º 9
0
        public async Task UntrustedClientCertificateFails()
        {
            var listenerOptions = new QuicListenerOptions();

            listenerOptions.ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0);
            listenerOptions.ServerAuthenticationOptions = GetSslServerAuthenticationOptions();
            listenerOptions.ServerAuthenticationOptions.ClientCertificateRequired           = true;
            listenerOptions.ServerAuthenticationOptions.RemoteCertificateValidationCallback = (sender, cert, chain, errors) =>
            {
                return(false);
            };

            using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, listenerOptions);
            QuicClientConnectionOptions clientOptions = CreateQuicClientOptions();

            clientOptions.RemoteEndPoint = listener.ListenEndPoint;
            clientOptions.ClientAuthenticationOptions.ClientCertificates = new X509CertificateCollection()
            {
                ClientCertificate
            };
            QuicConnection clientConnection = CreateQuicConnection(clientOptions);

            using CancellationTokenSource cts = new CancellationTokenSource();
            cts.CancelAfter(500); //Some delay to see if we would get failed connection.
            Task <QuicConnection> serverTask = listener.AcceptConnectionAsync(cts.Token).AsTask();

            ValueTask t = clientConnection.ConnectAsync(cts.Token);

            t.AsTask().Wait(PassingTestTimeout);
            await Assert.ThrowsAsync <OperationCanceledException>(() => serverTask);

            // The task will likely succed but we don't really care.
            // It may fail if the server aborts quickly.
            try
            {
                await t;
            }
            catch (Exception ex)
            {
                _output.WriteLine($"Ignored exception:{Environment.NewLine}{ex}");
            }
        }
Ejemplo n.º 10
0
        // RunAsync starts the QuicListener and continually waits for new clients
        public override async Task RunAsync(CancellationToken Token)
        {
            // Start the QuicListener
            QuicListener listener = new QuicListener(this.ExternalPort);

            //QuicListener Listener = new QuicListener(IPAddress.Any, this.ExternalPort);;
            listener.Start();

            // Continually wait for new client
            while (!Token.IsCancellationRequested)
            {
                // Handle the client asynchronously in a new thread
                QuicConnection client = listener.AcceptQuicClient();
                _ = Task.Run(() =>
                {
                    //client.ReceiveTimeout = client.SendTimeout = 0;
                    QuicStream stream = client.CreateStream(QuickNet.Utilities.StreamType.ClientBidirectional);
                    //stream.
                    //stream.ReadTimeout = stream.WriteTimeout = Timeout.Infinite;
                    while (!Token.IsCancellationRequested)
                    {
                        // byte[] data;
                        // Read from the implant
                        string read            = "";
                        client.OnDataReceived += (c) =>
                        {
                            read += Encoding.UTF8.GetString(c.Data);
                        };
                        //string read = Encoding.UTF8.GetString(data);
                        //string read = await Utilities.ReadStreamAsync(stream);
                        // Write to the Covenant server
                        string guid = this.WriteToConnector(read);
                        if (guid != null)
                        {
                            // Track this GUID -> client mapping, for use within the OnReadBridge function

                            Clients.TryAdd(guid, stream);
                        }
                    }
                });
            }
        }
Ejemplo n.º 11
0
        public static (IPEndPoint listenEp, Task finished) StartQuic(IPEndPoint endpoint, string certPath, string keyPath,
                                                                     CancellationToken cancellationToken)
        {
            TaskCompletionSource completionSource = new TaskCompletionSource();

            var options = new QuicListenerOptions
            {
                CertificateFilePath         = certPath,
                PrivateKeyFilePath          = keyPath,
                ListenEndPoint              = endpoint,
                ServerAuthenticationOptions = new SslServerAuthenticationOptions
                {
                    ApplicationProtocols = new List <SslApplicationProtocol>
                    {
                        Helpers.AlpnProtocol
                    }
                },
                MaxBidirectionalStreams = 1024
            };

            var listener = new QuicListener(options);

            listener.Start();

            List <Task> currentConnectionTasks = new List <Task>();

            Helpers.Dispatch(async() =>
            {
                while (true)
                {
                    var connection = await listener.AcceptConnectionAsync().ConfigureAwait(false);
                    Helpers.Trace("New connection");
                    var task = Helpers.Dispatch(() => ServerConnectionTask(connection, cancellationToken));
                    currentConnectionTasks.Add(task);
                }
            });

            cancellationToken.Register(() =>
                                       Task.WhenAll(currentConnectionTasks).ContinueWith(_ => completionSource.SetResult()));

            return(listener.ListenEndPoint, completionSource.Task);
        }
Ejemplo n.º 12
0
        public async Task CertificateCallbackThrowPropagates()
        {
            using CancellationTokenSource cts = new CancellationTokenSource(PassingTestTimeout);
            X509Certificate?receivedCertificate = null;
            bool            validationResult    = false;

            var listenerOptions = new QuicListenerOptions();

            listenerOptions.ListenEndPoint = new IPEndPoint(Socket.OSSupportsIPv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback, 0);
            listenerOptions.ServerAuthenticationOptions = GetSslServerAuthenticationOptions();
            using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, listenerOptions);

            QuicClientConnectionOptions clientOptions = CreateQuicClientOptions();

            clientOptions.RemoteEndPoint = listener.ListenEndPoint;
            clientOptions.ClientAuthenticationOptions.RemoteCertificateValidationCallback = (sender, cert, chain, errors) =>
            {
                receivedCertificate = cert;
                if (validationResult)
                {
                    return(validationResult);
                }

                throw new ArithmeticException("foobar");
            };

            clientOptions.ClientAuthenticationOptions.TargetHost = "foobar1";
            QuicConnection clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, clientOptions);

            await Assert.ThrowsAsync <ArithmeticException>(() => clientConnection.ConnectAsync(cts.Token).AsTask());

            Assert.Equal(listenerOptions.ServerAuthenticationOptions.ServerCertificate, receivedCertificate);
            clientConnection.Dispose();

            // Make sure the listner is still usable and there is no lingering bad conenction
            validationResult = true;
            (clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(listener);
            await PingPong(clientConnection, serverConnection);

            clientConnection.Dispose();
            serverConnection.Dispose();
        }
Ejemplo n.º 13
0
        protected override async Task <StreamPair> CreateConnectedStreamsAsync()
        {
            QuicImplementationProvider provider = Provider;
            var listener = new QuicListener(
                provider,
                new IPEndPoint(IPAddress.Loopback, 0),
                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() =>
            {
                connection2 = new QuicConnection(
                    provider,
                    listener.ListenEndPoint,
                    GetSslClientAuthenticationOptions());
                await connection2.ConnectAsync();
                stream2 = connection2.OpenBidirectionalStream();
                // OpenBidirectionalStream only allocates ID. We will force stream opening
                // by Writing there and receiving data on the other side.
                await stream2.WriteAsync(buffer);
            }));

            var result = new StreamPairWithOtherDisposables(stream1, stream2);

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

            return(result);
        }
Ejemplo n.º 14
0
        public QuicServerListener(QuicListener quicListener, QuicServerTransport quicServerTransport, bool isLspHooked)
        {
            if (quicListener == null)
            {
                throw new ArgumentNullException(nameof(quicListener));
            }

            if (quicServerTransport == null)
            {
                throw new ArgumentNullException(nameof(quicServerTransport));
            }

            this.lspHooked = isLspHooked;

            this.listener = quicListener;

            this.server = quicServerTransport;

            this.thread = new ThreadManager(AcceptLoop, Unblock);
        }
Ejemplo n.º 15
0
        static void Main(string[] args)
        {
            Console.WriteLine("Server");
            QuicListener listener = new QuicListener(18000);

            listener.Start();
            while (true)
            {
                // Blocks while waiting for a connection
                QuicConnection client = listener.AcceptQuicClient();

                // Assign an action when a data is received from that client.
                client.OnDataReceived += (c) => {
                    byte[] data = c.Data;
                    Console.WriteLine("Data received: " + Encoding.UTF8.GetString(data));
                    // Echo back data to the client
                    c.Send(Encoding.UTF8.GetBytes("Echo!"));
                };
            }
        }
Ejemplo n.º 16
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;
        }
Ejemplo n.º 17
0
    public QuicConnectionListener(QuicTransportOptions options, ILogger log, EndPoint endpoint, SslServerAuthenticationOptions sslServerAuthenticationOptions)
    {
        if (!QuicImplementationProviders.Default.IsSupported)
        {
            throw new NotSupportedException("QUIC is not supported or enabled on this platform. See https://aka.ms/aspnet/kestrel/http3reqs for details.");
        }

        _log     = log;
        _context = new QuicTransportContext(_log, options);
        var quicListenerOptions = new QuicListenerOptions();

        var listenEndPoint = endpoint as IPEndPoint;

        if (listenEndPoint == null)
        {
            throw new InvalidOperationException($"QUIC doesn't support listening on the configured endpoint type. Expected {nameof(IPEndPoint)} but got {endpoint.GetType().Name}.");
        }

        // Workaround for issue in System.Net.Quic
        // https://github.com/dotnet/runtime/issues/57241
        if (listenEndPoint.Address.Equals(IPAddress.Any) && listenEndPoint.Address != IPAddress.Any)
        {
            listenEndPoint = new IPEndPoint(IPAddress.Any, listenEndPoint.Port);
        }
        if (listenEndPoint.Address.Equals(IPAddress.IPv6Any) && listenEndPoint.Address != IPAddress.IPv6Any)
        {
            listenEndPoint = new IPEndPoint(IPAddress.IPv6Any, listenEndPoint.Port);
        }

        quicListenerOptions.ServerAuthenticationOptions = sslServerAuthenticationOptions;
        quicListenerOptions.ListenEndPoint           = listenEndPoint;
        quicListenerOptions.IdleTimeout              = options.IdleTimeout;
        quicListenerOptions.MaxBidirectionalStreams  = options.MaxBidirectionalStreamCount;
        quicListenerOptions.MaxUnidirectionalStreams = options.MaxUnidirectionalStreamCount;
        quicListenerOptions.ListenBacklog            = options.Backlog;

        _listener = new QuicListener(quicListenerOptions);

        // Listener endpoint will resolve an ephemeral port, e.g. 127.0.0.1:0, into the actual port.
        EndPoint = _listener.ListenEndPoint;
    }
Ejemplo n.º 18
0
        public async Task ConnectWithClientCertificate()
        {
            bool clientCertificateOK = false;

            var listenerOptions = new QuicListenerOptions();

            listenerOptions.ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0);
            listenerOptions.ServerAuthenticationOptions = GetSslServerAuthenticationOptions();
            listenerOptions.ServerAuthenticationOptions.ClientCertificateRequired           = true;
            listenerOptions.ServerAuthenticationOptions.RemoteCertificateValidationCallback = (sender, cert, chain, errors) =>
            {
                _output.WriteLine("client certificate {0}", cert);
                Assert.NotNull(cert);
                Assert.Equal(ClientCertificate.Thumbprint, ((X509Certificate2)cert).Thumbprint);

                clientCertificateOK = true;
                return(true);
            };

            using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, listenerOptions);
            QuicClientConnectionOptions clientOptions = CreateQuicClientOptions();

            clientOptions.ClientAuthenticationOptions.ClientCertificates = new X509CertificateCollection()
            {
                ClientCertificate
            };
            (QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(clientOptions, listener);

            // Verify functionality of the connections.
            await PingPong(clientConnection, serverConnection);

            // check we completed the client certificate verification.
            Assert.True(clientCertificateOK);
            Assert.Equal(ClientCertificate, serverConnection.RemoteCertificate);

            await serverConnection.CloseAsync(0);

            clientConnection.Dispose();
            serverConnection.Dispose();
        }
Ejemplo n.º 19
0
        public async Task ConnectWithCertificateChain()
        {
            (X509Certificate2 certificate, X509Certificate2Collection chain) = System.Net.Security.Tests.TestHelper.GenerateCertificates("localhost", longChain: true);
            X509Certificate2 rootCA = chain[chain.Count - 1];

            var quicOptions = new QuicListenerOptions();

            quicOptions.ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0);
            quicOptions.ServerAuthenticationOptions = GetSslServerAuthenticationOptions();
            quicOptions.ServerAuthenticationOptions.ServerCertificateContext = SslStreamCertificateContext.Create(certificate, chain);
            quicOptions.ServerAuthenticationOptions.ServerCertificate        = null;

            using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, quicOptions);

            QuicClientConnectionOptions options = new QuicClientConnectionOptions()
            {
                RemoteEndPoint = listener.ListenEndPoint,
                ClientAuthenticationOptions = GetSslClientAuthenticationOptions(),
            };

            options.ClientAuthenticationOptions.RemoteCertificateValidationCallback = (sender, cert, chain, errors) =>
            {
                Assert.Equal(certificate.Subject, cert.Subject);
                Assert.Equal(certificate.Issuer, cert.Issuer);
                // We should get full chain without root CA.
                // With trusted root, we should be able to build chain.
                chain.ChainPolicy.CustomTrustStore.Add(rootCA);
                chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
                Assert.True(chain.Build(certificate));

                return(true);
            };

            using QuicConnection clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options);
            ValueTask clientTask = clientConnection.ConnectAsync();

            using QuicConnection serverConnection = await listener.AcceptConnectionAsync();

            await clientTask;
        }
Ejemplo n.º 20
0
        static void Example()
        {
            QuicListener listener = new QuicListener(11000);

            listener.Start();

            while (true)
            {
                // Blocks while waiting for a connection
                QuicConnection client = listener.AcceptQuicClient();

                // Assign an action when a data is received from that client.
                client.OnDataReceived += (c) => {
                    byte[] data = c.Data;

                    Console.WriteLine("Data received: " + Encoding.UTF8.GetString(data));

                    c.Send(Encoding.UTF8.GetBytes("Echo!"));
                    c.Send(Encoding.UTF8.GetBytes("Echo2!"));
                };
            }
        }
Ejemplo n.º 21
0
        public async Task UnidirectionalAndBidirectionalChangeValues()
        {
            using QuicListener listener = CreateQuicListener();

            QuicClientConnectionOptions options = new QuicClientConnectionOptions()
            {
                MaxBidirectionalStreams = 10,
                MaxUnidirectionalStreams = 20,
                RemoteEndPoint = listener.ListenEndPoint,
                ClientAuthenticationOptions = GetSslClientAuthenticationOptions()
            };

            using QuicConnection clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options);

            ValueTask clientTask = clientConnection.ConnectAsync();
            using QuicConnection serverConnection = await listener.AcceptConnectionAsync();
            await clientTask;
            Assert.Equal(20, clientConnection.GetRemoteAvailableUnidirectionalStreamCount());
            Assert.Equal(10, clientConnection.GetRemoteAvailableBidirectionalStreamCount());
            Assert.Equal(100, serverConnection.GetRemoteAvailableBidirectionalStreamCount());
            Assert.Equal(100, serverConnection.GetRemoteAvailableUnidirectionalStreamCount());
        }
Ejemplo n.º 22
0
        public QuicConnectionListener(QuicTransportOptions options, IQuicTrace log, EndPoint endpoint, SslServerAuthenticationOptions sslServerAuthenticationOptions)
        {
            if (!QuicImplementationProviders.Default.IsSupported)
            {
                throw new NotSupportedException("QUIC is not supported or enabled on this platform. See https://aka.ms/aspnet/kestrel/http3reqs for details.");
            }

            _log     = log;
            _context = new QuicTransportContext(_log, options);
            var quicListenerOptions = new QuicListenerOptions();

            quicListenerOptions.ServerAuthenticationOptions = sslServerAuthenticationOptions;
            quicListenerOptions.ListenEndPoint           = endpoint as IPEndPoint;
            quicListenerOptions.IdleTimeout              = options.IdleTimeout;
            quicListenerOptions.MaxBidirectionalStreams  = options.MaxBidirectionalStreamCount;
            quicListenerOptions.MaxUnidirectionalStreams = options.MaxUnidirectionalStreamCount;

            _listener = new QuicListener(quicListenerOptions);

            // Listener endpoint will resolve an ephemeral port, e.g. 127.0.0.1:0, into the actual port.
            EndPoint = _listener.ListenEndPoint;
        }
Ejemplo n.º 23
0
        public async Task CertificateCallbackThrowPropagates()
        {
            using CancellationTokenSource cts = new CancellationTokenSource(PassingTestTimeout);
            X509Certificate?receivedCertificate = null;

            var quicOptions = new QuicListenerOptions();

            quicOptions.ListenEndPoint = new IPEndPoint(Socket.OSSupportsIPv6 ? IPAddress.IPv6Loopback : IPAddress.Loopback, 0);
            quicOptions.ServerAuthenticationOptions = GetSslServerAuthenticationOptions();

            using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, quicOptions);

            QuicClientConnectionOptions options = new QuicClientConnectionOptions()
            {
                RemoteEndPoint = listener.ListenEndPoint,
                ClientAuthenticationOptions = GetSslClientAuthenticationOptions(),
            };

            options.ClientAuthenticationOptions.RemoteCertificateValidationCallback = (sender, cert, chain, errors) =>
            {
                receivedCertificate = cert;
                throw new ArithmeticException("foobar");
            };

            options.ClientAuthenticationOptions.TargetHost = "foobar1";

            QuicConnection clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options);

            Task <QuicConnection> serverTask = listener.AcceptConnectionAsync(cts.Token).AsTask();
            await Assert.ThrowsAsync <ArithmeticException>(() => clientConnection.ConnectAsync(cts.Token).AsTask());

            QuicConnection serverConnection = await serverTask;

            Assert.Equal(quicOptions.ServerAuthenticationOptions.ServerCertificate, receivedCertificate);

            clientConnection.Dispose();
            serverConnection.Dispose();
        }
Ejemplo n.º 24
0
        public async Task TestStreams()
        {
            using QuicListener listener = new QuicListener(
                      QuicImplementationProviders.MsQuic,
                      new IPEndPoint(IPAddress.Loopback, 0),
                      GetSslServerAuthenticationOptions());

            listener.Start();
            IPEndPoint listenEndPoint = listener.ListenEndPoint;

            Assert.NotEqual(0, listenEndPoint.Port);

            using QuicConnection clientConnection = new QuicConnection(
                      QuicImplementationProviders.MsQuic,
                      listenEndPoint,
                      GetSslClientAuthenticationOptions());

            Assert.False(clientConnection.Connected);
            Assert.Equal(listenEndPoint, clientConnection.RemoteEndPoint);

            ValueTask      connectTask      = clientConnection.ConnectAsync();
            QuicConnection serverConnection = await listener.AcceptConnectionAsync();

            await connectTask;

            Assert.True(clientConnection.Connected);
            Assert.True(serverConnection.Connected);
            Assert.Equal(listenEndPoint, serverConnection.LocalEndPoint);
            Assert.Equal(listenEndPoint, clientConnection.RemoteEndPoint);
            Assert.Equal(clientConnection.LocalEndPoint, serverConnection.RemoteEndPoint);

            await CreateAndTestBidirectionalStream(clientConnection, serverConnection);
            await CreateAndTestBidirectionalStream(serverConnection, clientConnection);
            await CreateAndTestUnidirectionalStream(serverConnection, clientConnection);
            await CreateAndTestUnidirectionalStream(clientConnection, serverConnection);

            await clientConnection.CloseAsync(errorCode : 0);
        }
Ejemplo n.º 25
0
        public async Task Connect_PeerCertificateDisposed(bool useGetter)
        {
            await using QuicListener listener = await CreateQuicListener();

            QuicClientConnectionOptions clientOptions   = CreateQuicClientOptions(listener.LocalEndPoint);
            X509Certificate?            peerCertificate = null;

            clientOptions.ClientAuthenticationOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
            {
                peerCertificate = certificate;
                return(true);
            };

            ValueTask <QuicConnection> connectTask = CreateQuicConnection(clientOptions);
            ValueTask <QuicConnection> acceptTask  = listener.AcceptConnectionAsync();

            await new Task[] { connectTask.AsTask(), acceptTask.AsTask() }.WhenAllOrAnyFailed(PassingTestTimeoutMilliseconds);
            await using QuicConnection serverConnection = acceptTask.Result;
            QuicConnection clientConnection = connectTask.Result;

            Assert.NotNull(peerCertificate);
            if (useGetter)
            {
                Assert.Equal(peerCertificate, clientConnection.RemoteCertificate);
            }
            // Dispose connection, if we touched RemoteCertificate (useGetter), the cert should not be disposed; otherwise, it should be disposed.
            await clientConnection.DisposeAsync();

            if (useGetter)
            {
                Assert.NotEqual(IntPtr.Zero, peerCertificate.Handle);
            }
            else
            {
                Assert.Equal(IntPtr.Zero, peerCertificate.Handle);
            }
            peerCertificate.Dispose();
        }
Ejemplo n.º 26
0
        public async Task SetListenerTimeoutWorksWithSmallTimeout()
        {
            var quicOptions = new QuicListenerOptions();
            quicOptions.IdleTimeout = TimeSpan.FromSeconds(10);
            quicOptions.ServerAuthenticationOptions = GetSslServerAuthenticationOptions();
            quicOptions.ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0);

            using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, quicOptions);
            listener.Start();

            QuicClientConnectionOptions options = new QuicClientConnectionOptions()
            {
                RemoteEndPoint = listener.ListenEndPoint,
                ClientAuthenticationOptions = GetSslClientAuthenticationOptions(),
            };

            using QuicConnection clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options);
            ValueTask clientTask = clientConnection.ConnectAsync();
            using QuicConnection serverConnection = await listener.AcceptConnectionAsync();
            await clientTask;

            await Assert.ThrowsAsync<QuicOperationAbortedException>(async () => await serverConnection.AcceptStreamAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(100)));
        }
Ejemplo n.º 27
0
        public QuicConnectionListener(QuicTransportOptions options, IQuicTrace log, EndPoint endpoint)
        {
            _log     = log;
            _context = new QuicTransportContext(_log, options);
            EndPoint = endpoint;

            var quicListenerOptions = new QuicListenerOptions();
            var sslConfig           = new SslServerAuthenticationOptions();

            sslConfig.ServerCertificate    = options.Certificate;
            sslConfig.ApplicationProtocols = new List <SslApplicationProtocol>()
            {
                new SslApplicationProtocol(options.Alpn)
            };

            quicListenerOptions.ServerAuthenticationOptions = sslConfig;
            quicListenerOptions.CertificateFilePath         = options.CertificateFilePath;
            quicListenerOptions.PrivateKeyFilePath          = options.PrivateKeyFilePath;
            quicListenerOptions.ListenEndPoint = endpoint as IPEndPoint;

            _listener = new QuicListener(QuicImplementationProviders.MsQuic, quicListenerOptions);
            _listener.Start();
        }
Ejemplo n.º 28
0
        public async Task TestConnect()
        {
            using QuicListener listener = CreateQuicListener();
            IPEndPoint listenEndPoint = listener.ListenEndPoint;

            using QuicConnection clientConnection = CreateQuicConnection(listenEndPoint);

            Assert.False(clientConnection.Connected);
            Assert.Equal(listenEndPoint, clientConnection.RemoteEndPoint);

            ValueTask      connectTask      = clientConnection.ConnectAsync();
            QuicConnection serverConnection = await listener.AcceptConnectionAsync();

            await connectTask;

            Assert.True(clientConnection.Connected);
            Assert.True(serverConnection.Connected);
            Assert.Equal(listenEndPoint, serverConnection.LocalEndPoint);
            Assert.Equal(listenEndPoint, clientConnection.RemoteEndPoint);
            Assert.Equal(clientConnection.LocalEndPoint, serverConnection.RemoteEndPoint);
            Assert.Equal(ApplicationProtocol.ToString(), clientConnection.NegotiatedApplicationProtocol.ToString());
            Assert.Equal(ApplicationProtocol.ToString(), serverConnection.NegotiatedApplicationProtocol.ToString());
        }
Ejemplo n.º 29
0
        public async Task UnidirectionalAndBidirectionalChangeValues()
        {
            using QuicListener listener = CreateQuicListener();

            QuicClientConnectionOptions options = new QuicClientConnectionOptions()
            {
                MaxBidirectionalStreams     = 10,
                MaxUnidirectionalStreams    = 20,
                RemoteEndPoint              = listener.ListenEndPoint,
                ClientAuthenticationOptions = GetSslClientAuthenticationOptions()
            };

            using QuicConnection clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options);
            Task <QuicConnection> serverTask = listener.AcceptConnectionAsync().AsTask();
            await TaskTimeoutExtensions.WhenAllOrAnyFailed(clientConnection.ConnectAsync().AsTask(), serverTask, PassingTestTimeoutMilliseconds);

            using QuicConnection serverConnection = serverTask.Result;

            Assert.Equal(100, clientConnection.GetRemoteAvailableBidirectionalStreamCount());
            Assert.Equal(100, clientConnection.GetRemoteAvailableUnidirectionalStreamCount());
            Assert.Equal(10, serverConnection.GetRemoteAvailableBidirectionalStreamCount());
            Assert.Equal(20, serverConnection.GetRemoteAvailableUnidirectionalStreamCount());
        }
Ejemplo n.º 30
0
        public async Task TestConnect()
        {
            using QuicListener listener = CreateQuicListener();

            using QuicConnection clientConnection = CreateQuicConnection(listener.ListenEndPoint);

            Assert.False(clientConnection.Connected);
            Assert.Equal(listener.ListenEndPoint, clientConnection.RemoteEndPoint);

            ValueTask connectTask = clientConnection.ConnectAsync();
            ValueTask <QuicConnection> acceptTask = listener.AcceptConnectionAsync();

            await new Task[] { connectTask.AsTask(), acceptTask.AsTask() }.WhenAllOrAnyFailed(PassingTestTimeoutMilliseconds);
            QuicConnection serverConnection = acceptTask.Result;

            Assert.True(clientConnection.Connected);
            Assert.True(serverConnection.Connected);
            Assert.Equal(listener.ListenEndPoint, serverConnection.LocalEndPoint);
            Assert.Equal(listener.ListenEndPoint, clientConnection.RemoteEndPoint);
            Assert.Equal(clientConnection.LocalEndPoint, serverConnection.RemoteEndPoint);
            Assert.Equal(ApplicationProtocol.ToString(), clientConnection.NegotiatedApplicationProtocol.ToString());
            Assert.Equal(ApplicationProtocol.ToString(), serverConnection.NegotiatedApplicationProtocol.ToString());
        }