From 2f88af142c79169e5bf880f99106cd5a1007b5c1 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Wed, 8 Jun 2022 09:33:06 +0200 Subject: [PATCH 1/3] Removed abstract providers and mock from S.N.Quic --- .../System/Net/Http/Http3LoopbackServer.cs | 16 +- ...ttpClientHandlerTest.ServerCertificates.cs | 10 +- ...ttpClientHandlerTestBase.WinHttpHandler.cs | 4 +- .../FunctionalTests/PlatformHandlerTest.cs | 5 +- .../Http/SocketsHttpHandler/ConnectHelper.cs | 16 +- .../SocketsHttpHandler/HttpConnectionPool.cs | 4 +- .../HttpConnectionSettings.cs | 10 - .../HttpClientHandlerTest.AltSvc.cs | 20 +- .../HttpClientHandlerTest.Finalization.cs | 5 - .../HttpClientHandlerTest.Http3.cs | 98 +--- ...lientHandlerTestBase.SocketsHttpHandler.cs | 40 +- .../HttpClientMiniStressTest.cs | 16 +- .../ResponseStreamZeroByteReadTests.cs | 19 +- .../FunctionalTests/SocketsHttpHandlerTest.cs | 116 +---- .../tests/FunctionalTests/TelemetryTest.cs | 60 +-- .../System.Net.Quic/ref/System.Net.Quic.cs | 30 +- .../src/ExcludeApiList.PNSE.txt | 2 +- .../src/System.Net.Quic.csproj | 5 +- .../Implementations/Mock/MockConnection.cs | 484 ------------------ .../Mock/MockImplementationProvider.cs | 26 - .../Quic/Implementations/Mock/MockListener.cs | 114 ----- .../Quic/Implementations/Mock/MockStream.cs | 338 ------------ .../MsQuic/MsQuicConnection.cs | 30 +- .../MsQuic/MsQuicImplementationProvider.cs | 32 -- .../Implementations/MsQuic/MsQuicListener.cs | 8 +- .../Implementations/MsQuic/MsQuicStream.cs | 54 +- .../Implementations/QuicConnectionProvider.cs | 37 -- .../QuicImplementationProvider.cs | 18 - .../Implementations/QuicListenerProvider.cs | 17 - .../Implementations/QuicStreamProvider.cs | 62 --- .../src/System/Net/Quic/QuicConnection.cs | 37 +- ...QuicImplementationProviders.Unsupported.cs | 30 -- .../Net/Quic/QuicImplementationProviders.cs | 12 - .../src/System/Net/Quic/QuicListener.cs | 33 +- .../Net/Quic/QuicProvider.Unsupported.cs | 10 + .../src/System/Net/Quic/QuicProvider.cs | 35 ++ .../src/System/Net/Quic/QuicStream.cs | 5 +- .../MsQuicCipherSuitesPolicyTests.cs | 13 +- .../MsQuicPlatformDetectionTests.cs | 7 +- .../tests/FunctionalTests/MsQuicTests.cs | 28 +- .../FunctionalTests/QuicConnectionTests.cs | 50 +- .../FunctionalTests/QuicListenerTests.cs | 32 +- ...icStreamConnectedStreamConformanceTests.cs | 42 +- .../tests/FunctionalTests/QuicStreamTests.cs | 38 +- .../tests/FunctionalTests/QuicTestBase.cs | 50 +- 45 files changed, 280 insertions(+), 1838 deletions(-) delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockImplementationProvider.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockListener.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicImplementationProvider.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicConnectionProvider.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicImplementationProvider.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicListenerProvider.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.Unsupported.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.Unsupported.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.cs diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs index c8b00faad2759..2d749fa7e4097 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs @@ -5,7 +5,6 @@ using System.Diagnostics; using System.IO; using System.Net.Quic; -using System.Net.Quic.Implementations; using System.Net.Security; using System.Net.Sockets; using System.Security.Cryptography.X509Certificates; @@ -20,7 +19,7 @@ public sealed class Http3LoopbackServer : GenericLoopbackServer public override Uri Address => new Uri($"https://{_listener.ListenEndPoint}/"); - public Http3LoopbackServer(QuicImplementationProvider quicImplementationProvider = null, Http3Options options = null) + public Http3LoopbackServer(Http3Options options = null) { options ??= new Http3Options(); @@ -43,7 +42,7 @@ public Http3LoopbackServer(QuicImplementationProvider quicImplementationProvider MaxBidirectionalStreams = options.MaxBidirectionalStreams, }; - _listener = new QuicListener(quicImplementationProvider ?? QuicImplementationProviders.Default, listenerOptions); + _listener = QuicProvider.CreateListenerAsync(listenerOptions).Result; } public override void Dispose() @@ -82,20 +81,13 @@ public override async Task HandleRequestAsync(HttpStatusCode st public sealed class Http3LoopbackServerFactory : LoopbackServerFactory { - private QuicImplementationProvider _quicImplementationProvider; - - public Http3LoopbackServerFactory(QuicImplementationProvider quicImplementationProvider) - { - _quicImplementationProvider = quicImplementationProvider; - } - - public static Http3LoopbackServerFactory Singleton { get; } = new Http3LoopbackServerFactory(null); + public static Http3LoopbackServerFactory Singleton { get; } = new Http3LoopbackServerFactory(); public override Version Version { get; } = new Version(3, 0); public override GenericLoopbackServer CreateServer(GenericLoopbackOptions options = null) { - return new Http3LoopbackServer(_quicImplementationProvider, CreateOptions(options)); + return new Http3LoopbackServer(CreateOptions(options)); } public override async Task CreateServerAsync(Func funcAsync, int millisecondsTimeout = 60000, GenericLoopbackOptions options = null) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs index be1f072c1b72a..28ebca017e65e 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ServerCertificates.cs @@ -31,8 +31,8 @@ public abstract partial class HttpClientHandler_ServerCertificates_Test : HttpCl public HttpClientHandler_ServerCertificates_Test(ITestOutputHelper output) : base(output) { } // This enables customizing ServerCertificateCustomValidationCallback in WinHttpHandler variants: - protected bool AllowAllHttp2Certificates { get; set; } = true; - protected new HttpClientHandler CreateHttpClientHandler() => CreateHttpClientHandler(UseVersion, allowAllHttp2Certificates: AllowAllHttp2Certificates); + protected bool AllowAllCertificates { get; set; } = true; + protected new HttpClientHandler CreateHttpClientHandler() => CreateHttpClientHandler(UseVersion, allowAllCertificates: AllowAllCertificates); protected override HttpClient CreateHttpClient() => CreateHttpClient(CreateHttpClientHandler()); [Fact] @@ -393,19 +393,19 @@ public void HttpClientUsesSslCertEnvironmentVariables() File.WriteAllText(sslCertFile, ""); psi.Environment.Add("SSL_CERT_FILE", sslCertFile); - RemoteExecutor.Invoke(async (useVersionString, allowAllHttp2CertificatesString) => + RemoteExecutor.Invoke(async (useVersionString, allowAllCertificatesString) => { const string Url = "https://www.microsoft.com"; HttpClientHandler handler = CreateHttpClientHandler( Version.Parse(useVersionString), - allowAllHttp2Certificates: bool.Parse(allowAllHttp2CertificatesString)); + allowAllCertificates: bool.Parse(allowAllCertificatesString)); using (HttpClient client = CreateHttpClient(handler, useVersionString)) { await Assert.ThrowsAsync(() => client.GetAsync(Url)); } - }, UseVersion.ToString(), AllowAllHttp2Certificates.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose(); + }, UseVersion.ToString(), AllowAllCertificates.ToString(), new RemoteInvokeOptions { StartInfo = psi }).Dispose(); } } } diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/HttpClientHandlerTestBase.WinHttpHandler.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/HttpClientHandlerTestBase.WinHttpHandler.cs index 9c8289ec78934..ddbfecb2b15dc 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/HttpClientHandlerTestBase.WinHttpHandler.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/HttpClientHandlerTestBase.WinHttpHandler.cs @@ -10,13 +10,13 @@ public abstract partial class HttpClientHandlerTestBase : FileCleanupTestBase { protected static bool IsWinHttpHandler => true; - protected static WinHttpClientHandler CreateHttpClientHandler(Version useVersion = null, bool allowAllHttp2Certificates = true) + protected static WinHttpClientHandler CreateHttpClientHandler(Version useVersion = null, bool allowAllCertificates = true) { useVersion ??= HttpVersion.Version11; WinHttpClientHandler handler = new WinHttpClientHandler(useVersion); - if (useVersion >= HttpVersion20.Value && allowAllHttp2Certificates) + if (useVersion >= HttpVersion20.Value && allowAllCertificates) { handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; } diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs index 9e6d360d9ac7a..8e5c6524e6e73 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/PlatformHandlerTest.cs @@ -268,8 +268,9 @@ public sealed class PlatformHandler_HttpClientHandler_ServerCertificates_Http2_T { protected override Version UseVersion => HttpVersion20.Value; - public PlatformHandler_HttpClientHandler_ServerCertificates_Http2_Test(ITestOutputHelper output) : base(output) { - AllowAllHttp2Certificates = false; + public PlatformHandler_HttpClientHandler_ServerCertificates_Http2_Test(ITestOutputHelper output) : base(output) + { + AllowAllCertificates = false; } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs index 84d6ff8b345bb..7590fdaf60a4f 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System.IO; using System.Net.Quic; -using System.Net.Quic.Implementations; using System.Net.Security; using System.Net.Sockets; using System.Runtime.Versioning; @@ -105,19 +104,22 @@ public static async ValueTask EstablishSslConnectionAsync(SslClientAu [SupportedOSPlatform("windows")] [SupportedOSPlatform("linux")] [SupportedOSPlatform("macos")] - public static async ValueTask ConnectQuicAsync(HttpRequestMessage request, QuicImplementationProvider quicImplementationProvider, DnsEndPoint endPoint, SslClientAuthenticationOptions clientAuthenticationOptions, CancellationToken cancellationToken) + public static async ValueTask ConnectQuicAsync(HttpRequestMessage request, DnsEndPoint endPoint, SslClientAuthenticationOptions clientAuthenticationOptions, CancellationToken cancellationToken) { clientAuthenticationOptions = SetUpRemoteCertificateValidationCallback(clientAuthenticationOptions, request); - - QuicConnection con = new QuicConnection(quicImplementationProvider, endPoint, clientAuthenticationOptions); + QuicConnection connection = await QuicProvider.CreateConnectionAsync(new QuicClientConnectionOptions() + { + RemoteEndPoint = endPoint, + ClientAuthenticationOptions = clientAuthenticationOptions + }, cancellationToken).ConfigureAwait(false); try { - await con.ConnectAsync(cancellationToken).ConfigureAwait(false); - return con; + await connection.ConnectAsync(cancellationToken).ConfigureAwait(false); + return connection; } catch (Exception ex) { - con.Dispose(); + connection.Dispose(); throw CreateWrappedException(ex, endPoint.Host, endPoint.Port, cancellationToken); } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs index 22306fd911c9b..dff8f8e14c2f6 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs @@ -134,7 +134,7 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK if (IsHttp3Supported()) { - _http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30 && (_poolManager.Settings._quicImplementationProvider ?? QuicImplementationProviders.Default).IsSupported; + _http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30 && QuicProvider.IsSupported; } switch (kind) @@ -885,7 +885,7 @@ private async ValueTask GetHttp3ConnectionAsync(HttpRequestMess QuicConnection quicConnection; try { - quicConnection = await ConnectHelper.ConnectQuicAsync(request, Settings._quicImplementationProvider ?? QuicImplementationProviders.Default, new DnsEndPoint(authority.IdnHost, authority.Port), _sslOptionsHttp3!, cancellationToken).ConfigureAwait(false); + quicConnection = await ConnectHelper.ConnectQuicAsync(request, new DnsEndPoint(authority.IdnHost, authority.Port), _sslOptionsHttp3!, cancellationToken).ConfigureAwait(false); } catch (Exception e) { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs index 64476aa028663..f001392aba896 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Net.Security; using System.IO; -using System.Net.Quic.Implementations; using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; @@ -59,9 +58,6 @@ internal sealed class HttpConnectionSettings internal Func>? _connectCallback; internal Func>? _plaintextStreamFilter; - // !!! NOTE !!! This is temporary and will not ship. - internal QuicImplementationProvider? _quicImplementationProvider; - internal IDictionary? _properties; // Http2 flow control settings: @@ -123,12 +119,6 @@ public HttpConnectionSettings CloneAndNormalize() _defaultCredentialsUsedForServer = _credentials == CredentialCache.DefaultCredentials, }; - // TODO: Remove if/when QuicImplementationProvider is removed from System.Net.Quic. - if (HttpConnectionPool.IsHttp3Supported()) - { - settings._quicImplementationProvider = _quicImplementationProvider; - } - return settings; } diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs index 6cb8bbc075c2b..5cc4e1aad36bd 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.AltSvc.cs @@ -31,12 +31,6 @@ private HttpClient CreateHttpClient(Version version) [MemberData(nameof(AltSvcHeaderUpgradeVersions))] public async Task AltSvc_Header_Upgrade_Success(Version fromVersion, bool overrideHost) { - // [ActiveIssue("https://github.com/dotnet/runtime/issues/54050")] - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - // The test makes a request to a HTTP/1 or HTTP/2 server first, which supplies an Alt-Svc header pointing to the second server. using GenericLoopbackServer firstServer = fromVersion.Major switch @@ -48,7 +42,7 @@ public async Task AltSvc_Header_Upgrade_Success(Version fromVersion, bool overri // The second request is expected to come in on this HTTP/3 server. using Http3LoopbackServer secondServer = CreateHttp3LoopbackServer(); - + if (!overrideHost) Assert.Equal(firstServer.Address.IdnHost, secondServer.Address.IdnHost); @@ -80,12 +74,6 @@ public async Task AltSvc_Header_Upgrade_Success(Version fromVersion, bool overri [Fact] public async Task AltSvc_ConnectionFrame_UpgradeFrom20_Success() { - // [ActiveIssue("https://github.com/dotnet/runtime/issues/54050")] - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - using Http2LoopbackServer firstServer = Http2LoopbackServer.CreateServer(); using Http3LoopbackServer secondServer = CreateHttp3LoopbackServer(); using HttpClient client = CreateHttpClient(HttpVersion.Version20); @@ -111,12 +99,6 @@ public async Task AltSvc_ConnectionFrame_UpgradeFrom20_Success() [Fact] public async Task AltSvc_ResponseFrame_UpgradeFrom20_Success() { - // [ActiveIssue("https://github.com/dotnet/runtime/issues/54050")] - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - using Http2LoopbackServer firstServer = Http2LoopbackServer.CreateServer(); using Http3LoopbackServer secondServer = CreateHttp3LoopbackServer(); using HttpClient client = CreateHttpClient(HttpVersion.Version20); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs index 56c7345946dc9..0678869ef8250 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Finalization.cs @@ -29,11 +29,6 @@ private static Task GetAndDropResponse(HttpClient client, Uri url) [ActiveIssue("https://github.com/dotnet/runtime/issues/69870", TestPlatforms.Android)] public async Task IncompleteResponseStream_ResponseDropped_CancelsRequestToServer() { - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - using (HttpClient client = CreateHttpClient()) { bool stopGCs = false; diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs index 879dd78ce463d..b109ce2e11e74 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs @@ -19,7 +19,9 @@ namespace System.Net.Http.Functional.Tests { - public abstract class HttpClientHandlerTest_Http3 : HttpClientHandlerTestBase + [Collection(nameof(DisableParallelization))] + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class HttpClientHandlerTest_Http3 : HttpClientHandlerTestBase { protected override Version UseVersion => HttpVersion.Version30; @@ -161,13 +163,6 @@ public async Task SendStreamLimitRequestsConcurrently_Succeeds(int streamLimit) [InlineData(1000)] public async Task SendMoreThanStreamLimitRequestsConcurrently_LastWaits(int streamLimit) { - // This combination leads to a hang manifesting in CI only. Disabling it until there's more time to investigate. - // [ActiveIssue("https://github.com/dotnet/runtime/issues/53688")] - if (this.UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - using Http3LoopbackServer server = CreateHttp3LoopbackServer(new Http3Options() { MaxBidirectionalStreams = streamLimit }); var lastRequestContentStarted = new TaskCompletionSource(); @@ -423,12 +418,6 @@ public async Task RequestSendingResponseDisposed_ThrowsOnServer() [Fact] public async Task ServerCertificateCustomValidationCallback_Succeeds() { - // Mock doesn't make use of cart validation callback. - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - HttpRequestMessage? callbackRequest = null; int invocationCount = 0; @@ -565,15 +554,10 @@ public async Task DisposeHttpClient_Http3ConnectionIsClosed() } [OuterLoop] - [ConditionalTheory(nameof(IsMsQuicSupported))] + [ConditionalTheory(nameof(IsQuicSupported))] [MemberData(nameof(InteropUris))] public async Task Public_Interop_ExactVersion_Success(string uri) { - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - using HttpClient client = CreateHttpClient(); using HttpRequestMessage request = new HttpRequestMessage { @@ -589,15 +573,10 @@ public async Task Public_Interop_ExactVersion_Success(string uri) } [OuterLoop] - [ConditionalTheory(nameof(IsMsQuicSupported))] + [ConditionalTheory(nameof(IsQuicSupported))] [MemberData(nameof(InteropUrisWithContent))] public async Task Public_Interop_ExactVersion_BufferContent_Success(string uri) { - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - using HttpClient client = CreateHttpClient(); using HttpRequestMessage request = new HttpRequestMessage { @@ -616,18 +595,13 @@ public async Task Public_Interop_ExactVersion_BufferContent_Success(string uri) } [OuterLoop] - [ConditionalTheory(nameof(IsMsQuicSupported))] + [ConditionalTheory(nameof(IsQuicSupported))] [MemberData(nameof(InteropUris))] public async Task Public_Interop_Upgrade_Success(string uri) { - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - // Create the handler manually without passing in useVersion = Http3 to avoid using VersionHttpClientHandler, // because it overrides VersionPolicy on each request with RequestVersionExact (bypassing Alt-Svc code path completely). - using HttpClient client = CreateHttpClient(CreateHttpClientHandler(quicImplementationProvider: UseQuicImplementationProvider)); + using HttpClient client = CreateHttpClient(CreateHttpClientHandler()); // First request uses HTTP/1 or HTTP/2 and receives an Alt-Svc either by header or (with HTTP/2) by frame. @@ -667,16 +641,11 @@ public enum CancellationType CancellationToken } - [ConditionalTheory(nameof(IsMsQuicSupported))] + [ConditionalTheory(nameof(IsQuicSupported))] [InlineData(CancellationType.Dispose)] [InlineData(CancellationType.CancellationToken)] public async Task ResponseCancellation_ServerReceivesCancellation(CancellationType type) { - if (UseQuicImplementationProvider != QuicImplementationProviders.MsQuic) - { - return; - } - using Http3LoopbackServer server = CreateHttp3LoopbackServer(); using var clientDone = new SemaphoreSlim(0); @@ -757,11 +726,6 @@ public async Task ResponseCancellation_ServerReceivesCancellation(CancellationTy [Fact] public async Task ResponseCancellation_BothCancellationTokenAndDispose_Success() { - if (UseQuicImplementationProvider != QuicImplementationProviders.MsQuic) - { - return; - } - using Http3LoopbackServer server = CreateHttp3LoopbackServer(); using var clientDone = new SemaphoreSlim(0); @@ -841,15 +805,9 @@ private static async Task SendDataForever(Http3LoopbackStream stream) } } - [ConditionalFact(nameof(IsMsQuicSupported))] + [ConditionalFact(nameof(IsQuicSupported))] public async Task Alpn_H3_Success() { - // Mock doesn't use ALPN. - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - var options = new Http3Options() { Alpn = SslApplicationProtocol.Http3.ToString() }; using Http3LoopbackServer server = CreateHttp3LoopbackServer(options); @@ -881,15 +839,9 @@ public async Task Alpn_H3_Success() connection.Dispose(); } - [ConditionalFact(nameof(IsMsQuicSupported))] + [ConditionalFact(nameof(IsQuicSupported))] public async Task Alpn_NonH3_NegotiationFailure() { - // Mock doesn't use ALPN. - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - var options = new Http3Options() { Alpn = "h3-29" }; // anything other than "h3" using Http3LoopbackServer server = CreateHttp3LoopbackServer(options); @@ -951,7 +903,7 @@ private SslApplicationProtocol ExtractMsQuicNegotiatedAlpn(Http3LoopbackConnecti return (SslApplicationProtocol)alpn; } - [ConditionalTheory(nameof(IsMsQuicSupported))] + [ConditionalTheory(nameof(IsQuicSupported))] [MemberData(nameof(StatusCodesTestData))] public async Task StatusCodes_ReceiveSuccess(HttpStatusCode statusCode, bool qpackEncode) { @@ -1077,15 +1029,10 @@ public async Task EchoServerStreaming_DifferentMessageSize_Success(int messageSi connection.Dispose(); } - [ConditionalFact(nameof(IsMsQuicSupported))] + [ConditionalFact(nameof(IsQuicSupported))] [OuterLoop("Uses Task.Delay")] public async Task RequestContentStreaming_Timeout_BothClientAndServerReceiveCancellation() { - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - var message = new byte[1024]; var random = new Random(0); random.NextBytes(message); @@ -1147,14 +1094,9 @@ public async Task RequestContentStreaming_Timeout_BothClientAndServerReceiveCanc connection.Dispose(); } - [ConditionalFact(nameof(IsMsQuicSupported))] + [ConditionalFact(nameof(IsQuicSupported))] public async Task RequestContentStreaming_Cancellation_BothClientAndServerReceiveCancellation() { - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - var message = new byte[1024]; var random = new Random(0); random.NextBytes(message); @@ -1217,14 +1159,9 @@ public async Task RequestContentStreaming_Cancellation_BothClientAndServerReceiv connection.Dispose(); } - [ConditionalFact(nameof(IsMsQuicSupported))] + [ConditionalFact(nameof(IsQuicSupported))] public async Task DuplexStreaming_RequestCTCancellation_DoesNotApply() { - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - var message = new byte[1024]; var random = new Random(0); random.NextBytes(message); @@ -1303,16 +1240,11 @@ public async Task DuplexStreaming_RequestCTCancellation_DoesNotApply() connection.Dispose(); } - [ConditionalTheory(nameof(IsMsQuicSupported))] + [ConditionalTheory(nameof(IsQuicSupported))] [InlineData(true)] [InlineData(false)] public async Task DuplexStreaming_AbortByServer_StreamingCancelled(bool graceful) { - if (UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - var message = new byte[1024]; var random = new Random(0); random.NextBytes(message); diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs index 65030243c2f31..66d9d0b188433 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs @@ -3,7 +3,6 @@ using System.IO; using System.Net.Quic; -using System.Net.Quic.Implementations; using System.Net.Test.Common; using System.Reflection; using System.Threading.Tasks; @@ -14,15 +13,13 @@ public abstract partial class HttpClientHandlerTestBase : FileCleanupTestBase { protected static bool IsWinHttpHandler => false; - protected virtual QuicImplementationProvider UseQuicImplementationProvider => null; - - public static bool IsMsQuicSupported + public static bool IsQuicSupported { get { try { - return QuicImplementationProviders.MsQuic.IsSupported; + return QuicProvider.IsSupported; } catch (System.PlatformNotSupportedException) { @@ -35,33 +32,26 @@ public static bool IsMsQuicSupported public static bool IsMockQuicSupported => (OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS(); - protected static HttpClientHandler CreateHttpClientHandler(Version useVersion = null, QuicImplementationProvider quicImplementationProvider = null, bool allowAllHttp2Certificates = true) + protected static HttpClientHandler CreateHttpClientHandler(Version useVersion = null, bool allowAllCertificates = true) { useVersion ??= HttpVersion.Version11; HttpClientHandler handler = (PlatformDetection.SupportsAlpn && useVersion != HttpVersion.Version30) ? new HttpClientHandler() : new VersionHttpClientHandler(useVersion); - if (useVersion >= HttpVersion.Version20 && allowAllHttp2Certificates) + if (useVersion >= HttpVersion.Version20 && allowAllCertificates) { handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates; } - if (quicImplementationProvider != null) - { - SocketsHttpHandler socketsHttpHandler = (SocketsHttpHandler)GetUnderlyingSocketsHttpHandler(handler); - SetQuicImplementationProvider(socketsHttpHandler, quicImplementationProvider); - socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true; - } - return handler; } protected Http3LoopbackServer CreateHttp3LoopbackServer(Http3Options options = default) { - return new Http3LoopbackServer(UseQuicImplementationProvider, options); + return new Http3LoopbackServer(options); } - protected HttpClientHandler CreateHttpClientHandler() => CreateHttpClientHandler(UseVersion, UseQuicImplementationProvider); + protected HttpClientHandler CreateHttpClientHandler() => CreateHttpClientHandler(UseVersion); protected static HttpClientHandler CreateHttpClientHandler(string useVersionString) => CreateHttpClientHandler(Version.Parse(useVersionString)); @@ -73,14 +63,6 @@ protected static SocketsHttpHandler GetUnderlyingSocketsHttpHandler(HttpClientHa return (SocketsHttpHandler)field?.GetValue(handler); } - protected static void SetQuicImplementationProvider(SocketsHttpHandler handler, QuicImplementationProvider quicImplementationProvider) - { - FieldInfo settingsField = typeof(SocketsHttpHandler).GetField("_settings", BindingFlags.Instance | BindingFlags.NonPublic); - object settings = settingsField.GetValue(handler); - FieldInfo field = settings.GetType().GetField("_quicImplementationProvider", BindingFlags.Instance | BindingFlags.NonPublic); - field.SetValue(settings, quicImplementationProvider); - } - protected static HttpRequestMessage CreateRequest(HttpMethod method, Uri uri, Version version, bool exactVersion = false) => new HttpRequestMessage(method, uri) { @@ -88,18 +70,18 @@ protected static HttpRequestMessage CreateRequest(HttpMethod method, Uri uri, Ve VersionPolicy = exactVersion ? HttpVersionPolicy.RequestVersionExact : HttpVersionPolicy.RequestVersionOrLower }; - protected LoopbackServerFactory LoopbackServerFactory => GetFactoryForVersion(UseVersion, UseQuicImplementationProvider); + protected LoopbackServerFactory LoopbackServerFactory => GetFactoryForVersion(UseVersion); - protected static LoopbackServerFactory GetFactoryForVersion(string useVersion, QuicImplementationProvider quicImplementationProvider = null) => - GetFactoryForVersion(Version.Parse(useVersion), quicImplementationProvider); + protected static LoopbackServerFactory GetFactoryForVersion(string useVersion) => + GetFactoryForVersion(Version.Parse(useVersion)); - protected static LoopbackServerFactory GetFactoryForVersion(Version useVersion, QuicImplementationProvider quicImplementationProvider = null) + protected static LoopbackServerFactory GetFactoryForVersion(Version useVersion) { return useVersion.Major switch { #if NETCOREAPP #if HTTP3 - 3 => new Http3LoopbackServerFactory(quicImplementationProvider), + 3 => Http3LoopbackServerFactory.Singleton, #endif 2 => Http2LoopbackServerFactory.Singleton, #endif diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientMiniStressTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientMiniStressTest.cs index 4d26878c39252..4149c97843b28 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientMiniStressTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientMiniStressTest.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Net.Quic; -using System.Net.Quic.Implementations; using System.Net.Security; using System.Net.Sockets; using System.Net.Test.Common; @@ -32,21 +31,12 @@ public void CreateAndDestroyManyClients(int numClients) } } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandler_HttpClientMiniStress_Http3_MsQuic : HttpClientMiniStress + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class SocketsHttpHandler_HttpClientMiniStress_Http3 : HttpClientMiniStress { - public SocketsHttpHandler_HttpClientMiniStress_Http3_MsQuic(ITestOutputHelper output) : base(output) { } + public SocketsHttpHandler_HttpClientMiniStress_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] - public sealed class SocketsHttpHandler_HttpClientMiniStress_Http3_Mock : HttpClientMiniStress - { - public SocketsHttpHandler_HttpClientMiniStress_Http3_Mock(ITestOutputHelper output) : base(output) { } - protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } public sealed class SocketsHttpHandler_HttpClientMiniStress_Http2 : HttpClientMiniStress diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/ResponseStreamZeroByteReadTests.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/ResponseStreamZeroByteReadTests.cs index 0d0ca2b4af1d3..4909e8ca0f5b1 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/ResponseStreamZeroByteReadTests.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/ResponseStreamZeroByteReadTests.cs @@ -6,7 +6,6 @@ using System.IO.Tests; using System.Linq; using System.Net.Quic; -using System.Net.Quic.Implementations; using System.Net.Security; using System.Net.Test.Common; using System.Security.Authentication; @@ -210,25 +209,13 @@ public Http2ResponseStreamZeroByteReadTest(ITestOutputHelper output) : base(outp protected override Version UseVersion => HttpVersion.Version20; } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class Http3ResponseStreamZeroByteReadTest_MsQuic : ResponseStreamZeroByteReadTestBase + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class Http3ResponseStreamZeroByteReadTest : ResponseStreamZeroByteReadTestBase { - public Http3ResponseStreamZeroByteReadTest_MsQuic(ITestOutputHelper output) : base(output) { } + public Http3ResponseStreamZeroByteReadTest(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] - public sealed class Http3ResponseStreamZeroByteReadTest_Mock : ResponseStreamZeroByteReadTestBase - { - public Http3ResponseStreamZeroByteReadTest_Mock(ITestOutputHelper output) : base(output) { } - - protected override Version UseVersion => HttpVersion.Version30; - - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index 55ecefbe9473c..6248cf3c9ca54 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -6,7 +6,6 @@ using System.IO; using System.Linq; using System.Net.Quic; -using System.Net.Quic.Implementations; using System.Net.Security; using System.Net.Sockets; using System.Net.Test.Common; @@ -3505,128 +3504,52 @@ public SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http2(ITestOutputH protected override Version UseVersion => HttpVersion.Version20; } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandlerTest_Http3_MsQuic : HttpClientHandlerTest_Http3 + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class SocketsHttpHandlerTest_HttpClientHandlerTest_Http3 : HttpClientHandlerTest { - public SocketsHttpHandlerTest_Http3_MsQuic(ITestOutputHelper output) : base(output) { } - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandlerTest_Http3_Mock : HttpClientHandlerTest_Http3 - { - public SocketsHttpHandlerTest_Http3_Mock(ITestOutputHelper output) : base(output) { } - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandlerTest_HttpClientHandlerTest_Http3_MsQuic : HttpClientHandlerTest - { - public SocketsHttpHandlerTest_HttpClientHandlerTest_Http3_MsQuic(ITestOutputHelper output) : base(output) { } - protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandlerTest_HttpClientHandlerTest_Http3_Mock : HttpClientHandlerTest - { - public SocketsHttpHandlerTest_HttpClientHandlerTest_Http3_Mock(ITestOutputHelper output) : base(output) { } - protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandlerTest_Cookies_Http3_MsQuic : HttpClientHandlerTest_Cookies - { - public SocketsHttpHandlerTest_Cookies_Http3_MsQuic(ITestOutputHelper output) : base(output) { } - protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandlerTest_Cookies_Http3_Mock : HttpClientHandlerTest_Cookies - { - public SocketsHttpHandlerTest_Cookies_Http3_Mock(ITestOutputHelper output) : base(output) { } - protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http3_MsQuic : HttpClientHandlerTest_Headers - { - public SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http3_MsQuic(ITestOutputHelper output) : base(output) { } - protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http3_Mock : HttpClientHandlerTest_Headers - { - public SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http3_Mock(ITestOutputHelper output) : base(output) { } - protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3_MsQuic : SocketsHttpHandler_Cancellation_Test - { - public SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3_MsQuic(ITestOutputHelper output) : base(output) { } + public SocketsHttpHandlerTest_HttpClientHandlerTest_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3_Mock : SocketsHttpHandler_Cancellation_Test + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class SocketsHttpHandlerTest_Cookies_Http3 : HttpClientHandlerTest_Cookies { - public SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3_Mock(ITestOutputHelper output) : base(output) { } + public SocketsHttpHandlerTest_Cookies_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3_MsQuic : HttpClientHandler_AltSvc_Test + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http3 : HttpClientHandlerTest_Headers { - public SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3_MsQuic(ITestOutputHelper output) : base(output) { } + public SocketsHttpHandlerTest_HttpClientHandlerTest_Headers_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3_Mock : HttpClientHandler_AltSvc_Test + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3 : SocketsHttpHandler_Cancellation_Test { - public SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3_Mock(ITestOutputHelper output) : base(output) { } + public SocketsHttpHandler_HttpClientHandler_Cancellation_Test_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandler_HttpClientHandler_Finalization_Http3_MsQuic : HttpClientHandler_Finalization_Test + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3 : HttpClientHandler_AltSvc_Test { - public SocketsHttpHandler_HttpClientHandler_Finalization_Http3_MsQuic(ITestOutputHelper output) : base(output) { } + public SocketsHttpHandler_HttpClientHandler_AltSvc_Test_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class SocketsHttpHandler_HttpClientHandler_Finalization_Http3_Mock : HttpClientHandler_Finalization_Test + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class SocketsHttpHandler_HttpClientHandler_Finalization_Http3 : HttpClientHandler_Finalization_Test { - public SocketsHttpHandler_HttpClientHandler_Finalization_Http3_Mock(ITestOutputHelper output) : base(output) { } + public SocketsHttpHandler_HttpClientHandler_Finalization_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; } [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] @@ -3787,12 +3710,11 @@ public SocketsHttpHandler_RequestContentLengthMismatchTest_Http2(ITestOutputHelp protected override Version UseVersion => HttpVersion.Version20; } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] public sealed class SocketsHttpHandler_RequestContentLengthMismatchTest_Http3 : SocketsHttpHandler_RequestContentLengthMismatchTest { public SocketsHttpHandler_RequestContentLengthMismatchTest_Http3(ITestOutputHelper output) : base(output) { } protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; } public class MySsl : SslStream diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs index cd01207bf714a..6f31d7088501b 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/TelemetryTest.cs @@ -7,7 +7,6 @@ using System.IO; using System.Linq; using System.Net.Quic; -using System.Net.Quic.Implementations; using System.Net.Test.Common; using System.Text; using System.Threading; @@ -22,13 +21,6 @@ public abstract class TelemetryTest : HttpClientHandlerTestBase { public TelemetryTest(ITestOutputHelper output) : base(output) { } - private string QuicImplementationProvider => UseQuicImplementationProvider?.GetType().Name ?? string.Empty; - - private static QuicImplementationProvider GetQuicImplementationProvider(string provider) => - provider.Contains(nameof(QuicImplementationProviders.MsQuic)) ? QuicImplementationProviders.MsQuic : - provider.Contains(nameof(QuicImplementationProviders.Mock)) ? QuicImplementationProviders.Mock : - null; - [Fact] public static void EventSource_ExistsWithCorrectId() { @@ -67,7 +59,7 @@ public void EventSource_SuccessfulRequest_LogsStartStop(string testMethod) return; } - RemoteExecutor.Invoke(static async (useVersionString, quicProvider, testMethod) => + RemoteExecutor.Invoke(static async (useVersionString, testMethod) => { const int ResponseContentLength = 42; @@ -79,10 +71,10 @@ public void EventSource_SuccessfulRequest_LogsStartStop(string testMethod) var events = new ConcurrentQueue<(EventWrittenEventArgs Event, Guid ActivityId)>(); await listener.RunWithCallbackAsync(e => events.Enqueue((e, e.ActivityId)), async () => { - await GetFactoryForVersion(version, GetQuicImplementationProvider(quicProvider)).CreateClientAndServerAsync( + await GetFactoryForVersion(version).CreateClientAndServerAsync( async uri => { - using HttpClientHandler handler = CreateHttpClientHandler(version, GetQuicImplementationProvider(quicProvider)); + using HttpClientHandler handler = CreateHttpClientHandler(version); using HttpClient client = CreateHttpClient(handler, useVersionString); using var invoker = new HttpMessageInvoker(handler); @@ -194,7 +186,7 @@ await server.AcceptConnectionAsync(async connection => count: 1); ValidateEventCounters(events, requestCount: 1, shouldHaveFailures: false, versionMajor: version.Major); - }, UseVersion.ToString(), QuicImplementationProvider, testMethod).Dispose(); + }, UseVersion.ToString(), testMethod).Dispose(); } [OuterLoop] @@ -208,7 +200,7 @@ public void EventSource_UnsuccessfulRequest_LogsStartFailedStop(string testMetho return; } - RemoteExecutor.Invoke(static async (useVersionString, quicProvider, testMethod) => + RemoteExecutor.Invoke(static async (useVersionString, testMethod) => { Version version = Version.Parse(useVersionString); using var listener = new TestEventListener("System.Net.Http", EventLevel.Verbose, eventCounterInterval: 0.1d); @@ -220,10 +212,10 @@ await listener.RunWithCallbackAsync(e => events.Enqueue((e, e.ActivityId)), asyn var semaphore = new SemaphoreSlim(0, 1); var cts = new CancellationTokenSource(); - await GetFactoryForVersion(version, GetQuicImplementationProvider(quicProvider)).CreateClientAndServerAsync( + await GetFactoryForVersion(version).CreateClientAndServerAsync( async uri => { - using HttpClientHandler handler = CreateHttpClientHandler(version, GetQuicImplementationProvider(quicProvider)); + using HttpClientHandler handler = CreateHttpClientHandler(version); using HttpClient client = CreateHttpClient(handler, useVersionString); using var invoker = new HttpMessageInvoker(handler); @@ -297,7 +289,7 @@ await server.AcceptConnectionAsync(async connection => ValidateConnectionEstablishedClosed(events, version); ValidateEventCounters(events, requestCount: 1, shouldHaveFailures: true, versionMajor: version.Major); - }, UseVersion.ToString(), QuicImplementationProvider, testMethod).Dispose(); + }, UseVersion.ToString(), testMethod).Dispose(); } [OuterLoop] @@ -316,7 +308,7 @@ public void EventSource_SendingRequestContent_LogsRequestContentStartStop(string return; } - RemoteExecutor.Invoke(static async (useVersionString, quicProvider, testMethod) => + RemoteExecutor.Invoke(static async (useVersionString, testMethod) => { const int RequestContentLength = 42; const int ResponseContentLength = 43; @@ -328,10 +320,10 @@ public void EventSource_SendingRequestContent_LogsRequestContentStartStop(string var events = new ConcurrentQueue<(EventWrittenEventArgs Event, Guid ActivityId)>(); await listener.RunWithCallbackAsync(e => events.Enqueue((e, e.ActivityId)), async () => { - await GetFactoryForVersion(version, GetQuicImplementationProvider(quicProvider)).CreateClientAndServerAsync( + await GetFactoryForVersion(version).CreateClientAndServerAsync( async uri => { - using HttpClientHandler handler = CreateHttpClientHandler(version, GetQuicImplementationProvider(quicProvider)); + using HttpClientHandler handler = CreateHttpClientHandler(version); using HttpClient client = CreateHttpClient(handler, useVersionString); using var invoker = new HttpMessageInvoker(handler); @@ -398,7 +390,7 @@ await server.AcceptConnectionAsync(async connection => count: 1); ValidateEventCounters(events, requestCount: 1, shouldHaveFailures: false, versionMajor: version.Major); - }, UseVersion.ToString(), QuicImplementationProvider, testMethod).Dispose(); + }, UseVersion.ToString(), testMethod).Dispose(); } private static void ValidateStartFailedStopEvents(ConcurrentQueue<(EventWrittenEventArgs Event, Guid ActivityId)> events, Version version, bool shouldHaveFailures = false, int count = 1) @@ -618,12 +610,7 @@ private static void ValidateEventCounters(ConcurrentQueue<(EventWrittenEventArgs [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void EventSource_ConnectionPoolAtMaxConnections_LogsRequestLeftQueue() { - if (UseVersion.Major == 3 && UseQuicImplementationProvider == QuicImplementationProviders.Mock) - { - return; - } - - RemoteExecutor.Invoke(static async (useVersionString, quicProvider) => + RemoteExecutor.Invoke(static async (useVersionString) => { Version version = Version.Parse(useVersionString); using var listener = new TestEventListener("System.Net.Http", EventLevel.Verbose, eventCounterInterval: 0.1d); @@ -636,10 +623,10 @@ await listener.RunWithCallbackAsync(e => events.Enqueue((e, e.ActivityId)), asyn var secondRequestSent = new SemaphoreSlim(0, 1); var firstRequestFinished = new SemaphoreSlim(0, 1); - await GetFactoryForVersion(version, GetQuicImplementationProvider(quicProvider)).CreateClientAndServerAsync( + await GetFactoryForVersion(version).CreateClientAndServerAsync( async uri => { - using HttpClientHandler handler = CreateHttpClientHandler(version, GetQuicImplementationProvider(quicProvider)); + using HttpClientHandler handler = CreateHttpClientHandler(version); using HttpClient client = CreateHttpClient(handler, useVersionString); var socketsHttpHandler = GetUnderlyingSocketsHttpHandler(handler); @@ -729,7 +716,7 @@ await GetFactoryForVersion(version, GetQuicImplementationProvider(quicProvider)) ValidateRequestResponseStartStopEvents(events, requestContentLength: null, responseContentLength: 0, count: 3); ValidateEventCounters(events, requestCount: 3, shouldHaveFailures: false, versionMajor: version.Major, requestLeftQueue: true); - }, UseVersion.ToString(), QuicImplementationProvider).Dispose(); + }, UseVersion.ToString()).Dispose(); } private static async Task WaitForEventCountersAsync(ConcurrentQueue<(EventWrittenEventArgs Event, Guid ActivityId)> events) @@ -768,20 +755,11 @@ public sealed class TelemetryTest_Http20 : TelemetryTest public TelemetryTest_Http20(ITestOutputHelper output) : base(output) { } } - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMsQuicSupported))] [Collection(nameof(DisableParallelization))] - public sealed class TelemetryTest_Http30_MsQuic : TelemetryTest - { - protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.MsQuic; - public TelemetryTest_Http30_MsQuic(ITestOutputHelper output) : base(output) { } - } - - [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsMockQuicSupported))] - public sealed class TelemetryTest_Http30_Mock : TelemetryTest + [ConditionalClass(typeof(HttpClientHandlerTestBase), nameof(IsQuicSupported))] + public sealed class TelemetryTest_Http30 : TelemetryTest { protected override Version UseVersion => HttpVersion.Version30; - protected override QuicImplementationProvider UseQuicImplementationProvider => QuicImplementationProviders.Mock; - public TelemetryTest_Http30_Mock(ITestOutputHelper output) : base(output) { } + public TelemetryTest_Http30(ITestOutputHelper output) : base(output) { } } } diff --git a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs index e42d4f40c9dd1..dd9addfac5c56 100644 --- a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs +++ b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs @@ -15,10 +15,7 @@ public QuicClientConnectionOptions() { } } public sealed partial class QuicConnection : System.IDisposable { - public QuicConnection(System.Net.EndPoint remoteEndPoint, System.Net.Security.SslClientAuthenticationOptions? sslClientAuthenticationOptions, System.Net.IPEndPoint? localEndPoint = null) { } - public QuicConnection(System.Net.Quic.Implementations.QuicImplementationProvider implementationProvider, System.Net.EndPoint remoteEndPoint, System.Net.Security.SslClientAuthenticationOptions? sslClientAuthenticationOptions, System.Net.IPEndPoint? localEndPoint = null) { } - public QuicConnection(System.Net.Quic.Implementations.QuicImplementationProvider implementationProvider, System.Net.Quic.QuicClientConnectionOptions options) { } - public QuicConnection(System.Net.Quic.QuicClientConnectionOptions options) { } + internal QuicConnection() { } public bool Connected { get { throw null; } } public System.Net.IPEndPoint? LocalEndPoint { get { throw null; } } public System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get { throw null; } } @@ -44,18 +41,9 @@ public QuicException(string? message) { } public QuicException(string? message, System.Exception? innerException) { } public QuicException(string? message, System.Exception? innerException, int result) { } } - public static partial class QuicImplementationProviders - { - public static System.Net.Quic.Implementations.QuicImplementationProvider Default { get { throw null; } } - public static System.Net.Quic.Implementations.QuicImplementationProvider Mock { get { throw null; } } - public static System.Net.Quic.Implementations.QuicImplementationProvider MsQuic { get { throw null; } } - } public sealed partial class QuicListener : System.IDisposable { - public QuicListener(System.Net.IPEndPoint listenEndPoint, System.Net.Security.SslServerAuthenticationOptions sslServerAuthenticationOptions) { } - public QuicListener(System.Net.Quic.Implementations.QuicImplementationProvider implementationProvider, System.Net.IPEndPoint listenEndPoint, System.Net.Security.SslServerAuthenticationOptions sslServerAuthenticationOptions) { } - public QuicListener(System.Net.Quic.Implementations.QuicImplementationProvider implementationProvider, System.Net.Quic.QuicListenerOptions options) { } - public QuicListener(System.Net.Quic.QuicListenerOptions options) { } + internal QuicListener() { } public System.Net.IPEndPoint ListenEndPoint { get { throw null; } } public System.Threading.Tasks.ValueTask AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public void Dispose() { } @@ -78,6 +66,12 @@ public QuicOptions() { } public int MaxBidirectionalStreams { get { throw null; } set { } } public int MaxUnidirectionalStreams { get { throw null; } set { } } } + public static partial class QuicProvider + { + public static bool IsSupported { get { throw null; } } + public static System.Threading.Tasks.ValueTask CreateConnectionAsync(System.Net.Quic.QuicClientConnectionOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask CreateListenerAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + } public sealed partial class QuicStream : System.IO.Stream { internal QuicStream() { } @@ -127,11 +121,3 @@ public QuicStreamAbortedException(string message, long errorCode) : base (defaul public long ErrorCode { get { throw null; } } } } -namespace System.Net.Quic.Implementations -{ - public abstract partial class QuicImplementationProvider - { - internal QuicImplementationProvider() { } - public abstract bool IsSupported { get; } - } -} diff --git a/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt b/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt index ce5cc364f6ec7..25cbd3f4511f6 100644 --- a/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt +++ b/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt @@ -1 +1 @@ -C:System.Net.Quic.QuicImplementationProviders \ No newline at end of file +P:System.Net.Quic.QuicProvider.IsSupported \ No newline at end of file diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index 39d6fbb45e798..234ad7272a8d9 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -18,7 +18,7 @@ - + @@ -26,7 +26,6 @@ - @@ -43,7 +42,7 @@ - + diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs deleted file mode 100644 index 63cf03e3d2ba6..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs +++ /dev/null @@ -1,484 +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.Diagnostics; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.ExceptionServices; -using System.Threading; -using System.Threading.Channels; -using System.Threading.Tasks; -using System.Collections.Concurrent; -using System.Collections.Generic; - -namespace System.Net.Quic.Implementations.Mock -{ - internal sealed class MockConnection : QuicConnectionProvider - { - private readonly bool _isClient; - private bool _disposed; - private SslClientAuthenticationOptions? _sslClientAuthenticationOptions; - private IPEndPoint _remoteEndPoint; - private IPEndPoint _localEndPoint; - private object _syncObject = new object(); - private long _nextOutboundBidirectionalStream; - private long _nextOutboundUnidirectionalStream; - private readonly int _maxUnidirectionalStreams; - private readonly int _maxBidirectionalStreams; - - private ConnectionState? _state; - - internal PeerStreamLimit? LocalStreamLimit => _isClient ? _state?._clientStreamLimit : _state?._serverStreamLimit; - internal PeerStreamLimit? RemoteStreamLimit => _isClient ? _state?._serverStreamLimit : _state?._clientStreamLimit; - - internal long? ConnectionError - { - get - { - long? errorCode = _isClient ? _state?._serverErrorCode : _state?._clientErrorCode; - if (errorCode == -1) - { - errorCode = null; - } - - return errorCode; - } - } - - internal override X509Certificate? RemoteCertificate => null; - - // Constructor for outbound connections - internal MockConnection(EndPoint remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null, int maxUnidirectionalStreams = 100, int maxBidirectionalStreams = 100) - { - ArgumentNullException.ThrowIfNull(remoteEndPoint); - - IPEndPoint ipEndPoint = GetIPEndPoint(remoteEndPoint); - if (ipEndPoint.Address != IPAddress.Loopback) - { - throw new ArgumentException("Expected loopback address", nameof(remoteEndPoint)); - } - - _isClient = true; - _remoteEndPoint = ipEndPoint; - _localEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - _sslClientAuthenticationOptions = sslClientAuthenticationOptions; - _nextOutboundBidirectionalStream = 0; - _nextOutboundUnidirectionalStream = 2; - _maxUnidirectionalStreams = maxUnidirectionalStreams; - _maxBidirectionalStreams = maxBidirectionalStreams; - - // _state is not initialized until ConnectAsync - } - - // Constructor for accepted inbound connections - internal MockConnection(IPEndPoint localEndPoint, ConnectionState state) - { - _isClient = false; - _remoteEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - _localEndPoint = localEndPoint; - - _nextOutboundBidirectionalStream = 1; - _nextOutboundUnidirectionalStream = 3; - - _state = state; - } - - private static IPEndPoint GetIPEndPoint(EndPoint endPoint) - { - if (endPoint is IPEndPoint ipEndPoint) - { - return ipEndPoint; - } - - if (endPoint is DnsEndPoint dnsEndPoint) - { - if (dnsEndPoint.Host == "127.0.0.1") - { - return new IPEndPoint(IPAddress.Loopback, dnsEndPoint.Port); - } - - throw new InvalidOperationException($"invalid DNS name {dnsEndPoint.Host}"); - } - - throw new InvalidOperationException("unknown EndPoint type"); - } - - internal override bool Connected - { - get - { - CheckDisposed(); - - return _state != null; - } - } - - // TODO: Should clone the endpoint since it is mutable - // TODO: could this be made back to non-nullable? - // For inbound we have it immediately, for outbound after connect. - internal override IPEndPoint? LocalEndPoint => _localEndPoint; - - // TODO: Should clone the endpoint since it is mutable - internal override EndPoint RemoteEndPoint => _remoteEndPoint!; - - internal override SslApplicationProtocol NegotiatedApplicationProtocol - { - get - { - if (_state is null) - { - throw new InvalidOperationException("not connected"); - } - - return _state._applicationProtocol; - } - } - - internal override ValueTask ConnectAsync(CancellationToken cancellationToken = default) - { - CheckDisposed(); - - if (Connected) - { - throw new InvalidOperationException("Already connected"); - } - - Debug.Assert(_isClient, "not connected but also not _isClient??"); - - MockListener? listener = MockListener.TryGetListener(_remoteEndPoint); - if (listener is null) - { - throw new InvalidOperationException("Could not find listener"); - } - - // TODO: deal with protocol negotiation - _state = new ConnectionState(_sslClientAuthenticationOptions!.ApplicationProtocols![0]) - { - _clientStreamLimit = new PeerStreamLimit(_maxUnidirectionalStreams, _maxBidirectionalStreams) - }; - if (!listener.TryConnect(_state)) - { - throw new QuicException("Connection refused"); - } - - return ValueTask.CompletedTask; - } - - internal override async ValueTask OpenUnidirectionalStreamAsync(CancellationToken cancellationToken) - { - PeerStreamLimit? streamLimit = RemoteStreamLimit; - if (streamLimit is null) - { - throw new InvalidOperationException("Not connected"); - } - - while (!streamLimit.Unidirectional.TryIncrement()) - { - await streamLimit.Unidirectional.WaitForAvailableStreams(cancellationToken).ConfigureAwait(false); - } - - long streamId; - lock (_syncObject) - { - streamId = _nextOutboundUnidirectionalStream; - _nextOutboundUnidirectionalStream += 4; - } - - return OpenStream(streamId, false); - } - - internal override async ValueTask OpenBidirectionalStreamAsync(CancellationToken cancellationToken) - { - PeerStreamLimit? streamLimit = RemoteStreamLimit; - if (streamLimit is null) - { - throw new InvalidOperationException("Not connected"); - } - - while (!streamLimit.Bidirectional.TryIncrement()) - { - await streamLimit.Bidirectional.WaitForAvailableStreams(cancellationToken).ConfigureAwait(false); - } - - long streamId; - lock (_syncObject) - { - streamId = _nextOutboundBidirectionalStream; - _nextOutboundBidirectionalStream += 4; - } - - return OpenStream(streamId, true); - } - - internal MockStream OpenStream(long streamId, bool bidirectional) - { - CheckDisposed(); - - ConnectionState? state = _state; - if (state is null) - { - throw new InvalidOperationException("Not connected"); - } - - MockStream.StreamState streamState = new MockStream.StreamState(streamId, bidirectional); - // TODO Streams are never removed from a connection. Consider cleaning up in the future. - state._streams[streamState._streamId] = streamState; - - Channel streamChannel = _isClient ? state._clientInitiatedStreamChannel : state._serverInitiatedStreamChannel; - streamChannel.Writer.TryWrite(streamState); - - return new MockStream(this, streamState, true); - } - - internal override int GetRemoteAvailableUnidirectionalStreamCount() - { - PeerStreamLimit? streamLimit = RemoteStreamLimit; - if (streamLimit is null) - { - throw new InvalidOperationException("Not connected"); - } - - return streamLimit.Unidirectional.AvailableCount; - } - - internal override int GetRemoteAvailableBidirectionalStreamCount() - { - PeerStreamLimit? streamLimit = RemoteStreamLimit; - if (streamLimit is null) - { - throw new InvalidOperationException("Not connected"); - } - - return streamLimit.Bidirectional.AvailableCount; - } - - internal override async ValueTask AcceptStreamAsync(CancellationToken cancellationToken = default) - { - CheckDisposed(); - - ConnectionState? state = _state; - if (state is null) - { - throw new InvalidOperationException("Not connected"); - } - - Channel streamChannel = _isClient ? state._serverInitiatedStreamChannel : state._clientInitiatedStreamChannel; - - try - { - MockStream.StreamState streamState = await streamChannel.Reader.ReadAsync(cancellationToken).ConfigureAwait(false); - return new MockStream(this, streamState, false); - } - catch (ChannelClosedException) - { - long errorCode = _isClient ? state._serverErrorCode : state._clientErrorCode; - throw (errorCode == -1) ? new QuicOperationAbortedException() : new QuicConnectionAbortedException(errorCode); - } - } - - internal override ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default) - { - // TODO: We should abort local streams (and signal the peer to do likewise) - // Currently, we are not tracking the streams associated with this connection. - - ConnectionState? state = _state; - if (state is not null) - { - if (state._closed) - { - return default; - } - state._closed = true; - - if (_isClient) - { - state._clientErrorCode = errorCode; - DrainAcceptQueue(-1, errorCode); - } - else - { - state._serverErrorCode = errorCode; - DrainAcceptQueue(errorCode, -1); - } - - foreach (KeyValuePair kvp in state._streams) - { - kvp.Value._outboundWritesCompletedTcs.TrySetException(new QuicConnectionAbortedException(errorCode)); - kvp.Value._inboundWritesCompletedTcs.TrySetException(new QuicConnectionAbortedException(errorCode)); - } - } - - Dispose(); - - return default; - } - - private void CheckDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(nameof(QuicConnection)); - } - } - - private void DrainAcceptQueue(long outboundErrorCode, long inboundErrorCode) - { - ConnectionState? state = _state; - if (state is not null) - { - // TODO: We really only need to do the complete and drain once, but it doesn't really hurt to do it twice. - state._clientInitiatedStreamChannel.Writer.TryComplete(); - while (state._clientInitiatedStreamChannel.Reader.TryRead(out MockStream.StreamState? streamState)) - { - streamState._outboundReadErrorCode = streamState._outboundWriteErrorCode = outboundErrorCode; - streamState._inboundStreamBuffer?.AbortRead(); - streamState._outboundStreamBuffer?.EndWrite(); - } - - state._serverInitiatedStreamChannel.Writer.TryComplete(); - while (state._serverInitiatedStreamChannel.Reader.TryRead(out MockStream.StreamState? streamState)) - { - streamState._inboundReadErrorCode = streamState._inboundWriteErrorCode = inboundErrorCode; - streamState._outboundStreamBuffer?.AbortRead(); - streamState._inboundStreamBuffer?.EndWrite(); - } - } - } - - private void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - DrainAcceptQueue(-1, -1); - - PeerStreamLimit? streamLimit = LocalStreamLimit; - if (streamLimit is not null) - { - streamLimit.Unidirectional.CloseWaiters(); - streamLimit.Bidirectional.CloseWaiters(); - } - } - - // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. - // TODO: set large fields to null. - - _disposed = true; - } - } - - ~MockConnection() - { - Dispose(false); - } - - public override void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - internal sealed class StreamLimit - { - public readonly int MaxCount; - - private int _actualCount; - // Since this is mock, we don't need to be conservative with the allocations. - // We keep the TCSes allocated all the time for the simplicity of the code. - private TaskCompletionSource _availableTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - private readonly object _syncRoot = new object(); - - public StreamLimit(int maxCount) - { - MaxCount = maxCount; - } - - public int AvailableCount => MaxCount - _actualCount; - - public void Decrement() - { - TaskCompletionSource? availableTcs = null; - lock (_syncRoot) - { - --_actualCount; - if (!_availableTcs.Task.IsCompleted) - { - availableTcs = _availableTcs; - _availableTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - } - } - if (availableTcs is not null) - { - availableTcs.SetResult(); - } - } - - public bool TryIncrement() - { - lock (_syncRoot) - { - if (_actualCount < MaxCount) - { - ++_actualCount; - return true; - } - return false; - } - } - - public ValueTask WaitForAvailableStreams(CancellationToken cancellationToken) - { - TaskCompletionSource availableTcs; - lock (_syncRoot) - { - if (_actualCount > 0) - { - return default; - } - availableTcs = _availableTcs; - } - return new ValueTask(availableTcs.Task.WaitAsync(cancellationToken)); - } - - public void CloseWaiters() - => _availableTcs.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException())); - } - - internal sealed class PeerStreamLimit - { - public readonly StreamLimit Unidirectional; - public readonly StreamLimit Bidirectional; - - public PeerStreamLimit(int maxUnidirectional, int maxBidirectional) - { - Unidirectional = new StreamLimit(maxUnidirectional); - Bidirectional = new StreamLimit(maxBidirectional); - } - } - - internal sealed class ConnectionState - { - public readonly SslApplicationProtocol _applicationProtocol; - public readonly Channel _clientInitiatedStreamChannel; - public readonly Channel _serverInitiatedStreamChannel; - public readonly ConcurrentDictionary _streams; - - public PeerStreamLimit? _clientStreamLimit; - public PeerStreamLimit? _serverStreamLimit; - - public long _clientErrorCode; - public long _serverErrorCode; - public bool _closed; - - public ConnectionState(SslApplicationProtocol applicationProtocol) - { - _applicationProtocol = applicationProtocol; - _clientInitiatedStreamChannel = Channel.CreateUnbounded(); - _serverInitiatedStreamChannel = Channel.CreateUnbounded(); - _clientErrorCode = _serverErrorCode = -1; - _streams = new ConcurrentDictionary(); - } - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockImplementationProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockImplementationProvider.cs deleted file mode 100644 index d43fad609913d..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockImplementationProvider.cs +++ /dev/null @@ -1,26 +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.Security; - -namespace System.Net.Quic.Implementations.Mock -{ - internal sealed class MockImplementationProvider : QuicImplementationProvider - { - public override bool IsSupported => true; - - internal override QuicListenerProvider CreateListener(QuicListenerOptions options) - { - return new MockListener(options); - } - - internal override QuicConnectionProvider CreateConnection(QuicClientConnectionOptions options) - { - return new MockConnection(options.RemoteEndPoint!, - options.ClientAuthenticationOptions, - options.LocalEndPoint, - options.MaxUnidirectionalStreams, - options.MaxBidirectionalStreams); - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockListener.cs deleted file mode 100644 index 1be3400505174..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockListener.cs +++ /dev/null @@ -1,114 +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.Collections.Concurrent; -using System.Diagnostics; -using System.Threading; -using System.Threading.Channels; -using System.Threading.Tasks; - -namespace System.Net.Quic.Implementations.Mock -{ - internal sealed class MockListener : QuicListenerProvider - { - private bool _disposed; - private readonly QuicListenerOptions _options; - private readonly IPEndPoint _listenEndPoint; - private Channel _listenQueue; - - // We synthesize port numbers for the listener, starting with 1, and track these in a dictionary. - private static int s_mockPort; - private static ConcurrentDictionary s_listenerMap = new ConcurrentDictionary(); - - internal MockListener(QuicListenerOptions options) - { - if (options.ListenEndPoint is null || (options.ListenEndPoint.Address != IPAddress.Loopback && options.ListenEndPoint.Address != IPAddress.IPv6Loopback) || options.ListenEndPoint.Port != 0) - { - throw new ArgumentException("Must pass loopback address and port 0"); - } - - _options = options; - - int port = Interlocked.Increment(ref s_mockPort); - - _listenEndPoint = new IPEndPoint(IPAddress.Loopback, port); - bool success = s_listenerMap.TryAdd(port, this); - Debug.Assert(success); - - _listenQueue = Channel.CreateBounded(new BoundedChannelOptions(options.ListenBacklog)); - } - - // TODO: IPEndPoint is mutable, so we should create a copy here. - internal override IPEndPoint ListenEndPoint => _listenEndPoint; - - internal static MockListener? TryGetListener(IPEndPoint endpoint) - { - if (endpoint.Address != IPAddress.Loopback || endpoint.Port == 0) - { - return null; - } - - MockListener? listener; - if (!s_listenerMap.TryGetValue(endpoint.Port, out listener)) - { - return null; - } - - return listener; - } - - internal override async ValueTask AcceptConnectionAsync(CancellationToken cancellationToken = default) - { - CheckDisposed(); - - MockConnection.ConnectionState state = await _listenQueue.Reader.ReadAsync(cancellationToken).ConfigureAwait(false); - - return new MockConnection(_listenEndPoint, state); - } - - // Returns false if backlog queue is full. - internal bool TryConnect(MockConnection.ConnectionState state) - { - state._serverStreamLimit = new MockConnection.PeerStreamLimit(_options.MaxUnidirectionalStreams, _options.MaxBidirectionalStreams); - return _listenQueue.Writer.TryWrite(state); - } - - private void CheckDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(nameof(QuicListener)); - } - } - - private void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - MockListener? listener; - bool success = s_listenerMap.TryRemove(_listenEndPoint.Port, out listener); - Debug.Assert(success); - Debug.Assert(listener == this); - } - - // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. - // TODO: set large fields to null. - - _disposed = true; - } - } - - ~MockListener() - { - Dispose(false); - } - - public override void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs deleted file mode 100644 index f68c0972fb06c..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs +++ /dev/null @@ -1,338 +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.Buffers; -using System.Diagnostics; -using System.IO; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace System.Net.Quic.Implementations.Mock -{ - internal sealed class MockStream : QuicStreamProvider - { - private bool _disposed; - private readonly bool _isInitiator; - private readonly MockConnection _connection; - - private readonly StreamState _streamState; - private bool _writesCanceled; - - internal MockStream(MockConnection connection, StreamState streamState, bool isInitiator) - { - _connection = connection; - _streamState = streamState; - _isInitiator = isInitiator; - } - - private static ValueTask ConnectAsync(CancellationToken cancellationToken = default) - { - return ValueTask.CompletedTask; - } - - internal override long StreamId - { - get - { - CheckDisposed(); - return _streamState._streamId; - } - } - - private StreamBuffer? ReadStreamBuffer => _isInitiator ? _streamState._inboundStreamBuffer : _streamState._outboundStreamBuffer; - - internal override bool CanTimeout => false; - - internal override int ReadTimeout - { - get => throw new InvalidOperationException(); - set => throw new InvalidOperationException(); - } - - internal override int WriteTimeout - { - get => throw new InvalidOperationException(); - set => throw new InvalidOperationException(); - } - - internal override bool CanRead => !_disposed && ReadStreamBuffer is not null; - - internal override bool ReadsCompleted => ReadStreamBuffer?.IsComplete ?? false; - - internal override int Read(Span buffer) - { - CheckDisposed(); - - StreamBuffer? streamBuffer = ReadStreamBuffer; - if (streamBuffer is null) - { - throw new NotSupportedException(); - } - - return streamBuffer.Read(buffer); - } - - internal override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) - { - CheckDisposed(); - - StreamBuffer? streamBuffer = ReadStreamBuffer; - if (streamBuffer is null) - { - throw new NotSupportedException(); - } - - int bytesRead = await streamBuffer.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); - if (bytesRead == 0) - { - if (_connection.ConnectionError is long connectonError) - { - throw new QuicConnectionAbortedException(connectonError); - } - - long errorCode = _isInitiator ? _streamState._inboundReadErrorCode : _streamState._outboundReadErrorCode; - if (errorCode != 0) - { - throw (errorCode == -1) ? new QuicOperationAbortedException() : new QuicStreamAbortedException(errorCode); - } - } - - return bytesRead; - } - - private StreamBuffer? WriteStreamBuffer => _isInitiator ? _streamState._outboundStreamBuffer : _streamState._inboundStreamBuffer; - - internal override bool CanWrite => !_disposed && WriteStreamBuffer is not null; - - internal override void Write(ReadOnlySpan buffer) - { - CheckDisposed(); - if (Volatile.Read(ref _writesCanceled)) - { - throw new OperationCanceledException(); - } - - StreamBuffer? streamBuffer = WriteStreamBuffer; - if (streamBuffer is null) - { - throw new NotSupportedException(); - } - - streamBuffer.Write(buffer); - } - - internal override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) - { - return WriteAsync(buffer, endStream: false, cancellationToken); - } - - internal override async ValueTask WriteAsync(ReadOnlyMemory buffer, bool endStream, CancellationToken cancellationToken = default) - { - CheckDisposed(); - if (Volatile.Read(ref _writesCanceled)) - { - cancellationToken.ThrowIfCancellationRequested(); - throw new QuicOperationAbortedException(); - } - - StreamBuffer? streamBuffer = WriteStreamBuffer; - if (streamBuffer is null) - { - throw new NotSupportedException(); - } - - if (_connection.ConnectionError is long connectonError) - { - throw new QuicConnectionAbortedException(connectonError); - } - - long errorCode = _isInitiator ? _streamState._inboundWriteErrorCode : _streamState._outboundWriteErrorCode; - if (errorCode != 0) - { - throw new QuicStreamAbortedException(errorCode); - } - - using var registration = cancellationToken.UnsafeRegister(static s => - { - var stream = (MockStream)s!; - Volatile.Write(ref stream._writesCanceled, true); - }, this); - - await streamBuffer.WriteAsync(buffer, cancellationToken).ConfigureAwait(false); - - if (endStream) - { - streamBuffer.EndWrite(); - WritesCompletedTcs.TrySetResult(); - } - } - - internal override ValueTask WriteAsync(ReadOnlySequence buffers, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - internal override ValueTask WriteAsync(ReadOnlySequence buffers, bool endStream, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - internal override async ValueTask WriteAsync(ReadOnlyMemory> buffers, CancellationToken cancellationToken = default) - { - for (int i = 0; i < buffers.Length; i++) - { - await WriteAsync(buffers.Span[i], cancellationToken).ConfigureAwait(false); - } - } - - internal override ValueTask WriteAsync(ReadOnlyMemory> buffers, bool endStream, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - internal override void Flush() - { - CheckDisposed(); - } - - internal override Task FlushAsync(CancellationToken cancellationToken) - { - CheckDisposed(); - - return Task.CompletedTask; - } - - internal override void AbortRead(long errorCode) - { - if (_isInitiator) - { - _streamState._outboundWriteErrorCode = errorCode; - _streamState._inboundWritesCompletedTcs.TrySetException(new QuicStreamAbortedException(errorCode)); - } - else - { - _streamState._inboundWriteErrorCode = errorCode; - _streamState._outboundWritesCompletedTcs.TrySetException(new QuicOperationAbortedException()); - } - - ReadStreamBuffer?.AbortRead(); - } - - internal override void AbortWrite(long errorCode) - { - if (_isInitiator) - { - _streamState._outboundReadErrorCode = errorCode; - _streamState._outboundWritesCompletedTcs.TrySetException(new QuicStreamAbortedException(errorCode)); - } - else - { - _streamState._inboundReadErrorCode = errorCode; - _streamState._inboundWritesCompletedTcs.TrySetException(new QuicOperationAbortedException()); - } - - WriteStreamBuffer?.EndWrite(); - } - - internal override ValueTask ShutdownCompleted(CancellationToken cancellationToken = default) - { - CheckDisposed(); - - return default; - } - - internal override void Shutdown() - { - CheckDisposed(); - - // This seems to mean shutdown send, in particular, not both. - WriteStreamBuffer?.EndWrite(); - - if (_streamState._inboundStreamBuffer is null) // unidirectional stream - { - _connection.LocalStreamLimit!.Unidirectional.Decrement(); - } - else - { - _connection.LocalStreamLimit!.Bidirectional.Decrement(); - } - - WritesCompletedTcs.TrySetResult(); - } - - private void CheckDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(nameof(QuicStream)); - } - } - - public override void Dispose() - { - if (!_disposed) - { - Shutdown(); - - _disposed = true; - } - } - - public override ValueTask DisposeAsync() - { - if (!_disposed) - { - Shutdown(); - - _disposed = true; - } - - return default; - } - - internal override ValueTask WaitForWriteCompletionAsync(CancellationToken cancellationToken = default) - { - CheckDisposed(); - - return new ValueTask(WritesCompletedTcs.Task); - } - - private TaskCompletionSource WritesCompletedTcs => _isInitiator - ? _streamState._outboundWritesCompletedTcs - : _streamState._inboundWritesCompletedTcs; - - internal sealed class StreamState - { - public readonly long _streamId; - public StreamBuffer _outboundStreamBuffer; - public StreamBuffer? _inboundStreamBuffer; - public long _outboundReadErrorCode; - public long _inboundReadErrorCode; - public long _outboundWriteErrorCode; - public long _inboundWriteErrorCode; - public TaskCompletionSource _outboundWritesCompletedTcs; - public TaskCompletionSource _inboundWritesCompletedTcs; - - private const int InitialBufferSize = -#if DEBUG - 10; -#else - 4096; -#endif - private const int MaxBufferSize = -#if DEBUG - 4096; -#else - 32 * 1024; -#endif - public StreamState(long streamId, bool bidirectional) - { - _streamId = streamId; - _outboundStreamBuffer = new StreamBuffer(initialBufferSize: InitialBufferSize, maxBufferSize: MaxBufferSize); - _inboundStreamBuffer = (bidirectional ? new StreamBuffer() : null); - _outboundWritesCompletedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - _inboundWritesCompletedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - } - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs index 0ee1c3917931a..cbcc4f83348e2 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs @@ -19,7 +19,7 @@ namespace System.Net.Quic.Implementations.MsQuic { - internal sealed class MsQuicConnection : QuicConnectionProvider + internal sealed class MsQuicConnection : IDisposable { private static readonly Oid s_clientAuthOid = new Oid("1.3.6.1.5.5.7.3.2", "1.3.6.1.5.5.7.3.2"); private static readonly Oid s_serverAuthOid = new Oid("1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.1"); @@ -194,15 +194,15 @@ public unsafe MsQuicConnection(QuicClientConnectionOptions options) } } - internal override IPEndPoint? LocalEndPoint => _localEndPoint; + internal IPEndPoint? LocalEndPoint => _localEndPoint; - internal override EndPoint RemoteEndPoint => _remoteEndPoint; + internal EndPoint RemoteEndPoint => _remoteEndPoint; - internal override X509Certificate? RemoteCertificate => _state.RemoteCertificate; + internal X509Certificate? RemoteCertificate => _state.RemoteCertificate; - internal override SslApplicationProtocol NegotiatedApplicationProtocol => _negotiatedAlpnProtocol; + internal SslApplicationProtocol NegotiatedApplicationProtocol => _negotiatedAlpnProtocol; - internal override bool Connected => _state.Connected; + internal bool Connected => _state.Connected; private static unsafe int HandleEventConnected(State state, ref QUIC_CONNECTION_EVENT connectionEvent) { @@ -439,7 +439,7 @@ private static unsafe int HandleEventPeerCertificateReceived(State state, ref QU } } - internal override async ValueTask AcceptStreamAsync(CancellationToken cancellationToken = default) + internal async ValueTask AcceptStreamAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); @@ -457,7 +457,7 @@ internal override async ValueTask AcceptStreamAsync(Cancella return stream; } - private async ValueTask OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS flags, CancellationToken cancellationToken) + private async ValueTask OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS flags, CancellationToken cancellationToken) { ThrowIfDisposed(); if (!Connected) @@ -480,24 +480,24 @@ private async ValueTask OpenStreamAsync(QUIC_STREAM_OPEN_FLA return stream; } - internal override ValueTask OpenUnidirectionalStreamAsync(CancellationToken cancellationToken = default) + internal ValueTask OpenUnidirectionalStreamAsync(CancellationToken cancellationToken = default) => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL, cancellationToken); - internal override ValueTask OpenBidirectionalStreamAsync(CancellationToken cancellationToken = default) + internal ValueTask OpenBidirectionalStreamAsync(CancellationToken cancellationToken = default) => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.NONE, cancellationToken); - internal override int GetRemoteAvailableUnidirectionalStreamCount() + internal int GetRemoteAvailableUnidirectionalStreamCount() { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT); } - internal override int GetRemoteAvailableBidirectionalStreamCount() + internal int GetRemoteAvailableBidirectionalStreamCount() { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT); } - internal override unsafe ValueTask ConnectAsync(CancellationToken cancellationToken = default) + internal unsafe override ValueTask ConnectAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); @@ -680,7 +680,7 @@ private static unsafe int NativeCallback(QUIC_HANDLE* connection, void* context, } } - public override void Dispose() + public void Dispose() { Dispose(true); GC.SuppressFinalize(this); @@ -757,7 +757,7 @@ private unsafe void Dispose(bool disposing) // TODO: this appears abortive and will cause prior successfully shutdown and closed streams to drop data. // It's unclear how to gracefully wait for a connection to be 100% done. - internal override ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default) + internal ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default) { if (_disposed == 1) { diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicImplementationProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicImplementationProvider.cs deleted file mode 100644 index f260c11137548..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicImplementationProvider.cs +++ /dev/null @@ -1,32 +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.Quic.Implementations.MsQuic.Internal; - -namespace System.Net.Quic.Implementations.MsQuic -{ - internal sealed class MsQuicImplementationProvider : QuicImplementationProvider - { - public override bool IsSupported => MsQuicApi.IsQuicSupported; - - internal override QuicListenerProvider CreateListener(QuicListenerOptions options) - { - if (!IsSupported) - { - throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported); - } - - return new MsQuicListener(options); - } - - internal override QuicConnectionProvider CreateConnection(QuicClientConnectionOptions options) - { - if (!IsSupported) - { - throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported); - } - - return new MsQuicConnection(options); - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs index 2768493e08fbb..8dcb04b12577d 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs @@ -19,7 +19,7 @@ namespace System.Net.Quic.Implementations.MsQuic { - internal sealed class MsQuicListener : QuicListenerProvider, IDisposable + internal sealed class MsQuicListener : IDisposable { private readonly State _state; private GCHandle _stateHandle; @@ -118,7 +118,7 @@ internal unsafe MsQuicListener(QuicListenerOptions options) } } - internal override IPEndPoint ListenEndPoint + internal IPEndPoint ListenEndPoint { get { @@ -126,7 +126,7 @@ internal override IPEndPoint ListenEndPoint } } - internal override async ValueTask AcceptConnectionAsync(CancellationToken cancellationToken = default) + internal async ValueTask AcceptConnectionAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); @@ -140,7 +140,7 @@ internal override async ValueTask AcceptConnectionAsync( } } - public override void Dispose() + public void Dispose() { Dispose(true); GC.SuppressFinalize(this); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs index 4ad758ef87bc2..5f6c1592627f3 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs @@ -15,7 +15,7 @@ namespace System.Net.Quic.Implementations.MsQuic { - internal sealed class MsQuicStream : QuicStreamProvider + internal sealed class MsQuicStream : IAsyncDisposable, IDisposable { // The state is passed to msquic and then it's passed back by msquic to the callback handler. private readonly State _state = new State(); @@ -201,17 +201,19 @@ internal unsafe MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM } } - internal override bool CanRead => _disposed == 0 && _canRead; + internal bool CanRead => _disposed == 0 && _canRead; - internal override bool CanWrite => _disposed == 0 && _canWrite; + internal bool CanWrite => _disposed == 0 && _canWrite; - internal override bool ReadsCompleted => _state.ReadState == ReadState.ReadsCompleted; + internal bool ReadsCompleted => _state.ReadState == ReadState.ReadsCompleted; - internal override bool CanTimeout => true; +#pragma warning disable CA1822 + internal bool CanTimeout => true; +#pragma warning restore CA1822 private int _readTimeout = Timeout.Infinite; - internal override int ReadTimeout + internal int ReadTimeout { get { @@ -230,7 +232,7 @@ internal override int ReadTimeout } private int _writeTimeout = Timeout.Infinite; - internal override int WriteTimeout + internal int WriteTimeout { get { @@ -248,7 +250,7 @@ internal override int WriteTimeout } } - internal override long StreamId + internal long StreamId { get { @@ -258,32 +260,32 @@ internal override long StreamId } } - internal override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + internal ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) { return WriteAsync(buffer, endStream: false, cancellationToken); } - internal override ValueTask WriteAsync(ReadOnlySequence buffers, CancellationToken cancellationToken = default) + internal ValueTask WriteAsync(ReadOnlySequence buffers, CancellationToken cancellationToken = default) { return WriteAsync(buffers, endStream: false, cancellationToken); } - internal override ValueTask WriteAsync(ReadOnlySequence buffers, bool endStream, CancellationToken cancellationToken = default) + internal ValueTask WriteAsync(ReadOnlySequence buffers, bool endStream, CancellationToken cancellationToken = default) { return WriteAsync(static (state, buffers) => state.SendBuffers.Initialize(buffers), buffers, buffers.IsEmpty, endStream, cancellationToken); } - internal override ValueTask WriteAsync(ReadOnlyMemory> buffers, CancellationToken cancellationToken = default) + internal ValueTask WriteAsync(ReadOnlyMemory> buffers, CancellationToken cancellationToken = default) { return WriteAsync(buffers, endStream: false, cancellationToken); } - internal override ValueTask WriteAsync(ReadOnlyMemory> buffers, bool endStream, CancellationToken cancellationToken = default) + internal ValueTask WriteAsync(ReadOnlyMemory> buffers, bool endStream, CancellationToken cancellationToken = default) { return WriteAsync(static (state, buffers) => state.SendBuffers.Initialize(buffers), buffers, buffers.IsEmpty, endStream, cancellationToken); } - internal override ValueTask WriteAsync(ReadOnlyMemory buffer, bool endStream, CancellationToken cancellationToken = default) + internal ValueTask WriteAsync(ReadOnlyMemory buffer, bool endStream, CancellationToken cancellationToken = default) { return WriteAsync(static (state, buffer) => state.SendBuffers.Initialize(buffer), buffer, buffer.IsEmpty, endStream, cancellationToken); } @@ -445,7 +447,7 @@ private void CleanupWriteFailedState() } } - internal override async ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken = default) + internal async ValueTask ReadAsync(Memory destination, CancellationToken cancellationToken = default) { ThrowIfDisposed(); @@ -620,7 +622,7 @@ private static unsafe int CopyMsQuicBuffersToUserBuffer(ReadOnlySpan buffer) + internal int Read(Span buffer) { ThrowIfDisposed(); byte[] rentedBuffer = ArrayPool.Shared.Rent(buffer.Length); @@ -795,7 +797,7 @@ internal override int Read(Span buffer) } } - internal override void Write(ReadOnlySpan buffer) + internal void Write(ReadOnlySpan buffer) { ThrowIfDisposed(); CancellationTokenSource? cts = null; @@ -823,20 +825,20 @@ internal override void Write(ReadOnlySpan buffer) } // MsQuic doesn't support explicit flushing - internal override void Flush() + internal void Flush() { ThrowIfDisposed(); } // MsQuic doesn't support explicit flushing - internal override Task FlushAsync(CancellationToken cancellationToken = default) + internal Task FlushAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); return Task.CompletedTask; } - public override ValueTask DisposeAsync() + public ValueTask DisposeAsync() { // TODO: perform a graceful shutdown and wait for completion? @@ -844,7 +846,7 @@ public override ValueTask DisposeAsync() return default; } - public override void Dispose() + public void Dispose() { Dispose(true); GC.SuppressFinalize(this); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicConnectionProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicConnectionProvider.cs deleted file mode 100644 index 182c68abe2b8b..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicConnectionProvider.cs +++ /dev/null @@ -1,37 +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.Threading; -using System.Threading.Tasks; - -namespace System.Net.Quic.Implementations -{ - internal abstract class QuicConnectionProvider : IDisposable - { - internal abstract bool Connected { get; } - - internal abstract IPEndPoint? LocalEndPoint { get; } - - internal abstract EndPoint RemoteEndPoint { get; } - - internal abstract ValueTask ConnectAsync(CancellationToken cancellationToken = default); - - internal abstract ValueTask OpenUnidirectionalStreamAsync(CancellationToken cancellationToken = default); - - internal abstract ValueTask OpenBidirectionalStreamAsync(CancellationToken cancellationToken = default); - - internal abstract int GetRemoteAvailableUnidirectionalStreamCount(); - - internal abstract int GetRemoteAvailableBidirectionalStreamCount(); - - internal abstract ValueTask AcceptStreamAsync(CancellationToken cancellationToken = default); - - internal abstract System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get; } - - internal abstract System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get; } - - internal abstract ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default); - - public abstract void Dispose(); - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicImplementationProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicImplementationProvider.cs deleted file mode 100644 index 5534ec4ef90e7..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicImplementationProvider.cs +++ /dev/null @@ -1,18 +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.Security; - -namespace System.Net.Quic.Implementations -{ - public abstract class QuicImplementationProvider - { - internal QuicImplementationProvider() { } - - public abstract bool IsSupported { get; } - - internal abstract QuicListenerProvider CreateListener(QuicListenerOptions options); - - internal abstract QuicConnectionProvider CreateConnection(QuicClientConnectionOptions options); - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicListenerProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicListenerProvider.cs deleted file mode 100644 index c24d7b165900f..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicListenerProvider.cs +++ /dev/null @@ -1,17 +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.Threading; -using System.Threading.Tasks; - -namespace System.Net.Quic.Implementations -{ - internal abstract class QuicListenerProvider : IDisposable - { - internal abstract IPEndPoint ListenEndPoint { get; } - - internal abstract ValueTask AcceptConnectionAsync(CancellationToken cancellationToken = default); - - public abstract void Dispose(); - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs deleted file mode 100644 index 215ce1304c1a4..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs +++ /dev/null @@ -1,62 +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.Buffers; -using System.Threading; -using System.Threading.Tasks; - -namespace System.Net.Quic.Implementations -{ - internal abstract class QuicStreamProvider : IDisposable, IAsyncDisposable - { - internal abstract long StreamId { get; } - - internal abstract bool CanTimeout { get; } - - internal abstract bool CanRead { get; } - - internal abstract bool ReadsCompleted { get; } - - internal abstract int ReadTimeout { get; set; } - - internal abstract int Read(Span buffer); - - internal abstract ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default); - - internal abstract void AbortRead(long errorCode); - - internal abstract void AbortWrite(long errorCode); - - internal abstract bool CanWrite { get; } - - internal abstract void Write(ReadOnlySpan buffer); - - internal abstract int WriteTimeout { get; set; } - - internal abstract ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default); - - internal abstract ValueTask WriteAsync(ReadOnlyMemory buffer, bool endStream, CancellationToken cancellationToken = default); - - internal abstract ValueTask WriteAsync(ReadOnlySequence buffers, CancellationToken cancellationToken = default); - - internal abstract ValueTask WriteAsync(ReadOnlySequence buffers, bool endStream, CancellationToken cancellationToken = default); - - internal abstract ValueTask WriteAsync(ReadOnlyMemory> buffers, CancellationToken cancellationToken = default); - - internal abstract ValueTask WriteAsync(ReadOnlyMemory> buffers, bool endStream, CancellationToken cancellationToken = default); - - internal abstract ValueTask ShutdownCompleted(CancellationToken cancellationToken = default); - - internal abstract ValueTask WaitForWriteCompletionAsync(CancellationToken cancellationToken = default); - - internal abstract void Shutdown(); - - internal abstract void Flush(); - - internal abstract Task FlushAsync(CancellationToken cancellationToken); - - public abstract void Dispose(); - - public abstract ValueTask DisposeAsync(); - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index 74fa392c340b2..b5ee819f5527b 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Net.Quic.Implementations; +using System.Net.Quic.Implementations.MsQuic; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Threading; @@ -11,41 +12,9 @@ namespace System.Net.Quic { public sealed class QuicConnection : IDisposable { - private readonly QuicConnectionProvider _provider; + private readonly MsQuicConnection _provider; - /// - /// Create an outbound QUIC connection. - /// - /// The remote endpoint to connect to. - /// TLS options - /// The local endpoint to connect from. - public QuicConnection(EndPoint remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null) - : this(QuicImplementationProviders.Default, remoteEndPoint, sslClientAuthenticationOptions, localEndPoint) - { - } - - /// - /// Create an outbound QUIC connection. - /// - /// The connection options. - public QuicConnection(QuicClientConnectionOptions options) - : this(QuicImplementationProviders.Default, options) - { - } - - // !!! TEMPORARY: Remove or make internal before shipping - public QuicConnection(QuicImplementationProvider implementationProvider, EndPoint remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null) - : this(implementationProvider, new QuicClientConnectionOptions() { RemoteEndPoint = remoteEndPoint, ClientAuthenticationOptions = sslClientAuthenticationOptions, LocalEndPoint = localEndPoint }) - { - } - - // !!! TEMPORARY: Remove or make internal before shipping - public QuicConnection(QuicImplementationProvider implementationProvider, QuicClientConnectionOptions options) - { - _provider = implementationProvider.CreateConnection(options); - } - - internal QuicConnection(QuicConnectionProvider provider) + internal QuicConnection(MsQuicConnection provider) { _provider = provider; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.Unsupported.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.Unsupported.cs deleted file mode 100644 index 210b6c2ed3a22..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.Unsupported.cs +++ /dev/null @@ -1,30 +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.Quic.Implementations; - -namespace System.Net.Quic -{ - public static partial class QuicImplementationProviders - { - public static Implementations.QuicImplementationProvider Mock => Default; - public static Implementations.QuicImplementationProvider MsQuic => Default; - public static Implementations.QuicImplementationProvider Default { get; } = new UnsupportedQuicImplementationProvider(); - - private sealed class UnsupportedQuicImplementationProvider : QuicImplementationProvider - { - internal UnsupportedQuicImplementationProvider() : base(false) { } - public override bool IsSupported => false; - } - } -} - -namespace System.Net.Quic.Implementations -{ - public abstract partial class QuicImplementationProvider - { - // alternative constructor because currently it is not possible to exlude ctors from - // PNSE autogeneration (https://github.com/dotnet/arcade/issues/8676) - internal QuicImplementationProvider(bool _) { } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.cs deleted file mode 100644 index d7bc23f6ce003..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.Quic -{ - public static class QuicImplementationProviders - { - public static Implementations.QuicImplementationProvider Mock { get; } = new Implementations.Mock.MockImplementationProvider(); - public static Implementations.QuicImplementationProvider MsQuic { get; } = new Implementations.MsQuic.MsQuicImplementationProvider(); - public static Implementations.QuicImplementationProvider Default => MsQuic; - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs index acf18bf3ce319..8c31a7c487536 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Net.Quic.Implementations; +using System.Net.Quic.Implementations.MsQuic; using System.Net.Security; using System.Threading; using System.Threading.Tasks; @@ -10,37 +11,11 @@ namespace System.Net.Quic { public sealed class QuicListener : IDisposable { - private readonly QuicListenerProvider _provider; + private readonly MsQuicListener _provider; - /// - /// Create a QUIC listener. - /// - /// The local endpoint to listen on. - /// TLS options for the listener. - public QuicListener(IPEndPoint listenEndPoint, SslServerAuthenticationOptions sslServerAuthenticationOptions) - : this(QuicImplementationProviders.Default, listenEndPoint, sslServerAuthenticationOptions) - { - } - - /// - /// Create a QUIC listener. - /// - /// The listener options. - public QuicListener(QuicListenerOptions options) - : this(QuicImplementationProviders.Default, options) - { - } - - // !!! TEMPORARY: Remove or make internal before shipping - public QuicListener(QuicImplementationProvider implementationProvider, IPEndPoint listenEndPoint, SslServerAuthenticationOptions sslServerAuthenticationOptions) - : this(implementationProvider, new QuicListenerOptions() { ListenEndPoint = listenEndPoint, ServerAuthenticationOptions = sslServerAuthenticationOptions }) - { - } - - // !!! TEMPORARY: Remove or make internal before shipping - public QuicListener(QuicImplementationProvider implementationProvider, QuicListenerOptions options) + internal QuicListener(MsQuicListener provider) { - _provider = implementationProvider.CreateListener(options); + _provider = provider; } public IPEndPoint ListenEndPoint => _provider.ListenEndPoint; diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.Unsupported.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.Unsupported.cs new file mode 100644 index 0000000000000..b860c936e5166 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.Unsupported.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Net.Quic +{ + public static partial class QuicProvider + { + public static bool IsSupported => false; + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.cs new file mode 100644 index 0000000000000..c06e41cbec534 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.cs @@ -0,0 +1,35 @@ +// 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.Implementations.MsQuic; +using System.Net.Quic.Implementations.MsQuic.Internal; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Quic +{ + public static partial class QuicProvider + { + public static bool IsSupported => MsQuicApi.IsQuicSupported; + + public static ValueTask CreateListenerAsync(QuicListenerOptions options, CancellationToken cancellationToken = default) + { + if (!IsSupported) + { + throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported); + } + + return ValueTask.FromResult(new QuicListener(new MsQuicListener(options))); + } + + public static ValueTask CreateConnectionAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken = default) + { + if (!IsSupported) + { + throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported); + } + + return ValueTask.FromResult(new QuicConnection(new MsQuicConnection(options))); + } + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs index 98fdd51fb3633..011e22b7f1e62 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.IO; using System.Net.Quic.Implementations; +using System.Net.Quic.Implementations.MsQuic; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -12,9 +13,9 @@ namespace System.Net.Quic { public sealed class QuicStream : Stream { - private readonly QuicStreamProvider _provider; + private readonly MsQuicStream _provider; - internal QuicStream(QuicStreamProvider provider) + internal QuicStream(MsQuicStream provider) { _provider = provider; } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicCipherSuitesPolicyTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicCipherSuitesPolicyTests.cs index aa7eaa64cc0fd..43337eba15176 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicCipherSuitesPolicyTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicCipherSuitesPolicyTests.cs @@ -1,6 +1,5 @@ // 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.Implementations; using System.Net.Security; using System.Threading.Tasks; using Xunit; @@ -8,10 +7,10 @@ namespace System.Net.Quic.Tests { - [ConditionalClass(typeof(QuicTestBase), nameof(IsSupported))] [Collection(nameof(DisableParallelization))] + [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] [SkipOnPlatform(TestPlatforms.Windows, "CipherSuitesPolicy is not supported on Windows")] - public class MsQuicCipherSuitesPolicyTests : QuicTestBase + public class MsQuicCipherSuitesPolicyTests : QuicTestBase { public MsQuicCipherSuitesPolicyTests(ITestOutputHelper output) : base(output) { } @@ -19,12 +18,12 @@ private async Task TestConnection(CipherSuitesPolicy serverPolicy, CipherSuitesP { var listenerOptions = CreateQuicListenerOptions(); listenerOptions.ServerAuthenticationOptions.CipherSuitesPolicy = serverPolicy; - using QuicListener listener = CreateQuicListener(listenerOptions); + using QuicListener listener = await CreateQuicListener(listenerOptions); var clientOptions = CreateQuicClientOptions(); clientOptions.ClientAuthenticationOptions.CipherSuitesPolicy = clientPolicy; clientOptions.RemoteEndPoint = listener.ListenEndPoint; - using QuicConnection clientConnection = CreateQuicConnection(clientOptions); + using QuicConnection clientConnection = await CreateQuicConnection(clientOptions); await clientConnection.ConnectAsync(); await clientConnection.CloseAsync(0); @@ -45,12 +44,12 @@ public void NoSupportedCiphers_ThrowsArgumentException(TlsCipherSuite[] ciphers) CipherSuitesPolicy policy = new CipherSuitesPolicy(ciphers); var listenerOptions = CreateQuicListenerOptions(); listenerOptions.ServerAuthenticationOptions.CipherSuitesPolicy = policy; - Assert.Throws(() => CreateQuicListener(listenerOptions)); + Assert.ThrowsAsync(async () => await CreateQuicListener(listenerOptions)); var clientOptions = CreateQuicClientOptions(); clientOptions.ClientAuthenticationOptions.CipherSuitesPolicy = policy; clientOptions.RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, 5000); - Assert.Throws(() => CreateQuicConnection(clientOptions)); + Assert.ThrowsAsync(async () => await CreateQuicConnection(clientOptions)); } [Fact] diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicPlatformDetectionTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicPlatformDetectionTests.cs index 7dc0a159f5bb2..2d0bc54044556 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicPlatformDetectionTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicPlatformDetectionTests.cs @@ -1,6 +1,5 @@ // 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.Implementations; using System.Net.Security; using System.Threading.Tasks; using Xunit; @@ -8,7 +7,7 @@ namespace System.Net.Quic.Tests { - public class MsQuicPlatformDetectionTests : QuicTestBase + public class MsQuicPlatformDetectionTests : QuicTestBase { public MsQuicPlatformDetectionTests(ITestOutputHelper output) : base(output) { } @@ -17,8 +16,8 @@ public MsQuicPlatformDetectionTests(ITestOutputHelper output) : base(output) { } [ConditionalFact(nameof(IsQuicUnsupported))] public void UnsupportedPlatforms_ThrowsPlatformNotSupportedException() { - Assert.Throws(() => CreateQuicListener()); - Assert.Throws(() => CreateQuicConnection(new IPEndPoint(IPAddress.Loopback, 0))); + Assert.ThrowsAsync(async () => await CreateQuicListener()); + Assert.ThrowsAsync(async () => await CreateQuicConnection(new IPEndPoint(IPAddress.Loopback, 0))); } } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs index 65e78735e1282..eb1b5803e8b9e 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -21,9 +21,9 @@ namespace System.Net.Quic.Tests { - [ConditionalClass(typeof(QuicTestBase), nameof(IsSupported))] [Collection(nameof(DisableParallelization))] - public class MsQuicTests : QuicTestBase + [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] + public class MsQuicTests : QuicTestBase { private static byte[] s_data = "Hello world!"u8.ToArray(); @@ -122,11 +122,11 @@ public async Task UntrustedClientCertificateFails() return false; }; - using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, listenerOptions); + using QuicListener listener = await CreateQuicListener(listenerOptions); QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(); clientOptions.RemoteEndPoint = listener.ListenEndPoint; clientOptions.ClientAuthenticationOptions.ClientCertificates = new X509CertificateCollection() { ClientCertificate }; - QuicConnection clientConnection = CreateQuicConnection(clientOptions); + QuicConnection clientConnection = await CreateQuicConnection(clientOptions); using CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(500); //Some delay to see if we would get failed connection. @@ -136,7 +136,7 @@ public async Task UntrustedClientCertificateFails() t.AsTask().Wait(PassingTestTimeout); await Assert.ThrowsAsync(() => serverTask); - // The task will likely succed but we don't really care. + // The task will likely succeed but we don't really care. // It may fail if the server aborts quickly. try { @@ -158,7 +158,7 @@ public async Task CertificateCallbackThrowPropagates() 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); + using QuicListener listener = await CreateQuicListener(listenerOptions); QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(); clientOptions.RemoteEndPoint = listener.ListenEndPoint; @@ -174,14 +174,14 @@ public async Task CertificateCallbackThrowPropagates() }; clientOptions.ClientAuthenticationOptions.TargetHost = "foobar1"; - QuicConnection clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, clientOptions); + QuicConnection clientConnection = await CreateQuicConnection(clientOptions); await Assert.ThrowsAsync(() => 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 + // Make sure the listener is still usable and there is no lingering bad connection validationResult = true; (clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(listener); await PingPong(clientConnection, serverConnection); @@ -220,7 +220,7 @@ public async Task ConnectWithCertificateCallback() return null; }; - using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, listenerOptions); + using QuicListener listener = await CreateQuicListener(listenerOptions); QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(); clientOptions.ClientAuthenticationOptions.TargetHost = "foobar1"; clientOptions.ClientAuthenticationOptions.RemoteCertificateValidationCallback = (sender, cert, chain, errors) => @@ -237,7 +237,7 @@ public async Task ConnectWithCertificateCallback() // This should fail when callback return null. clientOptions.ClientAuthenticationOptions.TargetHost = "foobar3"; - clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, clientOptions); + clientConnection = await CreateQuicConnection(clientOptions); Task clientTask = clientConnection.ConnectAsync(cts.Token).AsTask(); await Assert.ThrowsAnyAsync(() => clientTask); @@ -270,7 +270,7 @@ public async Task ConnectWithIpSetsSni() return certificate; }; - using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, listenerOptions); + using QuicListener listener = await CreateQuicListener(listenerOptions); QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(); clientOptions.ClientAuthenticationOptions.TargetHost = expectedName; @@ -291,7 +291,7 @@ public async Task ConnectWithCertificateForDifferentName_Throws() quicOptions.ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0); quicOptions.ServerAuthenticationOptions = GetSslServerAuthenticationOptions(); quicOptions.ServerAuthenticationOptions.ServerCertificate = certificate; - using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, quicOptions); + using QuicListener listener = await CreateQuicListener(quicOptions); QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(); clientOptions.RemoteEndPoint = listener.ListenEndPoint; @@ -305,7 +305,7 @@ public async Task ConnectWithCertificateForDifferentName_Throws() return SslPolicyErrors.None == errors; }; - using QuicConnection clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, clientOptions); + using QuicConnection clientConnection = await CreateQuicConnection(clientOptions); ValueTask clientTask = clientConnection.ConnectAsync(); await Assert.ThrowsAsync(async () => await clientTask); @@ -369,7 +369,7 @@ public async Task ConnectWithClientCertificate(bool sendCertificate) return true; }; - using QuicListener listener = new QuicListener(QuicImplementationProviders.MsQuic, listenerOptions); + using QuicListener listener = await CreateQuicListener(listenerOptions); QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(); if (sendCertificate) { diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs index 2ffd8a07a223b..7b54875067131 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs @@ -8,8 +8,9 @@ namespace System.Net.Quic.Tests { - public abstract class QuicConnectionTests : QuicTestBase - where T : IQuicImplProviderFactory, new() + [Collection(nameof(DisableParallelization))] + [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] + public sealed class QuicConnectionTests : QuicTestBase { const int ExpectedErrorCode = 1234; @@ -18,9 +19,9 @@ public QuicConnectionTests(ITestOutputHelper output) : base(output) { } [Fact] public async Task TestConnect() { - using QuicListener listener = CreateQuicListener(); + using QuicListener listener = await CreateQuicListener(); - using QuicConnection clientConnection = CreateQuicConnection(listener.ListenEndPoint); + using QuicConnection clientConnection = await CreateQuicConnection(listener.ListenEndPoint); Assert.False(clientConnection.Connected); Assert.Equal(listener.ListenEndPoint, clientConnection.RemoteEndPoint); @@ -82,16 +83,8 @@ await RunClientServer( // Subsequent attempts should fail // TODO: Which exception is correct? - if (IsMockProvider) - { - await Assert.ThrowsAsync(async () => await serverConnection.AcceptStreamAsync()); - await Assert.ThrowsAsync(async () => await OpenAndUseStreamAsync(serverConnection)); - } - else - { - await Assert.ThrowsAsync(async () => await serverConnection.AcceptStreamAsync()); - await Assert.ThrowsAnyAsync(() => OpenAndUseStreamAsync(serverConnection)); - } + await Assert.ThrowsAsync(async () => await serverConnection.AcceptStreamAsync()); + await Assert.ThrowsAnyAsync(() => OpenAndUseStreamAsync(serverConnection)); }); } @@ -136,11 +129,6 @@ await RunClientServer( [Fact] public async Task ConnectionClosedByPeer_WithPendingAcceptAndConnect_PendingAndSubsequentThrowConnectionAbortedException() { - if (IsMockProvider) - { - return; - } - using var sync = new SemaphoreSlim(0); await RunClientServer( @@ -198,11 +186,6 @@ private static async Task DoReads(QuicStream reader, int readCount) [InlineData(10)] public async Task CloseAsync_WithOpenStream_LocalAndPeerStreamsFailWithQuicOperationAbortedException(int writesBeforeClose) { - if (IsMockProvider) - { - return; - } - using var sync = new SemaphoreSlim(0); await RunClientServer( @@ -241,11 +224,6 @@ await RunClientServer( [InlineData(10)] public async Task Dispose_WithOpenLocalStream_LocalStreamFailsWithQuicOperationAbortedException(int writesBeforeClose) { - if (IsMockProvider) - { - return; - } - // Set a short idle timeout so that after we dispose the connection, the peer will discover the connection is dead before too long. QuicListenerOptions listenerOptions = CreateQuicListenerOptions(); listenerOptions.IdleTimeout = TimeSpan.FromSeconds(1); @@ -280,18 +258,4 @@ await RunClientServer( }, listenerOptions: listenerOptions); } } - - [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] - public sealed class QuicConnectionTests_MockProvider : QuicConnectionTests - { - public QuicConnectionTests_MockProvider(ITestOutputHelper output) : base(output) { } - } - - [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] - [Collection(nameof(DisableParallelization))] - - public sealed class QuicConnectionTests_MsQuicProvider : QuicConnectionTests - { - public QuicConnectionTests_MsQuicProvider(ITestOutputHelper output) : base(output) { } - } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index 5a702a0574351..0cf1d886b5f3d 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -7,8 +7,9 @@ namespace System.Net.Quic.Tests { - public abstract class QuicListenerTests : QuicTestBase - where T : IQuicImplProviderFactory, new() + [Collection(nameof(DisableParallelization))] + [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] + public sealed class QuicListenerTests : QuicTestBase { public QuicListenerTests(ITestOutputHelper output) : base(output) { } @@ -17,9 +18,9 @@ public async Task Listener_Backlog_Success() { await Task.Run(async () => { - using QuicListener listener = CreateQuicListener(); + using QuicListener listener = await CreateQuicListener(); - using QuicConnection clientConnection = CreateQuicConnection(listener.ListenEndPoint); + using QuicConnection clientConnection = await CreateQuicConnection(listener.ListenEndPoint); var clientStreamTask = clientConnection.ConnectAsync(); using QuicConnection serverConnection = await listener.AcceptConnectionAsync(); @@ -32,9 +33,9 @@ public async Task Listener_Backlog_Success_IPv6() { await Task.Run(async () => { - using QuicListener listener = CreateQuicListener(new IPEndPoint(IPAddress.IPv6Loopback, 0)); + using QuicListener listener = await CreateQuicListener(new IPEndPoint(IPAddress.IPv6Loopback, 0)); - using QuicConnection clientConnection = CreateQuicConnection(listener.ListenEndPoint); + using QuicConnection clientConnection = await CreateQuicConnection(listener.ListenEndPoint); var clientStreamTask = clientConnection.ConnectAsync(); using QuicConnection serverConnection = await listener.AcceptConnectionAsync(); @@ -42,14 +43,14 @@ await Task.Run(async () => }).WaitAsync(TimeSpan.FromSeconds(6)); } - [ConditionalFact(nameof(IsMsQuicProvider))] + [Fact] public async Task Listener_IPv6Any_Accepts_IPv4() { await Task.Run(async () => { - using QuicListener listener = CreateQuicListener(new IPEndPoint(IPAddress.IPv6Any, 0)); + using QuicListener listener = await CreateQuicListener(new IPEndPoint(IPAddress.IPv6Any, 0)); - using QuicConnection clientConnection = CreateQuicConnection(new IPEndPoint(IPAddress.Loopback, listener.ListenEndPoint.Port)); + using QuicConnection clientConnection = await CreateQuicConnection(new IPEndPoint(IPAddress.Loopback, listener.ListenEndPoint.Port)); var clientStreamTask = clientConnection.ConnectAsync(); using QuicConnection serverConnection = await listener.AcceptConnectionAsync(); @@ -57,17 +58,4 @@ await Task.Run(async () => }).WaitAsync(TimeSpan.FromSeconds(6)); } } - - [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] - public sealed class QuicListenerTests_MockProvider : QuicListenerTests - { - public QuicListenerTests_MockProvider(ITestOutputHelper output) : base(output) { } - } - - [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class QuicListenerTests_MsQuicProvider : QuicListenerTests - { - public QuicListenerTests_MsQuicProvider(ITestOutputHelper output) : base(output) { } - } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs index 5b58ee229496e..1b8e1d5639b76 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs @@ -5,7 +5,6 @@ using System.IO; using System.IO.Tests; using System.Net.Sockets; -using System.Net.Quic.Implementations; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Threading; @@ -15,30 +14,14 @@ namespace System.Net.Quic.Tests { - [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] - public sealed class MockQuicStreamConformanceTests : QuicStreamConformanceTests - { - protected override QuicImplementationProvider Provider => QuicImplementationProviders.Mock; - protected override bool BlocksOnZeroByteReads => true; - } - - [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] [Collection(nameof(DisableParallelization))] - public sealed class MsQuicQuicStreamConformanceTests : QuicStreamConformanceTests + [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] + public sealed class QuicStreamConformanceTests : ConnectedStreamConformanceTests { - protected override QuicImplementationProvider Provider => QuicImplementationProviders.MsQuic; protected override bool UsableAfterCanceledReads => false; protected override bool BlocksOnZeroByteReads => true; protected override bool CanTimeout => true; - public MsQuicQuicStreamConformanceTests(ITestOutputHelper output) - { - _output = output; - } - } - - public abstract class QuicStreamConformanceTests : ConnectedStreamConformanceTests - { public X509Certificate2 ServerCertificate = System.Net.Test.Common.Configuration.Certificates.GetServerCertificate(); public ITestOutputHelper _output; @@ -66,15 +49,13 @@ public SslClientAuthenticationOptions GetSslClientAuthenticationOptions() }; } - protected abstract QuicImplementationProvider Provider { get; } - protected override async Task CreateConnectedStreamsAsync() { - QuicImplementationProvider provider = Provider; - var listener = new QuicListener( - provider, - new IPEndPoint(IPAddress.Loopback, 0), - GetSslServerAuthenticationOptions()); + var listener = await QuicProvider.CreateListenerAsync(new QuicListenerOptions() + { + ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), + ServerAuthenticationOptions = GetSslServerAuthenticationOptions() + }); byte[] buffer = new byte[1] { 42 }; QuicConnection connection1 = null, connection2 = null; @@ -90,10 +71,11 @@ await WhenAllOrAnyFailed( { try { - connection2 = new QuicConnection( - provider, - listener.ListenEndPoint, - GetSslClientAuthenticationOptions()); + connection2 = await QuicProvider.CreateConnectionAsync(new QuicClientConnectionOptions() + { + RemoteEndPoint = listener.ListenEndPoint, + ClientAuthenticationOptions = GetSslClientAuthenticationOptions() + }); await connection2.ConnectAsync(); stream2 = await connection2.OpenBidirectionalStreamAsync(); // OpenBidirectionalStream only allocates ID. We will force stream opening diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs index 0fe8068fcdcd5..fc1232273ed2b 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs @@ -12,8 +12,9 @@ namespace System.Net.Quic.Tests { - public abstract class QuicStreamTests : QuicTestBase - where T : IQuicImplProviderFactory, new() + [Collection(nameof(DisableParallelization))] + [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] + public sealed class QuicStreamTests : QuicTestBase { private static byte[] s_data = "Hello world!"u8.ToArray(); public QuicStreamTests(ITestOutputHelper output) : base(output) { } @@ -254,7 +255,7 @@ await RunClientServer( [Fact] public async Task TestStreams() { - using QuicListener listener = CreateQuicListener(); + using QuicListener listener = await CreateQuicListener(); (QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(listener); using (clientConnection) using (serverConnection) @@ -498,12 +499,6 @@ await RunBidirectionalClientServer( [Fact] public async Task ReadOutstanding_ReadAborted_Throws() { - // aborting doesn't work properly on mock - if (typeof(T) == typeof(MockProviderFactory)) - { - return; - } - (QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection(); using (clientConnection) using (serverConnection) @@ -620,12 +615,6 @@ await RunClientServer( [Fact] public async Task WriteCanceled_NextWriteThrows() { - // [ActiveIssue("https://github.com/dotnet/runtime/issues/55995")] - if (typeof(T) == typeof(MockProviderFactory)) - { - return; - } - const long expectedErrorCode = 1234; await RunClientServer( @@ -796,12 +785,6 @@ async ValueTask ReleaseOnWriteCompletionAsync() [Fact] public async Task WriteAsync_LocalAbort_Throws() { - if (IsMockProvider) - { - // Mock provider does not support aborting pending writes via AbortWrite - return; - } - const int ExpectedErrorCode = 0xfffffff; SemaphoreSlim sem = new SemaphoreSlim(0); @@ -992,17 +975,4 @@ async ValueTask ReleaseOnWriteCompletionAsync() ); } } - - [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] - public sealed class QuicStreamTests_MockProvider : QuicStreamTests - { - public QuicStreamTests_MockProvider(ITestOutputHelper output) : base(output) { } - } - - [ConditionalClass(typeof(QuicTestBase), nameof(QuicTestBase.IsSupported))] - [Collection(nameof(DisableParallelization))] - public sealed class QuicStreamTests_MsQuicProvider : QuicStreamTests - { - public QuicStreamTests_MsQuicProvider(ITestOutputHelper output) : base(output) { } - } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicTestBase.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicTestBase.cs index b613b6dd44f02..48880043bfae6 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicTestBase.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicTestBase.cs @@ -4,7 +4,6 @@ using System.Buffers; using System.Collections.Generic; using System.Diagnostics; -using System.Net.Quic.Implementations; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text; @@ -17,18 +16,12 @@ namespace System.Net.Quic.Tests { - public abstract class QuicTestBase - where T : IQuicImplProviderFactory, new() + public abstract class QuicTestBase { private static readonly byte[] s_ping = "PING"u8.ToArray(); private static readonly byte[] s_pong = "PONG"u8.ToArray(); - private static readonly IQuicImplProviderFactory s_factory = new T(); - public static QuicImplementationProvider ImplementationProvider { get; } = s_factory.GetProvider(); - public static bool IsSupported => ImplementationProvider.IsSupported; - - public static bool IsMockProvider => typeof(T) == typeof(MockProviderFactory); - public static bool IsMsQuicProvider => typeof(T) == typeof(MsQuicProviderFactory); + public static bool IsSupported => QuicProvider.IsSupported; public static SslApplicationProtocol ApplicationProtocol { get; } = new SslApplicationProtocol("quictest"); @@ -76,14 +69,16 @@ public QuicClientConnectionOptions CreateQuicClientOptions() }; } - internal QuicConnection CreateQuicConnection(IPEndPoint endpoint) + internal ValueTask CreateQuicConnection(IPEndPoint endpoint) { - return new QuicConnection(ImplementationProvider, endpoint, GetSslClientAuthenticationOptions()); + var options = CreateQuicClientOptions(); + options.RemoteEndPoint = endpoint; + return CreateQuicConnection(options); } - internal QuicConnection CreateQuicConnection(QuicClientConnectionOptions clientOptions) + internal ValueTask CreateQuicConnection(QuicClientConnectionOptions clientOptions) { - return new QuicConnection(ImplementationProvider, clientOptions); + return QuicProvider.CreateConnectionAsync(clientOptions); } internal QuicListenerOptions CreateQuicListenerOptions() @@ -95,7 +90,7 @@ internal QuicListenerOptions CreateQuicListenerOptions() }; } - internal QuicListener CreateQuicListener(int maxUnidirectionalStreams = 100, int maxBidirectionalStreams = 100) + internal ValueTask CreateQuicListener(int maxUnidirectionalStreams = 100, int maxBidirectionalStreams = 100) { var options = CreateQuicListenerOptions(); options.MaxUnidirectionalStreams = maxUnidirectionalStreams; @@ -104,7 +99,7 @@ internal QuicListener CreateQuicListener(int maxUnidirectionalStreams = 100, int return CreateQuicListener(options); } - internal QuicListener CreateQuicListener(IPEndPoint endpoint) + internal ValueTask CreateQuicListener(IPEndPoint endpoint) { var options = new QuicListenerOptions() { @@ -114,12 +109,12 @@ internal QuicListener CreateQuicListener(IPEndPoint endpoint) return CreateQuicListener(options); } - internal QuicListener CreateQuicListener(QuicListenerOptions options) => new QuicListener(ImplementationProvider, options); + internal ValueTask CreateQuicListener(QuicListenerOptions options) => QuicProvider.CreateListenerAsync(options); internal Task<(QuicConnection, QuicConnection)> CreateConnectedQuicConnection(QuicListener listener) => CreateConnectedQuicConnection(null, listener); internal async Task<(QuicConnection, QuicConnection)> CreateConnectedQuicConnection(QuicClientConnectionOptions? clientOptions, QuicListenerOptions listenerOptions) { - using (QuicListener listener = CreateQuicListener(listenerOptions)) + using (QuicListener listener = await CreateQuicListener(listenerOptions)) { clientOptions ??= new QuicClientConnectionOptions() { @@ -138,7 +133,7 @@ internal QuicListener CreateQuicListener(IPEndPoint endpoint) if (listener == null) { - listener = CreateQuicListener(); + listener = await CreateQuicListener(); disposeListener = true; } @@ -152,7 +147,7 @@ internal QuicListener CreateQuicListener(IPEndPoint endpoint) ValueTask serverTask = listener.AcceptConnectionAsync(); while (retry > 0) { - clientConnection = CreateQuicConnection(clientOptions); + clientConnection = await CreateQuicConnection(clientOptions); retry--; try { @@ -220,7 +215,7 @@ internal async Task RunClientServer(Func clientFunction, F const long ClientCloseErrorCode = 11111; const long ServerCloseErrorCode = 22222; - using QuicListener listener = CreateQuicListener(listenerOptions ?? CreateQuicListenerOptions()); + using QuicListener listener = await CreateQuicListener(listenerOptions ?? CreateQuicListenerOptions()); using var serverFinished = new SemaphoreSlim(0); using var clientFinished = new SemaphoreSlim(0); @@ -324,19 +319,4 @@ internal static async Task WriteForever(QuicStream stream, int size = 1) } } } - - public interface IQuicImplProviderFactory - { - QuicImplementationProvider GetProvider(); - } - - public sealed class MsQuicProviderFactory : IQuicImplProviderFactory - { - public QuicImplementationProvider GetProvider() => QuicImplementationProviders.MsQuic; - } - - public sealed class MockProviderFactory : IQuicImplProviderFactory - { - public QuicImplementationProvider GetProvider() => QuicImplementationProviders.Mock; - } } From 26502749e780a358bb5454eda6ace2a212e3afd8 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Wed, 15 Jun 2022 09:38:23 +0200 Subject: [PATCH 2/3] Removed provider and replaced with statics on Listener and Connection --- .../System/Net/Http/Http3LoopbackServer.cs | 2 +- .../Http/SocketsHttpHandler/ConnectHelper.cs | 2 +- .../SocketsHttpHandler/HttpConnectionPool.cs | 2 +- ...lientHandlerTestBase.SocketsHttpHandler.cs | 2 +- .../System.Net.Quic/ref/System.Net.Quic.cs | 10 +++--- .../src/ExcludeApiList.PNSE.txt | 3 +- .../src/System.Net.Quic.csproj | 4 +-- .../MsQuic/MsQuicConnection.cs | 2 +- .../Net/Quic/QuicConnection.Unsupported.cs | 10 ++++++ .../src/System/Net/Quic/QuicConnection.cs | 13 +++++++ ...pported.cs => QuicListener.Unsupported.cs} | 2 +- .../src/System/Net/Quic/QuicListener.cs | 13 +++++++ .../src/System/Net/Quic/QuicProvider.cs | 35 ------------------- ...icStreamConnectedStreamConformanceTests.cs | 4 +-- .../tests/FunctionalTests/QuicTestBase.cs | 6 ++-- 15 files changed, 55 insertions(+), 55 deletions(-) create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs rename src/libraries/System.Net.Quic/src/System/Net/Quic/{QuicProvider.Unsupported.cs => QuicListener.Unsupported.cs} (83%) delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.cs diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs index 2d749fa7e4097..c3287d7933bb0 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs @@ -42,7 +42,7 @@ public Http3LoopbackServer(Http3Options options = null) MaxBidirectionalStreams = options.MaxBidirectionalStreams, }; - _listener = QuicProvider.CreateListenerAsync(listenerOptions).Result; + _listener = QuicListener.ListenAsync(listenerOptions).Result; } public override void Dispose() diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs index 7590fdaf60a4f..ec2e912e4a35c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs @@ -107,7 +107,7 @@ public static async ValueTask EstablishSslConnectionAsync(SslClientAu public static async ValueTask ConnectQuicAsync(HttpRequestMessage request, DnsEndPoint endPoint, SslClientAuthenticationOptions clientAuthenticationOptions, CancellationToken cancellationToken) { clientAuthenticationOptions = SetUpRemoteCertificateValidationCallback(clientAuthenticationOptions, request); - QuicConnection connection = await QuicProvider.CreateConnectionAsync(new QuicClientConnectionOptions() + QuicConnection connection = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions() { RemoteEndPoint = endPoint, ClientAuthenticationOptions = clientAuthenticationOptions diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs index dff8f8e14c2f6..027e01dafd86b 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs @@ -134,7 +134,7 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK if (IsHttp3Supported()) { - _http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30 && QuicProvider.IsSupported; + _http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30 && QuicConnection.IsSupported; } switch (kind) diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs index 66d9d0b188433..3d66d05613c81 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTestBase.SocketsHttpHandler.cs @@ -19,7 +19,7 @@ public static bool IsQuicSupported { try { - return QuicProvider.IsSupported; + return QuicConnection.IsSupported; } catch (System.PlatformNotSupportedException) { diff --git a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs index dd9addfac5c56..8e2c856827535 100644 --- a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs +++ b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs @@ -17,12 +17,14 @@ public sealed partial class QuicConnection : System.IDisposable { internal QuicConnection() { } public bool Connected { get { throw null; } } + public static bool IsSupported { get { throw null; } } public System.Net.IPEndPoint? LocalEndPoint { get { throw null; } } public System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get { throw null; } } public System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get { throw null; } } public System.Net.EndPoint RemoteEndPoint { get { throw null; } } public System.Threading.Tasks.ValueTask AcceptStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public System.Threading.Tasks.ValueTask CloseAsync(long errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask ConnectAsync(System.Net.Quic.QuicClientConnectionOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public System.Threading.Tasks.ValueTask ConnectAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public void Dispose() { } public int GetRemoteAvailableBidirectionalStreamCount() { throw null; } @@ -44,9 +46,11 @@ public QuicException(string? message, System.Exception? innerException, int resu public sealed partial class QuicListener : System.IDisposable { internal QuicListener() { } + public static bool IsSupported { get { throw null; } } public System.Net.IPEndPoint ListenEndPoint { get { throw null; } } public System.Threading.Tasks.ValueTask AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public void Dispose() { } + public static System.Threading.Tasks.ValueTask ListenAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } public partial class QuicListenerOptions : System.Net.Quic.QuicOptions { @@ -66,12 +70,6 @@ public QuicOptions() { } public int MaxBidirectionalStreams { get { throw null; } set { } } public int MaxUnidirectionalStreams { get { throw null; } set { } } } - public static partial class QuicProvider - { - public static bool IsSupported { get { throw null; } } - public static System.Threading.Tasks.ValueTask CreateConnectionAsync(System.Net.Quic.QuicClientConnectionOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public static System.Threading.Tasks.ValueTask CreateListenerAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - } public sealed partial class QuicStream : System.IO.Stream { internal QuicStream() { } diff --git a/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt b/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt index 25cbd3f4511f6..d6b3f48e2a732 100644 --- a/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt +++ b/src/libraries/System.Net.Quic/src/ExcludeApiList.PNSE.txt @@ -1 +1,2 @@ -P:System.Net.Quic.QuicProvider.IsSupported \ No newline at end of file +P:System.Net.Quic.QuicConnection.IsSupported +P:System.Net.Quic.QuicListener.IsSupported \ No newline at end of file diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index 234ad7272a8d9..a989b8dd455ff 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -18,7 +18,6 @@ - @@ -42,7 +41,8 @@ - + + diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs index cbcc4f83348e2..8dfc80218bfa4 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs @@ -497,7 +497,7 @@ internal int GetRemoteAvailableBidirectionalStreamCount() return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT); } - internal unsafe override ValueTask ConnectAsync(CancellationToken cancellationToken = default) + internal unsafe ValueTask ConnectAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs new file mode 100644 index 0000000000000..93ad515214433 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Net.Quic +{ + public sealed partial class QuicConnection + { + public static bool IsSupported => false; + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index b5ee819f5527b..b919e6e9d38b6 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -3,6 +3,7 @@ using System.Net.Quic.Implementations; using System.Net.Quic.Implementations.MsQuic; +using System.Net.Quic.Implementations.MsQuic.Internal; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Threading; @@ -12,6 +13,18 @@ namespace System.Net.Quic { public sealed class QuicConnection : IDisposable { + public static bool IsSupported => MsQuicApi.IsQuicSupported; + + public static ValueTask ConnectAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken = default) + { + if (!IsSupported) + { + throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported); + } + + return ValueTask.FromResult(new QuicConnection(new MsQuicConnection(options))); + } + private readonly MsQuicConnection _provider; internal QuicConnection(MsQuicConnection provider) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.Unsupported.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.Unsupported.cs similarity index 83% rename from src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.Unsupported.cs rename to src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.Unsupported.cs index b860c936e5166..6d37aeff8a0b6 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.Unsupported.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.Unsupported.cs @@ -3,7 +3,7 @@ namespace System.Net.Quic { - public static partial class QuicProvider + public sealed partial class QuicListener { public static bool IsSupported => false; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs index 8c31a7c487536..9d29f34176d1f 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs @@ -3,6 +3,7 @@ using System.Net.Quic.Implementations; using System.Net.Quic.Implementations.MsQuic; +using System.Net.Quic.Implementations.MsQuic.Internal; using System.Net.Security; using System.Threading; using System.Threading.Tasks; @@ -11,6 +12,18 @@ namespace System.Net.Quic { public sealed class QuicListener : IDisposable { + public static bool IsSupported => MsQuicApi.IsQuicSupported; + + public static ValueTask ListenAsync(QuicListenerOptions options, CancellationToken cancellationToken = default) + { + if (!IsSupported) + { + throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported); + } + + return ValueTask.FromResult(new QuicListener(new MsQuicListener(options))); + } + private readonly MsQuicListener _provider; internal QuicListener(MsQuicListener provider) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.cs deleted file mode 100644 index c06e41cbec534..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicProvider.cs +++ /dev/null @@ -1,35 +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.Quic.Implementations.MsQuic; -using System.Net.Quic.Implementations.MsQuic.Internal; -using System.Threading; -using System.Threading.Tasks; - -namespace System.Net.Quic -{ - public static partial class QuicProvider - { - public static bool IsSupported => MsQuicApi.IsQuicSupported; - - public static ValueTask CreateListenerAsync(QuicListenerOptions options, CancellationToken cancellationToken = default) - { - if (!IsSupported) - { - throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported); - } - - return ValueTask.FromResult(new QuicListener(new MsQuicListener(options))); - } - - public static ValueTask CreateConnectionAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken = default) - { - if (!IsSupported) - { - throw new PlatformNotSupportedException(SR.SystemNetQuic_PlatformNotSupported); - } - - return ValueTask.FromResult(new QuicConnection(new MsQuicConnection(options))); - } - } -} diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs index 1b8e1d5639b76..f0ac82216343a 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamConnectedStreamConformanceTests.cs @@ -51,7 +51,7 @@ public SslClientAuthenticationOptions GetSslClientAuthenticationOptions() protected override async Task CreateConnectedStreamsAsync() { - var listener = await QuicProvider.CreateListenerAsync(new QuicListenerOptions() + var listener = await QuicListener.ListenAsync(new QuicListenerOptions() { ListenEndPoint = new IPEndPoint(IPAddress.Loopback, 0), ServerAuthenticationOptions = GetSslServerAuthenticationOptions() @@ -71,7 +71,7 @@ await WhenAllOrAnyFailed( { try { - connection2 = await QuicProvider.CreateConnectionAsync(new QuicClientConnectionOptions() + connection2 = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions() { RemoteEndPoint = listener.ListenEndPoint, ClientAuthenticationOptions = GetSslClientAuthenticationOptions() diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicTestBase.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicTestBase.cs index 48880043bfae6..8f970cf6e3f72 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicTestBase.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicTestBase.cs @@ -21,7 +21,7 @@ public abstract class QuicTestBase private static readonly byte[] s_ping = "PING"u8.ToArray(); private static readonly byte[] s_pong = "PONG"u8.ToArray(); - public static bool IsSupported => QuicProvider.IsSupported; + public static bool IsSupported => QuicListener.IsSupported && QuicConnection.IsSupported; public static SslApplicationProtocol ApplicationProtocol { get; } = new SslApplicationProtocol("quictest"); @@ -78,7 +78,7 @@ internal ValueTask CreateQuicConnection(IPEndPoint endpoint) internal ValueTask CreateQuicConnection(QuicClientConnectionOptions clientOptions) { - return QuicProvider.CreateConnectionAsync(clientOptions); + return QuicConnection.ConnectAsync(clientOptions); } internal QuicListenerOptions CreateQuicListenerOptions() @@ -109,7 +109,7 @@ internal ValueTask CreateQuicListener(IPEndPoint endpoint) return CreateQuicListener(options); } - internal ValueTask CreateQuicListener(QuicListenerOptions options) => QuicProvider.CreateListenerAsync(options); + internal ValueTask CreateQuicListener(QuicListenerOptions options) => QuicListener.ListenAsync(options); internal Task<(QuicConnection, QuicConnection)> CreateConnectedQuicConnection(QuicListener listener) => CreateConnectedQuicConnection(null, listener); internal async Task<(QuicConnection, QuicConnection)> CreateConnectedQuicConnection(QuicClientConnectionOptions? clientOptions, QuicListenerOptions listenerOptions) From 911c3a09bc0d1744023c9c4fcee2d5bdefb9f3ce Mon Sep 17 00:00:00 2001 From: ManickaP Date: Sat, 18 Jun 2022 10:46:07 +0200 Subject: [PATCH 3/3] Added assert --- .../Common/tests/System/Net/Http/Http3LoopbackServer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs index c3287d7933bb0..c87eb6c78351b 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs @@ -42,7 +42,9 @@ public Http3LoopbackServer(Http3Options options = null) MaxBidirectionalStreams = options.MaxBidirectionalStreams, }; - _listener = QuicListener.ListenAsync(listenerOptions).Result; + ValueTask valueTask = QuicListener.ListenAsync(listenerOptions); + Debug.Assert(valueTask.IsCompleted); + _listener = valueTask.Result; } public override void Dispose()