public async Task MaxResponseContentBufferSize_ThrowsIfTooSmallForContent(int maxSize, int contentLength, bool exceptionExpected)
        {
            var content = new CustomContent(async s =>
            {
                await s.WriteAsync(TestHelper.GenerateRandomContent(contentLength));
            });

            var handler = new CustomResponseHandler((r, c) => Task.FromResult(new HttpResponseMessage()
            {
                Content = content
            }));

            using (var client = new HttpClient(handler))
            {
                client.MaxResponseContentBufferSize = maxSize;

                if (exceptionExpected)
                {
                    await Assert.ThrowsAsync <HttpRequestException>(() => client.GetAsync(CreateFakeUri()));
                }
                else
                {
                    await client.GetAsync(CreateFakeUri());
                }
            }
        }
Exemple #2
0
        public async Task Http2_FlowControl_ClientDoesNotExceedWindows()
        {
            const int InitialWindowSize = 65535;
            const int ContentSize       = 100_000;

            HttpClientHandler handler = CreateHttpClientHandler();

            handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
            TestHelper.EnsureHttp2Feature(handler);

            var content = new ByteArrayContent(TestHelper.GenerateRandomContent(ContentSize));

            using (var server = Http2LoopbackServer.CreateServer())
                using (var client = new HttpClient(handler))
                {
                    Task <HttpResponseMessage> clientTask = client.PostAsync(server.Address, content);

                    await server.EstablishConnectionAsync();

                    Frame frame = await server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                    int streamId = frame.StreamId;
                    Assert.Equal(FrameType.Headers, frame.Type);
                    Assert.Equal(FrameFlags.EndHeaders, frame.Flags);

                    // Receive up to initial window size
                    int bytesReceived = 0;
                    while (bytesReceived < InitialWindowSize)
                    {
                        frame = await server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                        Assert.Equal(streamId, frame.StreamId);
                        Assert.Equal(FrameType.Data, frame.Type);
                        Assert.Equal(FrameFlags.None, frame.Flags);
                        Assert.True(frame.Length > 0);

                        bytesReceived += frame.Length;
                    }

                    Assert.Equal(InitialWindowSize, bytesReceived);

                    // Issue another read. It shouldn't complete yet. Wait a brief period of time to ensure it doesn't complete.
                    Task <Frame> readFrameTask = server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase connection window by one. This should still not complete the read.
                    await server.WriteFrameAsync(new WindowUpdateFrame(1, 0));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase stream window by two. This should complete the read with a single byte.
                    await server.WriteFrameAsync(new WindowUpdateFrame(2, streamId));

                    frame = await readFrameTask;
                    Assert.Equal(1, frame.Length);
                    bytesReceived++;

                    // Issue another read and ensure it doesn't complete yet.
                    readFrameTask = server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase connection window by two. This should complete the read with a single byte.
                    await server.WriteFrameAsync(new WindowUpdateFrame(2, 0));

                    frame = await readFrameTask;
                    Assert.Equal(1, frame.Length);
                    bytesReceived++;

                    // Issue another read and ensure it doesn't complete yet.
                    readFrameTask = server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase connection window to allow exactly the remaining request size. This should still not complete the read.
                    await server.WriteFrameAsync(new WindowUpdateFrame(ContentSize - bytesReceived - 1, 0));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase stream window to allow exactly the remaining request size. This should allow the rest of the request to be sent.
                    await server.WriteFrameAsync(new WindowUpdateFrame(ContentSize - bytesReceived, streamId));

                    frame = await readFrameTask;
                    Assert.Equal(streamId, frame.StreamId);
                    Assert.Equal(FrameType.Data, frame.Type);
                    Assert.Equal(FrameFlags.None, frame.Flags);
                    Assert.True(frame.Length > 0);

                    bytesReceived += frame.Length;

                    // Read to end of stream
                    while (true)
                    {
                        frame = await server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                        if (frame.EndStreamFlag)
                        {
                            break;
                        }

                        Assert.Equal(streamId, frame.StreamId);
                        Assert.Equal(FrameType.Data, frame.Type);
                        Assert.Equal(FrameFlags.None, frame.Flags);
                        Assert.True(frame.Length > 0);

                        bytesReceived += frame.Length;
                    }

                    Assert.Equal(ContentSize, bytesReceived);

                    // Verify EndStream frame
                    Assert.Equal(streamId, frame.StreamId);
                    Assert.Equal(FrameType.Data, frame.Type);
                    Assert.Equal(FrameFlags.EndStream, frame.Flags);
                    Assert.True(frame.Length == 0);

                    await server.SendDefaultResponseAsync(streamId);

                    HttpResponseMessage response = await clientTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                }
        }
Exemple #3
0
        public async Task Http2_InitialWindowSize_ClientDoesNotExceedWindows()
        {
            const int DefaultInitialWindowSize = 65535;
            const int ContentSize = 100_000;

            HttpClientHandler handler = CreateHttpClientHandler();

            handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
            TestHelper.EnsureHttp2Feature(handler);

            var content = new ByteArrayContent(TestHelper.GenerateRandomContent(ContentSize));

            using (var server = Http2LoopbackServer.CreateServer())
                using (var client = new HttpClient(handler))
                {
                    Task <HttpResponseMessage> clientTask = client.PostAsync(server.Address, content);

                    await server.EstablishConnectionAsync();

                    // Bump connection window so it won't block the client.
                    await server.WriteFrameAsync(new WindowUpdateFrame(ContentSize - DefaultInitialWindowSize, 0));

                    Frame frame = await server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                    int streamId = frame.StreamId;
                    Assert.Equal(FrameType.Headers, frame.Type);
                    Assert.Equal(FrameFlags.EndHeaders, frame.Flags);

                    // Receive up to initial window size
                    int bytesReceived = 0;
                    while (bytesReceived < DefaultInitialWindowSize)
                    {
                        frame = await server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                        Assert.Equal(streamId, frame.StreamId);
                        Assert.Equal(FrameType.Data, frame.Type);
                        Assert.Equal(FrameFlags.None, frame.Flags);
                        Assert.True(frame.Length > 0);

                        bytesReceived += frame.Length;
                    }

                    Assert.Equal(DefaultInitialWindowSize, bytesReceived);

                    // Issue another read. It shouldn't complete yet. Wait a brief period of time to ensure it doesn't complete.
                    Task <Frame> readFrameTask = server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Change SETTINGS_INITIAL_WINDOW_SIZE to 0. This will make the client's credit go negative.
                    server.ExpectSettingsAck();
                    await server.WriteFrameAsync(new SettingsFrame(new SettingsEntry {
                        SettingId = SettingId.InitialWindowSize, Value = 0
                    }));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase stream window by one. Client credit will still be negative.
                    await server.WriteFrameAsync(new WindowUpdateFrame(1, streamId));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Change SETTINGS_INITIAL_WINDOW_SIZE to 1. Client credit will still be negative.
                    server.ExpectSettingsAck();
                    await server.WriteFrameAsync(new SettingsFrame(new SettingsEntry {
                        SettingId = SettingId.InitialWindowSize, Value = 1
                    }));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase stream window so client credit will be 0.
                    await server.WriteFrameAsync(new WindowUpdateFrame(DefaultInitialWindowSize - 2, streamId));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase stream window by one, so client can now send a single byte.
                    await server.WriteFrameAsync(new WindowUpdateFrame(1, streamId));

                    frame = await readFrameTask;
                    Assert.Equal(FrameType.Data, frame.Type);
                    Assert.Equal(1, frame.Length);
                    bytesReceived++;

                    // Issue another read and ensure it doesn't complete yet.
                    readFrameTask = server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase SETTINGS_INITIAL_WINDOW_SIZE to 2, so client can now send a single byte.
                    server.ExpectSettingsAck();
                    await server.WriteFrameAsync(new SettingsFrame(new SettingsEntry {
                        SettingId = SettingId.InitialWindowSize, Value = 2
                    }));

                    frame = await readFrameTask;
                    Assert.Equal(FrameType.Data, frame.Type);
                    Assert.Equal(1, frame.Length);
                    bytesReceived++;

                    // Issue another read and ensure it doesn't complete yet.
                    readFrameTask = server.ReadFrameAsync(TimeSpan.FromSeconds(30));

                    await Task.Delay(500);

                    Assert.False(readFrameTask.IsCompleted);

                    // Increase SETTINGS_INITIAL_WINDOW_SIZE to be enough that the client can send the rest of the content.
                    server.ExpectSettingsAck();
                    await server.WriteFrameAsync(new SettingsFrame(new SettingsEntry {
                        SettingId = SettingId.InitialWindowSize, Value = ContentSize - (DefaultInitialWindowSize - 1)
                    }));

                    frame = await readFrameTask;
                    Assert.Equal(streamId, frame.StreamId);
                    Assert.Equal(FrameType.Data, frame.Type);
                    Assert.Equal(FrameFlags.None, frame.Flags);
                    Assert.True(frame.Length > 0);

                    bytesReceived += frame.Length;

                    // Read to end of stream
                    bytesReceived += await ReadToEndOfStream(server, streamId);

                    Assert.Equal(ContentSize, bytesReceived);

                    await server.SendDefaultResponseAsync(streamId);

                    HttpResponseMessage response = await clientTask;
                    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                }
        }