diff options
author | James Newton-King <james@newtonking.com> | 2022-07-14 10:41:48 +0300 |
---|---|---|
committer | James Newton-King <james@newtonking.com> | 2022-07-14 10:41:48 +0300 |
commit | 1f55da74ef2a385e15e28fd5bddf33f9ad8de025 (patch) | |
tree | 09962e6b50b54147e2b11be056dc8219f9f04b1b | |
parent | cad280c1a96bf3256d7316913ce4ad68fd6b088a (diff) |
React to QUIC connection API changesjamesnk/quic-api-reaction
9 files changed, 96 insertions, 173 deletions
diff --git a/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicConnectionContext.cs b/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicConnectionContext.cs index 5f9828d868..6fc49e6a19 100644 --- a/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicConnectionContext.cs +++ b/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicConnectionContext.cs @@ -65,7 +65,7 @@ internal partial class QuicConnectionContext : TransportMultiplexedConnection _log.LogWarning(ex, "Failed to gracefully shutdown connection."); } - _connection.Dispose(); + await _connection.DisposeAsync(); } public override void Abort() => Abort(new ConnectionAbortedException("The connection was aborted by the application via MultiplexedConnectionContext.Abort().")); @@ -91,7 +91,7 @@ internal partial class QuicConnectionContext : TransportMultiplexedConnection { try { - var stream = await _connection.AcceptStreamAsync(cancellationToken); + var stream = await _connection.AcceptInboundStreamAsync(cancellationToken); QuicStreamContext? context = null; @@ -194,16 +194,16 @@ internal partial class QuicConnectionContext : TransportMultiplexedConnection { if (streamDirectionFeature.CanRead) { - quicStream = await _connection.OpenBidirectionalStreamAsync(cancellationToken); + quicStream = await _connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional, cancellationToken); } else { - quicStream = await _connection.OpenUnidirectionalStreamAsync(cancellationToken); + quicStream = await _connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional, cancellationToken); } } else { - quicStream = await _connection.OpenBidirectionalStreamAsync(cancellationToken); + quicStream = await _connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional, cancellationToken); } // Only a handful of control streams are created by the server and they last for the diff --git a/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicConnectionListener.cs b/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicConnectionListener.cs index 0f6c16a5e3..eb02565185 100644 --- a/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicConnectionListener.cs +++ b/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicConnectionListener.cs @@ -51,8 +51,8 @@ internal sealed class QuicConnectionListener : IMultiplexedConnectionListener, I { ServerAuthenticationOptions = sslServerAuthenticationOptions, IdleTimeout = options.IdleTimeout, - MaxBidirectionalStreams = options.MaxBidirectionalStreamCount, - MaxUnidirectionalStreams = options.MaxUnidirectionalStreamCount + MaxInboundBidirectionalStreams = options.MaxBidirectionalStreamCount, + MaxInboundUnidirectionalStreams = options.MaxUnidirectionalStreamCount }; return ValueTask.FromResult(connectionOptions); } diff --git a/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicStreamContext.FeatureCollection.cs b/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicStreamContext.FeatureCollection.cs index c01209238b..b3728699f0 100644 --- a/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicStreamContext.FeatureCollection.cs +++ b/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicStreamContext.FeatureCollection.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Net.Quic; using Microsoft.AspNetCore.Connections; using Microsoft.AspNetCore.Connections.Features; @@ -41,7 +42,7 @@ internal sealed partial class QuicStreamContext : IPersistentStateFeature, IStre { _shutdownReadReason = abortReason; QuicLog.StreamAbortRead(_log, this, errorCode, abortReason.Message); - _stream.AbortRead(errorCode); + _stream.Abort(QuicAbortDirection.Read, errorCode); } else { @@ -61,7 +62,7 @@ internal sealed partial class QuicStreamContext : IPersistentStateFeature, IStre { _shutdownWriteReason = abortReason; QuicLog.StreamAbortWrite(_log, this, errorCode, abortReason.Message); - _stream.AbortWrite(errorCode); + _stream.Abort(QuicAbortDirection.Write, errorCode); } else { diff --git a/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicStreamContext.cs b/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicStreamContext.cs index 8e27ecdcef..585278586c 100644 --- a/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicStreamContext.cs +++ b/src/Servers/Kestrel/Transport.Quic/src/Internal/QuicStreamContext.cs @@ -92,7 +92,7 @@ internal partial class QuicStreamContext : TransportConnection, IPooledStream, I CanRead = _stream.CanRead; CanWrite = _stream.CanWrite; _error = null; - StreamId = _stream.StreamId; + StreamId = _stream.Id; PoolExpirationTicks = 0; Transport = _originalTransport; @@ -174,7 +174,7 @@ internal partial class QuicStreamContext : TransportConnection, IPooledStream, I try { - await _stream.WaitForWriteCompletionAsync(); + await _stream.WritesClosed; } catch (Exception ex) { @@ -211,7 +211,7 @@ internal partial class QuicStreamContext : TransportConnection, IPooledStream, I ValueTask<FlushResult> flushTask; - if (_stream.ReadsCompleted) + if (_stream.ReadsClosed.IsCompletedSuccessfully) { // If the data returned from ReadAsync is the final chunk on the stream then // flush data and end pipe together with CompleteAsync. @@ -381,7 +381,7 @@ internal partial class QuicStreamContext : TransportConnection, IPooledStream, I if (buffer.IsSingleSegment) { // Fast path when the buffer is a single segment. - await _stream.WriteAsync(buffer.First, endStream: isCompleted); + await _stream.WriteAsync(buffer.First, completeWrites: isCompleted); } else { @@ -395,7 +395,7 @@ internal partial class QuicStreamContext : TransportConnection, IPooledStream, I { var currentSegment = enumerator.Current; isLastSegment = !enumerator.MoveNext(); - await _stream.WriteAsync(currentSegment, endStream: isLastSegment && isCompleted); + await _stream.WriteAsync(currentSegment, completeWrites: isLastSegment && isCompleted); } } } @@ -478,11 +478,11 @@ internal partial class QuicStreamContext : TransportConnection, IPooledStream, I { if (_stream.CanRead) { - _stream.AbortRead(resolvedErrorCode); + _stream.Abort(QuicAbortDirection.Read, resolvedErrorCode); } if (_stream.CanWrite) { - _stream.AbortWrite(resolvedErrorCode); + _stream.Abort(QuicAbortDirection.Write, resolvedErrorCode); } } } @@ -503,7 +503,7 @@ internal partial class QuicStreamContext : TransportConnection, IPooledStream, I _shutdownReason = shutdownReason ?? new ConnectionAbortedException("The QUIC transport's send loop completed gracefully."); QuicLog.StreamShutdownWrite(_log, this, _shutdownReason.Message); - _stream.Shutdown(); + _stream.CompleteWrites(); } } catch (Exception ex) diff --git a/src/Servers/Kestrel/Transport.Quic/src/QuicConnectionFactory.cs b/src/Servers/Kestrel/Transport.Quic/src/QuicConnectionFactory.cs deleted file mode 100644 index 0ddec2fe74..0000000000 --- a/src/Servers/Kestrel/Transport.Quic/src/QuicConnectionFactory.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Net; -using System.Net.Quic; -using System.Net.Security; -using Microsoft.AspNetCore.Connections; -using Microsoft.AspNetCore.Http.Features; -using Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.Internal; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Quic; - -// Not used anywhere. Remove? -internal sealed class QuicConnectionFactory : IMultiplexedConnectionFactory -{ - private readonly QuicTransportContext _transportContext; - - public QuicConnectionFactory(IOptions<QuicTransportOptions> options, ILoggerFactory loggerFactory) - { - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - var logger = loggerFactory.CreateLogger("Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.Client"); - - _transportContext = new QuicTransportContext(logger, options.Value); - } - - public async ValueTask<MultiplexedConnectionContext> ConnectAsync(EndPoint endPoint, IFeatureCollection? features = null, CancellationToken cancellationToken = default) - { - if (endPoint is not IPEndPoint) - { - throw new NotSupportedException($"{endPoint} is not supported"); - } - - var sslOptions = features?.Get<SslClientAuthenticationOptions>(); - var connection = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions() - { - RemoteEndPoint = endPoint, - ClientAuthenticationOptions = sslOptions ?? new SslClientAuthenticationOptions() - }, cancellationToken); - - await connection.ConnectAsync(cancellationToken); - return new QuicConnectionContext(connection, _transportContext); - } -} diff --git a/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs b/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs index e09068ffe3..4684a65f66 100644 --- a/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs +++ b/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionContextTests.cs @@ -23,8 +23,6 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest public async Task AcceptAsync_CancellationThenAccept_AcceptStreamAfterCancellation() { // Arrange - var connectionClosedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); // Act @@ -32,8 +30,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await acceptTask.DefaultTimeout(); @@ -48,7 +45,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest // Wait for stream after cancellation acceptStreamTask = serverConnection.AcceptAsync(); - await using var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); + await using var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData); // Assert @@ -74,8 +71,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await acceptTask.DefaultTimeout(); serverConnection.ConnectionClosed.Register(() => connectionClosedTcs.SetResult()); @@ -101,15 +97,14 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act var acceptTask = serverConnection.AcceptAsync(); - await using var clientStream = await quicConnection.OpenUnidirectionalStreamAsync(); + await using var clientStream = await quicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData); await using var serverStream = await acceptTask.DefaultTimeout(); @@ -127,7 +122,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest serverStream.Transport.Input.AdvanceTo(read.Buffer.End); // Shutdown client. - clientStream.Shutdown(); + clientStream.CompleteWrites(); // Receive shutdown on server. read = await serverStream.Transport.Input.ReadAsync().DefaultTimeout(); @@ -144,15 +139,14 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act var acceptTask = serverConnection.AcceptAsync(); - await using var clientStream = await quicConnection.OpenBidirectionalStreamAsync(); + await using var clientStream = await quicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData); await using var serverStream = await acceptTask.DefaultTimeout(); @@ -176,7 +170,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest Assert.Equal(TestData, data); // Shutdown from client. - clientStream.Shutdown(); + clientStream.CompleteWrites(); // Get shutdown from client. read = await serverStream.Transport.Input.ReadAsync().DefaultTimeout(); @@ -195,13 +189,12 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act - var acceptTask = quicConnection.AcceptStreamAsync(); + var acceptTask = quicConnection.AcceptInboundStreamAsync(); await using var serverStream = await serverConnection.ConnectAsync(); await serverStream.Transport.Output.WriteAsync(TestData).DefaultTimeout(); @@ -241,8 +234,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -268,8 +260,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -280,8 +271,8 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest var quicConnectionContext = Assert.IsType<QuicConnectionContext>(serverConnection); Assert.Equal(0, quicConnectionContext.StreamPool.Count); - var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); - await clientStream.WriteAsync(TestData, endStream: true).DefaultTimeout(); + var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + await clientStream.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); @@ -312,8 +303,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -324,8 +314,8 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest var quicConnectionContext = Assert.IsType<QuicConnectionContext>(serverConnection); Assert.Equal(0, quicConnectionContext.StreamPool.Count); - var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); - await clientStream.WriteAsync(TestData, endStream: true).DefaultTimeout(); + var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + await clientStream.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); @@ -358,8 +348,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -370,14 +359,14 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest var quicConnectionContext = Assert.IsType<QuicConnectionContext>(serverConnection); Assert.Equal(0, quicConnectionContext.StreamPool.Count); - var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); + var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); - clientStream.AbortWrite((long)Http3ErrorCode.InternalError); + clientStream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.InternalError); // Receive abort form client. var ex = await Assert.ThrowsAsync<ConnectionResetException>(() => serverStream.Transport.Input.ReadAsync().AsTask()).DefaultTimeout(); @@ -406,8 +395,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -418,14 +406,14 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest var quicConnectionContext = Assert.IsType<QuicConnectionContext>(serverConnection); Assert.Equal(0, quicConnectionContext.StreamPool.Count); - var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); + var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); - clientStream.AbortWrite((long)Http3ErrorCode.InternalError); + clientStream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.InternalError); // Receive abort form client. var serverEx = await Assert.ThrowsAsync<ConnectionResetException>(() => serverStream.Transport.Input.ReadAsync().AsTask()).DefaultTimeout(); @@ -465,8 +453,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory, testSystemClock); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -520,8 +507,7 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -554,8 +540,8 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest static async Task SendStream(RequestState requestState) { - var clientStream = await requestState.QuicConnection.OpenBidirectionalStreamAsync(); - await clientStream.WriteAsync(TestData, endStream: true).DefaultTimeout(); + var clientStream = await requestState.QuicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + await clientStream.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); var serverStream = await requestState.ServerConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); @@ -599,15 +585,14 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act Logger.LogInformation("Client starting stream 1"); - var clientStream1 = await clientConnection.OpenBidirectionalStreamAsync(); - await clientStream1.WriteAsync(TestData, endStream: true).DefaultTimeout(); + var clientStream1 = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + await clientStream1.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); Logger.LogInformation("Server accept stream 1"); var serverStream1 = await serverConnection.AcceptAsync().DefaultTimeout(); @@ -634,8 +619,8 @@ public class QuicConnectionContextTests : TestApplicationErrorLoggerLoggedTest quicStreamContext1.Dispose(); Logger.LogInformation("Client starting stream 2"); - var clientStream2 = await clientConnection.OpenBidirectionalStreamAsync(); - await clientStream2.WriteAsync(TestData, endStream: true).DefaultTimeout(); + var clientStream2 = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + await clientStream2.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); Logger.LogInformation("Server accept stream 2"); var serverStream2 = await serverConnection.AcceptAsync().DefaultTimeout(); diff --git a/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionListenerTests.cs b/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionListenerTests.cs index 0080b1d8d3..564056574c 100644 --- a/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionListenerTests.cs +++ b/src/Servers/Kestrel/Transport.Quic/test/QuicConnectionListenerTests.cs @@ -44,8 +44,7 @@ public class QuicConnectionListenerTests : TestApplicationErrorLoggerLoggedTest var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); // Assert await using var serverConnection = await acceptTask.DefaultTimeout(); @@ -72,15 +71,14 @@ public class QuicConnectionListenerTests : TestApplicationErrorLoggerLoggedTest options.ClientAuthenticationOptions.ClientCertificates = new X509CertificateCollection { testCert }; // Act - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Server waits for stream from client var serverStreamTask = serverConnection.AcceptAsync().DefaultTimeout(); // Client creates stream - using var clientStream = await quicConnection.OpenBidirectionalStreamAsync(); + using var clientStream = await quicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); // Server finishes accepting @@ -108,9 +106,6 @@ public class QuicConnectionListenerTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory, clientCertificateRequired: true); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - - await clientConnection.ConnectAsync().DefaultTimeout(); - Assert.True(clientConnection.Connected); + await using var clientConnection = await QuicConnection.ConnectAsync(options); } } diff --git a/src/Servers/Kestrel/Transport.Quic/test/QuicStreamContextTests.cs b/src/Servers/Kestrel/Transport.Quic/test/QuicStreamContextTests.cs index e026d35639..1ebacdbf3a 100644 --- a/src/Servers/Kestrel/Transport.Quic/test/QuicStreamContextTests.cs +++ b/src/Servers/Kestrel/Transport.Quic/test/QuicStreamContextTests.cs @@ -31,8 +31,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -56,13 +55,12 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act - var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); + var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); @@ -103,13 +101,12 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act - var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); + var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); var readTask = clientStream.ReadUntilEndAsync(); @@ -133,8 +130,8 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest var disposeTask = quicStreamContext.DisposeAsync(); // Client aborts while server is draining - clientStream.AbortRead((long)Http3ErrorCode.RequestCancelled); - clientStream.AbortWrite((long)Http3ErrorCode.RequestCancelled); + clientStream.Abort(QuicAbortDirection.Read, (long)Http3ErrorCode.RequestCancelled); + clientStream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.RequestCancelled); // Server finishes disposing await disposeTask.DefaultTimeout(); @@ -163,15 +160,14 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act Logger.LogInformation("Client starting stream."); - var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); - await clientStream.WriteAsync(TestData, endStream: true).DefaultTimeout(); + var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + await clientStream.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); Logger.LogInformation("Server accepted stream."); @@ -221,8 +217,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var clientConnection = await QuicConnection.ConnectAsync(options); - await clientConnection.ConnectAsync().DefaultTimeout(); + await using var clientConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -244,13 +239,12 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act - await using var clientStream = await quicConnection.OpenBidirectionalStreamAsync(); + await using var clientStream = await quicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); await using var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); @@ -260,7 +254,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest var closedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); serverStream.ConnectionClosed.Register(() => closedTcs.SetResult()); - clientStream.AbortWrite((long)Http3ErrorCode.InternalError); + clientStream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.InternalError); // Receive abort from client. var ex = await Assert.ThrowsAsync<ConnectionResetException>(() => serverStream.Transport.Input.ReadAsync().AsTask()).DefaultTimeout(); @@ -289,14 +283,13 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); 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 clientStream = await quicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + await clientStream.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); await using var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); @@ -324,13 +317,12 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act - await using var clientStream = await quicConnection.OpenUnidirectionalStreamAsync(); + await using var clientStream = await quicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); await using var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); @@ -340,7 +332,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest var closedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); serverStream.ConnectionClosed.Register(() => closedTcs.SetResult()); - clientStream.AbortWrite((long)Http3ErrorCode.InternalError); + clientStream.Abort(QuicAbortDirection.Write, (long)Http3ErrorCode.InternalError); // Receive abort from client. var ex = await Assert.ThrowsAsync<ConnectionResetException>(() => serverStream.Transport.Input.ReadAsync().AsTask()).DefaultTimeout(); @@ -364,13 +356,12 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act - await using var clientStream = await quicConnection.OpenUnidirectionalStreamAsync(); + await using var clientStream = await quicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); await using var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); @@ -379,7 +370,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest var readResultTask = serverStream.Transport.Input.ReadAsync(); - await clientStream.WriteAsync(TestData, endStream: true).DefaultTimeout(); + await clientStream.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); // Assert var completeReadResult = await readResultTask.DefaultTimeout(); @@ -396,8 +387,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -407,7 +397,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest var serverStream = await serverConnection.ConnectAsync(features).DefaultTimeout(); await serverStream.Transport.Output.WriteAsync(TestData).DefaultTimeout(); - await using var clientStream = await quicConnection.AcceptStreamAsync(); + await using var clientStream = await quicConnection.AcceptInboundStreamAsync(); var data = await clientStream.ReadAtLeastLengthAsync(TestData.Length).DefaultTimeout(); @@ -438,8 +428,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); @@ -449,7 +438,7 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest var serverStream = await serverConnection.ConnectAsync(features).DefaultTimeout(); await serverStream.Transport.Output.WriteAsync(TestData).DefaultTimeout(); - await using var clientStream = await quicConnection.AcceptStreamAsync(); + await using var clientStream = await quicConnection.AcceptInboundStreamAsync(); var data = await clientStream.ReadAtLeastLengthAsync(TestData.Length).DefaultTimeout(); @@ -483,13 +472,12 @@ public class QuicStreamContextTests : TestApplicationErrorLoggerLoggedTest await using var connectionListener = await QuicTestHelpers.CreateConnectionListenerFactory(LoggerFactory); var options = QuicTestHelpers.CreateClientConnectionOptions(connectionListener.EndPoint); - using var quicConnection = await QuicConnection.ConnectAsync(options); - await quicConnection.ConnectAsync().DefaultTimeout(); + await using var quicConnection = await QuicConnection.ConnectAsync(options); await using var serverConnection = await connectionListener.AcceptAndAddFeatureAsync().DefaultTimeout(); // Act - await using var clientStream = await quicConnection.OpenBidirectionalStreamAsync(); + await using var clientStream = await quicConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); await clientStream.WriteAsync(TestData).DefaultTimeout(); await using var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); diff --git a/src/Servers/Kestrel/Transport.Quic/test/QuicTestHelpers.cs b/src/Servers/Kestrel/Transport.Quic/test/QuicTestHelpers.cs index 7c60088eac..f6385cde29 100644 --- a/src/Servers/Kestrel/Transport.Quic/test/QuicTestHelpers.cs +++ b/src/Servers/Kestrel/Transport.Quic/test/QuicTestHelpers.cs @@ -71,7 +71,7 @@ internal static class QuicTestHelpers public static async ValueTask<MultiplexedConnectionContext> AcceptAndAddFeatureAsync(this IMultiplexedConnectionListener listener) { var connection = await listener.AcceptAsync(); - connection.Features.Set<IConnectionHeartbeatFeature>(new TestConnectionHeartbeatFeature()); + connection?.Features.Set<IConnectionHeartbeatFeature>(new TestConnectionHeartbeatFeature()); return connection; } @@ -91,24 +91,27 @@ internal static class QuicTestHelpers { return new QuicClientConnectionOptions { - MaxBidirectionalStreams = 200, - MaxUnidirectionalStreams = 200, + MaxInboundBidirectionalStreams = 200, + MaxInboundUnidirectionalStreams = 200, RemoteEndPoint = remoteEndPoint, ClientAuthenticationOptions = new SslClientAuthenticationOptions { ApplicationProtocols = new List<SslApplicationProtocol> - { - SslApplicationProtocol.Http3 - }, + { + SslApplicationProtocol.Http3 + }, RemoteCertificateValidationCallback = RemoteCertificateValidationCallback - } + }, + DefaultStreamErrorCode = 0, + DefaultCloseErrorCode = 0, + }; } public static async Task<QuicStreamContext> CreateAndCompleteBidirectionalStreamGracefully(QuicConnection clientConnection, MultiplexedConnectionContext serverConnection) { - var clientStream = await clientConnection.OpenBidirectionalStreamAsync(); - await clientStream.WriteAsync(TestData, endStream: true).DefaultTimeout(); + var clientStream = await clientConnection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); + await clientStream.WriteAsync(TestData, completeWrites: true).DefaultTimeout(); var serverStream = await serverConnection.AcceptAsync().DefaultTimeout(); var readResult = await serverStream.Transport.Input.ReadAtLeastAsync(TestData.Length).DefaultTimeout(); serverStream.Transport.Input.AdvanceTo(readResult.Buffer.End); |