From a012247b94fc31dc978d8acc0584d7b51a0f14de Mon Sep 17 00:00:00 2001 From: Bar Arnon Date: Tue, 3 Aug 2021 16:28:54 +0300 Subject: [PATCH 1/7] Add SslApplicationProtocol.Http3 Fix #1293 --- src/libraries/System.Net.Security/ref/System.Net.Security.cs | 3 ++- .../src/System/Net/Security/SslApplicationProtocol.cs | 4 ++++ .../tests/UnitTests/SslApplicationProtocolTests.cs | 2 ++ .../tests/UnitTests/SslAuthenticationOptionsTests.cs | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Security/ref/System.Net.Security.cs b/src/libraries/System.Net.Security/ref/System.Net.Security.cs index d31416123ca8e..eadbe245af53d 100644 --- a/src/libraries/System.Net.Security/ref/System.Net.Security.cs +++ b/src/libraries/System.Net.Security/ref/System.Net.Security.cs @@ -118,8 +118,9 @@ public readonly struct SslClientHelloInfo { private readonly object _dummy; private readonly int _dummyPrimitive; - public static readonly System.Net.Security.SslApplicationProtocol Http11; + public static readonly System.Net.Security.SslApplicationProtocol Http3; public static readonly System.Net.Security.SslApplicationProtocol Http2; + public static readonly System.Net.Security.SslApplicationProtocol Http11; public SslApplicationProtocol(byte[] protocol) { throw null; } public SslApplicationProtocol(string protocol) { throw null; } public System.ReadOnlyMemory Protocol { get { throw null; } } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslApplicationProtocol.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslApplicationProtocol.cs index ebac2d844fab5..7f4f0a7615d3a 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslApplicationProtocol.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslApplicationProtocol.cs @@ -10,10 +10,13 @@ namespace System.Net.Security public readonly struct SslApplicationProtocol : IEquatable { private static readonly Encoding s_utf8 = Encoding.GetEncoding(Encoding.UTF8.CodePage, EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback); + private static readonly byte[] s_http3Utf8 = new byte[] { 0x68, 0x33 }; // "h3" private static readonly byte[] s_http2Utf8 = new byte[] { 0x68, 0x32 }; // "h2" private static readonly byte[] s_http11Utf8 = new byte[] { 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 }; // "http/1.1" // Refer to IANA on ApplicationProtocols: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids + // h3 + public static readonly SslApplicationProtocol Http3 = new SslApplicationProtocol(s_http3Utf8, copy: false); // h2 public static readonly SslApplicationProtocol Http2 = new SslApplicationProtocol(s_http2Utf8, copy: false); // http/1.1 @@ -77,6 +80,7 @@ public override string ToString() { return arr is null ? string.Empty : + ReferenceEquals(arr, s_http3Utf8) ? "h3" : ReferenceEquals(arr, s_http2Utf8) ? "h2" : ReferenceEquals(arr, s_http11Utf8) ? "http/1.1" : s_utf8.GetString(arr); diff --git a/src/libraries/System.Net.Security/tests/UnitTests/SslApplicationProtocolTests.cs b/src/libraries/System.Net.Security/tests/UnitTests/SslApplicationProtocolTests.cs index 34a11a05d94ea..fe016e6c631ef 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/SslApplicationProtocolTests.cs +++ b/src/libraries/System.Net.Security/tests/UnitTests/SslApplicationProtocolTests.cs @@ -13,6 +13,7 @@ public class SslApplicationProtocolTests [Fact] public void Constants_Values_AreCorrect() { + Assert.Equal(new SslApplicationProtocol(new byte[] { 0x68, 0x33 }), SslApplicationProtocol.Http3); Assert.Equal(new SslApplicationProtocol(new byte[] { 0x68, 0x32 }), SslApplicationProtocol.Http2); Assert.Equal(new SslApplicationProtocol(new byte[] { 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 }), SslApplicationProtocol.Http11); } @@ -75,6 +76,7 @@ public void ToString_Rendering_Succeeds() { Assert.Equal("http/1.1", SslApplicationProtocol.Http11.ToString()); Assert.Equal("h2", SslApplicationProtocol.Http2.ToString()); + Assert.Equal("h3", SslApplicationProtocol.Http3.ToString()); Assert.Equal("hello", new SslApplicationProtocol("hello").ToString()); Assert.Equal("0x0b 0xee", new SslApplicationProtocol(new byte[] { 0x0B, 0xEE }).ToString()); Assert.Equal(string.Empty, default(SslApplicationProtocol).ToString()); diff --git a/src/libraries/System.Net.Security/tests/UnitTests/SslAuthenticationOptionsTests.cs b/src/libraries/System.Net.Security/tests/UnitTests/SslAuthenticationOptionsTests.cs index 91d40fc744837..354acab9021bd 100644 --- a/src/libraries/System.Net.Security/tests/UnitTests/SslAuthenticationOptionsTests.cs +++ b/src/libraries/System.Net.Security/tests/UnitTests/SslAuthenticationOptionsTests.cs @@ -41,7 +41,7 @@ public void ApplicationProtocols_Get_Set_Succeeds() Assert.Null(_clientOptions.ApplicationProtocols); Assert.Null(_serverOptions.ApplicationProtocols); - List applnProtos = new List { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; + List applnProtos = new List { SslApplicationProtocol.Http3, SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; _clientOptions.ApplicationProtocols = applnProtos; _serverOptions.ApplicationProtocols = applnProtos; From c80a0cbb9e59a58fef2c5284eeb1a18b9b8a0702 Mon Sep 17 00:00:00 2001 From: Bar Arnon Date: Tue, 3 Aug 2021 16:34:26 +0300 Subject: [PATCH 2/7] Add XML doc --- .../src/System/Net/Security/SslApplicationProtocol.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslApplicationProtocol.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslApplicationProtocol.cs index 7f4f0a7615d3a..f218ce2875128 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslApplicationProtocol.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslApplicationProtocol.cs @@ -15,11 +15,11 @@ namespace System.Net.Security private static readonly byte[] s_http11Utf8 = new byte[] { 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31 }; // "http/1.1" // Refer to IANA on ApplicationProtocols: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids - // h3 + /// Defines a instance for HTTP 3.0. public static readonly SslApplicationProtocol Http3 = new SslApplicationProtocol(s_http3Utf8, copy: false); - // h2 + /// Defines a instance for HTTP 2.0. public static readonly SslApplicationProtocol Http2 = new SslApplicationProtocol(s_http2Utf8, copy: false); - // http/1.1 + /// Defines a instance for HTTP 1.1. public static readonly SslApplicationProtocol Http11 = new SslApplicationProtocol(s_http11Utf8, copy: false); private readonly byte[] _readOnlyProtocol; From 67e695f3cbe84d2944f9b5497a5d8ea088f9a607 Mon Sep 17 00:00:00 2001 From: Bar Arnon Date: Tue, 3 Aug 2021 16:52:31 +0300 Subject: [PATCH 3/7] Reuse in Http3Connection --- .../Net/Http/SocketsHttpHandler/Http3Connection.cs | 3 --- .../Http/SocketsHttpHandler/HttpConnectionPool.cs | 13 +------------ 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs index 279c769f714a2..dca12ee814794 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs @@ -20,9 +20,6 @@ namespace System.Net.Http [SupportedOSPlatform("macos")] internal sealed class Http3Connection : HttpConnectionBase { - // TODO: once HTTP/3 is standardized, create APIs for this. - public static readonly SslApplicationProtocol Http3ApplicationProtocol = new SslApplicationProtocol("h3"); - private readonly HttpConnectionPool _pool; private readonly HttpAuthority? _origin; private readonly HttpAuthority _authority; 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 8f14d1fe66d45..6c65b97c73148 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 @@ -295,21 +295,10 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK [SupportedOSPlatformGuard("Windows")] internal static bool IsHttp3Supported() => (OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS(); - private static readonly List s_http3ApplicationProtocols = CreateHttp3ApplicationProtocols(); + private static readonly List s_http3ApplicationProtocols = new List() { SslApplicationProtocol.Http3, SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; private static readonly List s_http2ApplicationProtocols = new List() { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; private static readonly List s_http2OnlyApplicationProtocols = new List() { SslApplicationProtocol.Http2 }; - private static List CreateHttp3ApplicationProtocols() - { - if (IsHttp3Supported()) - { - // TODO: Once the HTTP/3 versions are part of SslApplicationProtocol, see https://github.com/dotnet/runtime/issues/1293, move this back to field initialization. - return new List() { Http3Connection.Http3ApplicationProtocol }; - } - - return null!; - } - private static SslClientAuthenticationOptions ConstructSslOptions(HttpConnectionPoolManager poolManager, string sslHostName) { Debug.Assert(sslHostName != null); From 68c435fd56314955228f4ebee2267e69335d9e9b Mon Sep 17 00:00:00 2001 From: Bar Arnon Date: Tue, 3 Aug 2021 16:56:45 +0300 Subject: [PATCH 4/7] Reuse in tests --- .../tests/FunctionalTests/HttpClientHandlerTest.Http3.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 df5b59b500eb3..c7d7ed8b2873f 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs @@ -650,7 +650,7 @@ public async Task Alpn_H3_Success() using Http3LoopbackConnection connection = (Http3LoopbackConnection)await server.EstablishGenericConnectionAsync(); SslApplicationProtocol negotiatedAlpn = ExtractMsQuicNegotiatedAlpn(connection); - Assert.Equal(new SslApplicationProtocol("h3"), negotiatedAlpn); + Assert.Equal(SslApplicationProtocol.Http3, negotiatedAlpn); using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync(); await stream.HandleRequestAsync(); From c4fae7392ed97f3dc9d7ebdd0cf7c8a1f05459ab Mon Sep 17 00:00:00 2001 From: Bar Arnon Date: Tue, 3 Aug 2021 16:58:49 +0300 Subject: [PATCH 5/7] HTTP/3 has no negotiation --- .../System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 6c65b97c73148..3389946c710e4 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 @@ -295,7 +295,7 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK [SupportedOSPlatformGuard("Windows")] internal static bool IsHttp3Supported() => (OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS(); - private static readonly List s_http3ApplicationProtocols = new List() { SslApplicationProtocol.Http3, SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; + private static readonly List s_http3ApplicationProtocols = new List() { SslApplicationProtocol.Http3 }; private static readonly List s_http2ApplicationProtocols = new List() { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; private static readonly List s_http2OnlyApplicationProtocols = new List() { SslApplicationProtocol.Http2 }; From a008e8eaa69319b8bc360fff267b2d196c4a23be Mon Sep 17 00:00:00 2001 From: Bar Arnon Date: Tue, 3 Aug 2021 17:18:04 +0300 Subject: [PATCH 6/7] Use SslApplicationProtocol.Http3.ToString() in tests --- .../Common/tests/System/Net/Http/Http3LoopbackServer.cs | 2 +- .../tests/FunctionalTests/HttpClientHandlerTest.Http3.cs | 2 +- .../tests/StressTests/HttpStress/StressServer.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs index ffd97b9219c2b..3ba40c4655439 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackServer.cs @@ -130,7 +130,7 @@ public Http3Options() { MaxUnidirectionalStreams = 100; MaxBidirectionalStreams = 100; - Alpn = "h3"; + Alpn = SslApplicationProtocol.Http3.ToString(); } } } 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 c7d7ed8b2873f..42c42d43f39bd 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs @@ -639,7 +639,7 @@ public async Task Alpn_H3_Success() return; } - var options = new Http3Options() { Alpn = "h3" }; + var options = new Http3Options() { Alpn = SslApplicationProtocol.Http3.ToString() }; using Http3LoopbackServer server = CreateHttp3LoopbackServer(options); using var clientDone = new SemaphoreSlim(0); diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressServer.cs b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressServer.cs index e994e7ed15cb2..c4c05ee6fb1f0 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressServer.cs +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressServer.cs @@ -127,7 +127,7 @@ void ConfigureListenOptions(ListenOptions listenOptions) { host = host.UseQuic(options => { - options.Alpn = "h3"; + options.Alpn = SslApplicationProtocol.Http3.ToString(); options.IdleTimeout = TimeSpan.FromMinutes(1); }); } From 3a24095a12da594e4ff5d167ba47180703c46082 Mon Sep 17 00:00:00 2001 From: Bar Arnon Date: Tue, 3 Aug 2021 17:39:58 +0300 Subject: [PATCH 7/7] Ascending order in ref --- src/libraries/System.Net.Security/ref/System.Net.Security.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Security/ref/System.Net.Security.cs b/src/libraries/System.Net.Security/ref/System.Net.Security.cs index eadbe245af53d..ded8bc9ffa09f 100644 --- a/src/libraries/System.Net.Security/ref/System.Net.Security.cs +++ b/src/libraries/System.Net.Security/ref/System.Net.Security.cs @@ -118,9 +118,9 @@ public readonly struct SslClientHelloInfo { private readonly object _dummy; private readonly int _dummyPrimitive; - public static readonly System.Net.Security.SslApplicationProtocol Http3; - public static readonly System.Net.Security.SslApplicationProtocol Http2; public static readonly System.Net.Security.SslApplicationProtocol Http11; + public static readonly System.Net.Security.SslApplicationProtocol Http2; + public static readonly System.Net.Security.SslApplicationProtocol Http3; public SslApplicationProtocol(byte[] protocol) { throw null; } public SslApplicationProtocol(string protocol) { throw null; } public System.ReadOnlyMemory Protocol { get { throw null; } }