public async Task SendMoreThanStreamLimitRequests_Succeeds(int streamLimit)
        {
            using Http3LoopbackServer server = CreateHttp3LoopbackServer();

            Task serverTask = Task.Run(async() =>
            {
                using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync();
                for (int i = 0; i < streamLimit + 1; ++i)
                {
                    using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync();
                    await stream.HandleRequestAsync();
                }
            });

            Task clientTask = Task.Run(async() =>
            {
                using HttpClient client = CreateHttpClient();

                for (int i = 0; i < streamLimit + 1; ++i)
                {
                    using HttpRequestMessage request = new()
                          {
                              Method        = HttpMethod.Get,
                              RequestUri    = server.Address,
                              Version       = HttpVersion30,
                              VersionPolicy = HttpVersionPolicy.RequestVersionExact
                          };
                    using var response = await client.SendAsync(request).WaitAsync(TimeSpan.FromSeconds(10));
                }
            });

            await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000);
        }
Exemplo n.º 2
0
        public async Task AltSvc_Header_Upgrade_Success(Version fromVersion)
        {
            // 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
                  {
                      1 => new LoopbackServer(new LoopbackServer.Options { UseSsl = true }),
                      2 => Http2LoopbackServer.CreateServer(),
                      _ => throw new Exception("Unknown HTTP version.")
                  };

            // The second request is expected to come in on this HTTP/3 server.
            using var secondServer = new Http3LoopbackServer();

            using HttpClient client = CreateHttpClient();

            Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address);
            Task serverTask = firstServer.AcceptConnectionSendResponseAndCloseAsync(additionalHeaders: new[]
            {
                new HttpHeaderData("Alt-Svc", $"h3=\"{secondServer.Address.IdnHost}:{secondServer.Address.Port}\"")
            });

            await new[] { firstResponseTask, serverTask }.WhenAllOrAnyFailed(30_000);

            using HttpResponseMessage firstResponse = firstResponseTask.Result;
            Assert.True(firstResponse.IsSuccessStatusCode);

            await AltSvc_Upgrade_Success(firstServer, secondServer, client);
        }
Exemplo n.º 3
0
        public async Task AltSvc_ResponseFrame_UpgradeFrom20_Success()
        {
            using Http2LoopbackServer firstServer  = Http2LoopbackServer.CreateServer();
            using Http3LoopbackServer secondServer = new Http3LoopbackServer();
            using HttpClient client = CreateHttpClient();

            Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address);
            Task serverTask = Task.Run(async() =>
            {
                using Http2LoopbackConnection connection = await firstServer.EstablishConnectionAsync();

                int streamId = await connection.ReadRequestHeaderAsync();
                await connection.SendDefaultResponseHeadersAsync(streamId);
                await connection.WriteFrameAsync(new AltSvcFrame("", $"h3=\"{secondServer.Address.IdnHost}:{secondServer.Address.Port}\"", streamId));
                await connection.SendResponseDataAsync(streamId, Array.Empty <byte>(), true);
            });

            await new[] { firstResponseTask, serverTask }.WhenAllOrAnyFailed(30_000);

            HttpResponseMessage firstResponse = firstResponseTask.Result;

            Assert.True(firstResponse.IsSuccessStatusCode);

            await AltSvc_Upgrade_Success(firstServer, secondServer, client);
        }
        public async Task AltSvc_ResponseFrame_UpgradeFrom20_Success()
        {
            using Http2LoopbackServer firstServer  = Http2LoopbackServer.CreateServer();
            using Http3LoopbackServer secondServer = new Http3LoopbackServer();
            using HttpClient client = CreateHttpClient(CreateHttpClientHandler(HttpVersion.Version30));

            Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address);

            using (Http2LoopbackConnection connection = await firstServer.EstablishConnectionAsync())
            {
                int streamId = await connection.ReadRequestHeaderAsync();

                await connection.SendDefaultResponseHeadersAsync(streamId);

                await connection.WriteFrameAsync(new AltSvcFrame("", $"h3={secondServer.Address.IdnHost}:{secondServer.Address.Port}", streamId));

                await connection.SendResponseDataAsync(streamId, Array.Empty <byte>(), true);
            }

            HttpResponseMessage firstResponse = await firstResponseTask;

            Assert.True(firstResponse.IsSuccessStatusCode);

            await AltSvc_Upgrade_Success(firstServer, secondServer, client);
        }
Exemplo n.º 5
0
        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);

            Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address);
            Task serverTask = Task.Run(async() =>
            {
                using Http2LoopbackConnection connection = await firstServer.EstablishConnectionAsync();

                int streamId = await connection.ReadRequestHeaderAsync();
                await connection.WriteFrameAsync(new AltSvcFrame($"https://{firstServer.Address.IdnHost}:{firstServer.Address.Port}", $"h3=\"{secondServer.Address.IdnHost}:{secondServer.Address.Port}\"", streamId: 0));
                await connection.SendDefaultResponseAsync(streamId);
            });

            await new[] { firstResponseTask, serverTask }.WhenAllOrAnyFailed(30_000);

            HttpResponseMessage firstResponse = firstResponseTask.Result;

            Assert.True(firstResponse.IsSuccessStatusCode);

            await AltSvc_Upgrade_Success(firstServer, secondServer, client);
        }
        private async Task AltSvc_Upgrade_Success(GenericLoopbackServer firstServer, Http3LoopbackServer secondServer, HttpClient client)
        {
            Task <HttpResponseMessage> secondResponseTask = client.GetAsync(firstServer.Address);

            HttpRequestData secondRequest = await secondServer.AcceptConnectionSendResponseAndCloseAsync();

            string altUsed = secondRequest.GetSingleHeaderValue("Alt-Used");

            Assert.Equal($"{secondServer.Address.IdnHost}:{secondServer.Address.Port}", altUsed);

            HttpResponseMessage secondResponse = await secondResponseTask;

            Assert.True(secondResponse.IsSuccessStatusCode);
        }
Exemplo n.º 7
0
        private async Task AltSvc_Upgrade_Success(GenericLoopbackServer firstServer, Http3LoopbackServer secondServer, HttpClient client)
        {
            Task <HttpResponseMessage> secondResponseTask = client.GetAsync(firstServer.Address);
            Task <HttpRequestData>     secondRequestTask  = secondServer.AcceptConnectionSendResponseAndCloseAsync();

            await new[] { (Task)secondResponseTask, secondRequestTask }.WhenAllOrAnyFailed(30_000);

            HttpRequestData secondRequest = secondRequestTask.Result;

            using HttpResponseMessage secondResponse = secondResponseTask.Result;

            string altUsed = secondRequest.GetSingleHeaderValue("Alt-Used");

            Assert.Equal($"{secondServer.Address.IdnHost}:{secondServer.Address.Port}", altUsed);
            Assert.True(secondResponse.IsSuccessStatusCode);
        }
        [InlineData(10_000_000)] // 8 bytes settings value.
        public async Task ClientSettingsReceived_Success(int headerSizeLimit)
        {
            using Http3LoopbackServer server = CreateHttp3LoopbackServer();

            Task serverTask = Task.Run(async() =>
            {
                using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync();

                (Http3LoopbackStream settingsStream, Http3LoopbackStream requestStream) = await connection.AcceptControlAndRequestStreamAsync();

                using (settingsStream)
                    using (requestStream)
                    {
                        Assert.False(settingsStream.CanWrite, "Expected unidirectional control stream.");

                        long?streamType = await settingsStream.ReadIntegerAsync();
                        Assert.Equal(Http3LoopbackStream.ControlStream, streamType);

                        List <(long settingId, long settingValue)> settings = await settingsStream.ReadSettingsAsync();
                        (long settingId, long settingValue) = Assert.Single(settings);

                        Assert.Equal(Http3LoopbackStream.MaxHeaderListSize, settingId);
                        Assert.Equal(headerSizeLimit * 1024L, settingValue);

                        await requestStream.ReadRequestDataAsync();
                        await requestStream.SendResponseAsync();
                    }
            });

            Task clientTask = Task.Run(async() =>
            {
                using HttpClientHandler handler  = CreateHttpClientHandler();
                handler.MaxResponseHeadersLength = headerSizeLimit;

                using HttpClient client          = CreateHttpClient(handler);
                using HttpRequestMessage request = new()
                      {
                          Method        = HttpMethod.Get,
                          RequestUri    = server.Address,
                          Version       = HttpVersion30,
                          VersionPolicy = HttpVersionPolicy.RequestVersionExact
                      };
                using HttpResponseMessage response = await client.SendAsync(request);
            });

            await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000);
        }
        private async Task AltSvc_Header_Upgrade_Success(Version fromVersion)
        {
            using GenericLoopbackServer firstServer = GetFactoryForVersion(fromVersion).CreateServer();
            using Http3LoopbackServer secondServer  = new Http3LoopbackServer();
            using HttpClient client = CreateHttpClient(CreateHttpClientHandler(HttpVersion.Version30));

            Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address);

            await firstServer.AcceptConnectionSendResponseAndCloseAsync(additionalHeaders : new[]
            {
                new HttpHeaderData("Alt-Svc", $"h3={secondServer.Address.IdnHost}:{secondServer.Address.Port}")
            });

            HttpResponseMessage firstResponse = await firstResponseTask;

            Assert.True(firstResponse.IsSuccessStatusCode);

            await AltSvc_Upgrade_Success(firstServer, secondServer, client);
        }
Exemplo n.º 10
0
        public async Task SendMoreThanStreamLimitRequests_Succeeds(int streamLimit)
        {
            // [ActiveIssue("https://github.com/dotnet/runtime/issues/55957")]
            if (this.UseQuicImplementationProvider == QuicImplementationProviders.Mock)
            {
                return;
            }

            using Http3LoopbackServer server = CreateHttp3LoopbackServer(new Http3Options()
            {
                MaxBidirectionalStreams = streamLimit
            });

            Task serverTask = Task.Run(async() =>
            {
                using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync();
                for (int i = 0; i < streamLimit + 1; ++i)
                {
                    using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync();
                    await stream.HandleRequestAsync();
                }
            });

            Task clientTask = Task.Run(async() =>
            {
                using HttpClient client = CreateHttpClient();

                for (int i = 0; i < streamLimit + 1; ++i)
                {
                    HttpRequestMessage request = new()
                    {
                        Method        = HttpMethod.Get,
                        RequestUri    = server.Address,
                        Version       = HttpVersion30,
                        VersionPolicy = HttpVersionPolicy.RequestVersionExact
                    };
                    using var response = await client.SendAsync(request).WaitAsync(TimeSpan.FromSeconds(10));
                }
            });

            await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000);
        }
        public async Task SendStreamLimitRequestsConcurrently_Succeeds(int streamLimit)
        {
            using Http3LoopbackServer server = CreateHttp3LoopbackServer(new Http3Options()
            {
                MaxBidirectionalStreams = streamLimit
            });

            Task serverTask = Task.Run(async() =>
            {
                using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync();
                for (int i = 0; i < streamLimit; ++i)
                {
                    using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync();
                    await stream.HandleRequestAsync();
                }
            });

            Task clientTask = Task.Run(async() =>
            {
                using HttpClient client = CreateHttpClient();

                var tasks = new Task <HttpResponseMessage> [streamLimit];
                Parallel.For(0, streamLimit, i =>
                {
                    HttpRequestMessage request = new()
                    {
                        Method        = HttpMethod.Get,
                        RequestUri    = server.Address,
                        Version       = HttpVersion30,
                        VersionPolicy = HttpVersionPolicy.RequestVersionExact
                    };

                    tasks[i] = client.SendAsync(request);
                });

                var responses = await Task.WhenAll(tasks);
                foreach (var response in responses)
                {
                    response.Dispose();
                }
            });
Exemplo n.º 12
0
        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
                  {
                      1 => Http11LoopbackServerFactory.Singleton.CreateServer(new LoopbackServer.Options { UseSsl = true }),
                      2 => Http2LoopbackServer.CreateServer(),
                      _ => throw new Exception("Unknown HTTP version.")
                  };

            // 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);
            }

            using HttpClient client = CreateHttpClient(fromVersion);

            Task <HttpResponseMessage> firstResponseTask = client.GetAsync(firstServer.Address);
            Task serverTask = firstServer.AcceptConnectionSendResponseAndCloseAsync(additionalHeaders: new[]
            {
                new HttpHeaderData("Alt-Svc", $"h3=\"{(overrideHost ? secondServer.Address.IdnHost : null)}:{secondServer.Address.Port}\"")
            });

            await new[] { firstResponseTask, serverTask }.WhenAllOrAnyFailed(30_000);

            using HttpResponseMessage firstResponse = firstResponseTask.Result;
            Assert.True(firstResponse.IsSuccessStatusCode);

            await AltSvc_Upgrade_Success(firstServer, secondServer, client);
        }
        public async Task ReservedFrameType_Throws()
        {
            const int  ReservedHttp2PriorityFrameId = 0x2;
            const long UnexpectedFrameErrorCode     = 0x105;

            using Http3LoopbackServer server = CreateHttp3LoopbackServer();

            Task serverTask = Task.Run(async() =>
            {
                using Http3LoopbackConnection connection = (Http3LoopbackConnection) await server.EstablishGenericConnectionAsync();
                using Http3LoopbackStream stream         = await connection.AcceptRequestStreamAsync();

                await stream.SendFrameAsync(ReservedHttp2PriorityFrameId, new byte[8]);

                QuicConnectionAbortedException ex = await Assert.ThrowsAsync <QuicConnectionAbortedException>(async() =>
                {
                    await stream.HandleRequestAsync();
                    using Http3LoopbackStream stream2 = await connection.AcceptRequestStreamAsync();
                });

                Assert.Equal(UnexpectedFrameErrorCode, ex.ErrorCode);
            });

            Task clientTask = Task.Run(async() =>
            {
                using HttpClient client          = CreateHttpClient();
                using HttpRequestMessage request = new()
                      {
                          Method        = HttpMethod.Get,
                          RequestUri    = server.Address,
                          Version       = HttpVersion30,
                          VersionPolicy = HttpVersionPolicy.RequestVersionExact
                      };

                await Assert.ThrowsAsync <HttpRequestException>(async() => await client.SendAsync(request));
            });

            await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000);
        }