{
MaxUnidirectionalStreams = 100;
MaxBidirectionalStreams = 100;
- Alpn = "h3";
+ Alpn = SslApplicationProtocol.Http3.ToString();
}
}
}
[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;
[SupportedOSPlatformGuard("Windows")]
internal static bool IsHttp3Supported() => (OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS();
- private static readonly List<SslApplicationProtocol> s_http3ApplicationProtocols = CreateHttp3ApplicationProtocols();
+ private static readonly List<SslApplicationProtocol> s_http3ApplicationProtocols = new List<SslApplicationProtocol>() { SslApplicationProtocol.Http3 };
private static readonly List<SslApplicationProtocol> s_http2ApplicationProtocols = new List<SslApplicationProtocol>() { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 };
private static readonly List<SslApplicationProtocol> s_http2OnlyApplicationProtocols = new List<SslApplicationProtocol>() { SslApplicationProtocol.Http2 };
- private static List<SslApplicationProtocol> 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<SslApplicationProtocol>() { Http3Connection.Http3ApplicationProtocol };
- }
-
- return null!;
- }
-
private static SslClientAuthenticationOptions ConstructSslOptions(HttpConnectionPoolManager poolManager, string sslHostName)
{
Debug.Assert(sslHostName != null);
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);
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();
{
host = host.UseQuic(options =>
{
- options.Alpn = "h3";
+ options.Alpn = SslApplicationProtocol.Http3.ToString();
options.IdleTimeout = TimeSpan.FromMinutes(1);
});
}
private readonly int _dummyPrimitive;
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<byte> Protocol { get { throw null; } }
public readonly struct SslApplicationProtocol : IEquatable<SslApplicationProtocol>
{
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
- // h2
+ /// <summary>Defines a <see cref="SslApplicationProtocol"/> instance for HTTP 3.0.</summary>
+ public static readonly SslApplicationProtocol Http3 = new SslApplicationProtocol(s_http3Utf8, copy: false);
+ /// <summary>Defines a <see cref="SslApplicationProtocol"/> instance for HTTP 2.0.</summary>
public static readonly SslApplicationProtocol Http2 = new SslApplicationProtocol(s_http2Utf8, copy: false);
- // http/1.1
+ /// <summary>Defines a <see cref="SslApplicationProtocol"/> instance for HTTP 1.1.</summary>
public static readonly SslApplicationProtocol Http11 = new SslApplicationProtocol(s_http11Utf8, copy: false);
private readonly byte[] _readOnlyProtocol;
{
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);
[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);
}
{
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());
Assert.Null(_clientOptions.ApplicationProtocols);
Assert.Null(_serverOptions.ApplicationProtocols);
- List<SslApplicationProtocol> applnProtos = new List<SslApplicationProtocol> { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 };
+ List<SslApplicationProtocol> applnProtos = new List<SslApplicationProtocol> { SslApplicationProtocol.Http3, SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 };
_clientOptions.ApplicationProtocols = applnProtos;
_serverOptions.ApplicationProtocols = applnProtos;