public async Task WaitForAvailableUnidirectionStreamsAsyncWorks() { using QuicListener listener = CreateQuicListener(maxUnidirectionalStreams: 1); using QuicConnection clientConnection = CreateQuicConnection(listener.ListenEndPoint); Task <QuicConnection> serverTask = listener.AcceptConnectionAsync().AsTask(); await TaskTimeoutExtensions.WhenAllOrAnyFailed(clientConnection.ConnectAsync().AsTask(), serverTask, PassingTestTimeoutMilliseconds); using QuicConnection serverConnection = serverTask.Result; listener.Dispose(); // No stream opened yet, should return immediately. Assert.True(clientConnection.WaitForAvailableUnidirectionalStreamsAsync().IsCompletedSuccessfully); // Open one stream, should wait till it closes. QuicStream stream = clientConnection.OpenUnidirectionalStream(); ValueTask waitTask = clientConnection.WaitForAvailableUnidirectionalStreamsAsync(); Assert.False(waitTask.IsCompleted); Assert.Throws <QuicException>(() => clientConnection.OpenUnidirectionalStream()); // Close the streams, the waitTask should finish as a result. stream.Dispose(); QuicStream newStream = await serverConnection.AcceptStreamAsync(); newStream.Dispose(); await waitTask.AsTask().WaitAsync(TimeSpan.FromSeconds(10)); }
public async Task WaitForAvailableUnidirectionStreamsAsyncWorks() { using QuicListener listener = CreateQuicListener(maxUnidirectionalStreams: 1); using QuicConnection clientConnection = CreateQuicConnection(listener.ListenEndPoint); ValueTask clientTask = clientConnection.ConnectAsync(); using QuicConnection serverConnection = await listener.AcceptConnectionAsync(); await clientTask; // No stream openned yet, should return immediately. Assert.True(clientConnection.WaitForAvailableUnidirectionalStreamsAsync().IsCompletedSuccessfully); // Open one stream, should wait till it closes. QuicStream stream = clientConnection.OpenUnidirectionalStream(); ValueTask waitTask = clientConnection.WaitForAvailableUnidirectionalStreamsAsync(); Assert.False(waitTask.IsCompleted); Assert.Throws <QuicException>(() => clientConnection.OpenUnidirectionalStream()); // Close the stream, the waitTask should finish as a result. stream.Dispose(); await waitTask.AsTask().WaitAsync(TimeSpan.FromSeconds(10)); }
public ValueTask <ConnectionContext> StartUnidirectionalStreamAsync() { var stream = _connection.OpenUnidirectionalStream(); var context = new QuicStreamContext(stream, this, _context); context.Start(); return(new ValueTask <ConnectionContext>(context)); }
public override ValueTask <ConnectionContext> ConnectAsync(IFeatureCollection?features = null, CancellationToken cancellationToken = default) { QuicStream quicStream; var streamDirectionFeature = features?.Get <IStreamDirectionFeature>(); if (streamDirectionFeature != null) { if (streamDirectionFeature.CanRead) { quicStream = _connection.OpenBidirectionalStream(); } else { quicStream = _connection.OpenUnidirectionalStream(); } } else { quicStream = _connection.OpenBidirectionalStream(); } // 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(new ValueTask <ConnectionContext>(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 = quicConnection.OpenUnidirectionalStream(); 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); }
protected sealed override async Task QuicStreamServer(QuicConnection connection) { await using var stream = connection.OpenUnidirectionalStream(); await SendData(stream); await stream.ShutdownWriteCompleted(); }
public async Task QuicStream_ReadWrite_Random_Success(int readSize, int writeSize) { byte[] testBuffer = new byte[8192]; new Random().NextBytes(testBuffer); await Task.WhenAll(DoWrite(), DoRead()); async Task DoWrite() { using QuicConnection clientConnection = CreateQuicConnection(DefaultListener.ListenEndPoint); await clientConnection.ConnectAsync(); await using QuicStream clientStream = clientConnection.OpenUnidirectionalStream(); ReadOnlyMemory <byte> sendBuffer = testBuffer; while (sendBuffer.Length != 0) { ReadOnlyMemory <byte> chunk = sendBuffer.Slice(0, Math.Min(sendBuffer.Length, writeSize)); await clientStream.WriteAsync(chunk); sendBuffer = sendBuffer.Slice(chunk.Length); } clientStream.Shutdown(); await clientStream.ShutdownWriteCompleted(); } async Task DoRead() { using QuicConnection serverConnection = await DefaultListener.AcceptConnectionAsync(); await using QuicStream serverStream = await serverConnection.AcceptStreamAsync(); byte[] receiveBuffer = new byte[testBuffer.Length]; int totalBytesRead = 0; while (totalBytesRead != receiveBuffer.Length) { int bytesRead = await serverStream.ReadAsync(receiveBuffer.AsMemory(totalBytesRead, Math.Min(receiveBuffer.Length - totalBytesRead, readSize))); if (bytesRead == 0) { break; } totalBytesRead += bytesRead; } Assert.True(receiveBuffer.AsSpan().SequenceEqual(testBuffer)); } }
message); // message private async ValueTask SendSettingsAsync() { try { _clientControl = _connection.OpenUnidirectionalStream(); await _clientControl.WriteAsync(_pool.Settings.Http3SettingsFrame, CancellationToken.None).ConfigureAwait(false); } catch (Exception ex) { Abort(ex); } }
private static async Task CreateAndTestUnidirectionalStream(QuicConnection c1, QuicConnection c2) { using QuicStream s1 = c1.OpenUnidirectionalStream(); Assert.False(s1.CanRead); Assert.True(s1.CanWrite); ValueTask writeTask = s1.WriteAsync(s_data); using QuicStream s2 = await c2.AcceptStreamAsync(); await ReceiveDataAsync(s_data, s2); await writeTask; await TestUnidirectionalStream(s1, s2); }
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 = quicConnection.OpenUnidirectionalStream(); 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.AcceptAsync().DefaultTimeout(); // Act await using var clientStream = quicConnection.OpenUnidirectionalStream(); 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.AcceptAsync().DefaultTimeout(); // Act await using var clientStream = quicConnection.OpenUnidirectionalStream(); 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(); // 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 Http3LoopbackStream OpenUnidirectionalStream() { return(new Http3LoopbackStream(_connection.OpenUnidirectionalStream())); }