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); } }
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); }
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; }
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); }
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(); }
/// <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); }
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(); } } }
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}"); } }
// 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); } } }); } }
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); }
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(); }
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); }
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); }
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!")); }; } }
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; }
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; }
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(); }
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; }
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!")); }; } }
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()); }
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; }
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(); }
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); }
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(); }
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))); }
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(); }
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()); }
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()); }
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()); }