public override async ValueTask <ConnectionContext> ConnectAsync(IFeatureCollection?features = null, CancellationToken cancellationToken = default) { QuicStream quicStream; var streamDirectionFeature = features?.Get <IStreamDirectionFeature>(); if (streamDirectionFeature != null) { if (streamDirectionFeature.CanRead) { quicStream = await _connection.OpenBidirectionalStreamAsync(cancellationToken); } else { quicStream = await _connection.OpenUnidirectionalStreamAsync(cancellationToken); } } else { quicStream = await _connection.OpenBidirectionalStreamAsync(cancellationToken); } // Only a handful of control streams are created by the server and they last for the // lifetime of the connection. No value in pooling them. QuicStreamContext?context = new QuicStreamContext(this, _context); context.Initialize(quicStream); context.Start(); QuicLog.ConnectedStream(_log, context); return(context); }
public async Task ClientToServerUnidirectionalStream_CompleteWrites_PipeProvidesDataAndCompleteTogether() { // Arrange await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); using var quicConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options); await quicConnection.ConnectAsync().DefaultTimeout(); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act await using var clientStream = await quicConnection.OpenUnidirectionalStreamAsync(); await clientStream.WriteAsync(TestData).DefaultTimeout(); await using var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); var readResultTask = serverStream.Transport.Input.ReadAsync(); await clientStream.WriteAsync(TestData, endStream : true).DefaultTimeout(); // Assert var completeReadResult = await readResultTask.DefaultTimeout(); Assert.Equal(TestData, completeReadResult.Buffer.ToArray()); Assert.True(completeReadResult.IsCompleted); }
public async Task AcceptAsync_ClientStartsAndStopsUnidirectionStream_ServerAccepts() { // Arrange await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); using var quicConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options); await quicConnection.ConnectAsync().DefaultTimeout(); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act var acceptTask = serverConnection.AcceptAsync(); await using var clientStream = await quicConnection.OpenUnidirectionalStreamAsync(); await clientStream.WriteAsync(TestData); await using var serverStream = await acceptTask.DefaultTimeout(); // Assert Assert.NotNull(serverStream); Assert.False(serverStream.ConnectionClosed.IsCancellationRequested); var closedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); serverStream.ConnectionClosed.Register(() => closedTcs.SetResult()); // Read data from client. var read = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); Assert.Equal(TestData, read.Buffer.ToArray()); serverStream.Transport.Input.AdvanceTo(read.Buffer.End); // Shutdown client. clientStream.Shutdown(); // Receive shutdown on server. read = await serverStream.Transport.Input.ReadAsync().DefaultTimeout(); Assert.True(read.IsCompleted); await closedTcs.Task.DefaultTimeout(); }
public async Task ClientToServerUnidirectionalStream_ClientAbort_ServerReceivesAbort() { // Arrange await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); using var quicConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options); await quicConnection.ConnectAsync().DefaultTimeout(); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act await using var clientStream = await quicConnection.OpenUnidirectionalStreamAsync(); await clientStream.WriteAsync(TestData).DefaultTimeout(); await using var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); var closedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); serverStream.ConnectionClosed.Register(() => closedTcs.SetResult()); clientStream.AbortWrite((long)Http3ErrorCode.InternalError); // Receive abort from client. var ex = await Assert.ThrowsAsync <ConnectionResetException>(() => serverStream.Transport.Input.ReadAsync().AsTask()).DefaultTimeout(); // Assert Assert.Equal((long)Http3ErrorCode.InternalError, ((QuicStreamAbortedException)ex.InnerException).ErrorCode); var quicStreamContext = Assert.IsType <QuicStreamContext>(serverStream); // Both send and receive loops have exited. await quicStreamContext._processingTask.DefaultTimeout(); await closedTcs.Task.DefaultTimeout(); }
public async Task ClientToServerUnidirectionalStream_ServerReadsData_GracefullyClosed() { // Arrange await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); using var quicConnection = new QuicConnection(QuicImplementationProviders.MsQuic, options); await quicConnection.ConnectAsync().DefaultTimeout(); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act await using var clientStream = await quicConnection.OpenUnidirectionalStreamAsync(); await clientStream.WriteAsync(TestData, endStream : true).DefaultTimeout(); await using var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); // Input should be completed. readResult = await serverStream.Transport.Input.ReadAsync().DefaultTimeout(); // Assert Assert.True(readResult.IsCompleted); var quicStreamContext = Assert.IsType <QuicStreamContext>(serverStream); Assert.False(quicStreamContext.CanWrite); Assert.True(quicStreamContext.CanRead); // Both send and receive loops have exited. await quicStreamContext._processingTask.DefaultTimeout(); }
public async ValueTask <Http3LoopbackStream> OpenUnidirectionalStreamAsync() { return(new Http3LoopbackStream(await _connection.OpenUnidirectionalStreamAsync())); }