Exemplo n.º 1
0
        public async Task WritesShouldRespectConnectionFlowControlWindow()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            // Create a stream. It will have a flow control window of 64kb
            // for stream and connection
            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Initiate response by sending and consuming headers
            await res.stream.WriteHeadersAsync(
                DefaultStatusHeaders, false);

            await outPipe.ReadAndDiscardHeaders(1u, false);

            // Increase flow control window for stream so that write is blocked
            // on connection window
            await inPipe.WriteWindowUpdate(1, 1024 *1024);

            var writeTask = Task.Run(async() =>
            {
                await res.stream.WriteAsync(new ArraySegment <byte>(new byte[32000]));
                await res.stream.WriteAsync(new ArraySegment <byte>(new byte[33535 + 1024]));
                await res.stream.WriteAsync(new ArraySegment <byte>(new byte[1024]));
            });
            // Expect to read the stream flow control window amount of data
            await outPipe.ReadAndDiscardData(1u, false, 16384);

            await outPipe.ReadAndDiscardData(1u, false, 15616);

            await outPipe.ReadAndDiscardData(1u, false, 16384);

            await outPipe.ReadAndDiscardData(1u, false, 16384);

            await outPipe.ReadAndDiscardData(1u, false, 767);

            // Give a bigger flow control window for connection and expect more data
            await inPipe.WriteWindowUpdate(0u, 512);

            await outPipe.ReadAndDiscardData(1u, false, 512);

            await inPipe.WriteWindowUpdate(0u, 1024);

            await outPipe.ReadAndDiscardData(1u, false, 512);

            await outPipe.ReadAndDiscardData(1u, false, 512);

            await inPipe.WriteWindowUpdate(0u, 512);

            await outPipe.ReadAndDiscardData(1u, false, 512);

            // Expect the writer to finish
            var doneTask = await Task.WhenAny(writeTask, Task.Delay(250));

            Assert.True(writeTask == doneTask, "Expected write task to finish");
        }
Exemplo n.º 2
0
        public async Task ItShouldBePossibleToSendInformationalHeaders()
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);
            var infoHeaders = new HeaderField[]
            {
                new HeaderField { Name = ":status", Value = "100" },
                new HeaderField { Name = "extension-field", Value = "bar" },
            };
            await r.stream.WriteHeadersAsync(infoHeaders, false);
            await r.stream.WriteHeadersAsync(DefaultStatusHeaders, false);
            await r.stream.WriteAsync(new ArraySegment<byte>(new byte[0]), true);
            await outPipe.ReadAndDiscardHeaders(1, false);
            await outPipe.ReadAndDiscardHeaders(1, false);
            await outPipe.ReadAndDiscardData(1, true, 0);
        }
Exemplo n.º 3
0
        public async Task NegativeFlowControlWindowsThroughSettingsShouldBeSupported()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            // Start with a stream window of 10
            var settings = Settings.Default;

            settings.InitialWindowSize = 10;
            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe,
                remoteSettings : settings);

            // Initiate response by sending and consuming headers
            await res.stream.WriteHeadersAsync(
                DefaultStatusHeaders, false);

            await outPipe.ReadAndDiscardHeaders(1u, false);

            // Start to write 20 bytes of data
            var writeTask = Task.Run(async() =>
            {
                var data = new byte[20];
                await res.stream.WriteAsync(new ArraySegment <byte>(data), true);
            });

            // Expect to receive the first 10 bytes
            await outPipe.ReadAndDiscardData(1u, false, 10);

            // Stream has now a window of 0
            // Decrease that to -10 by decreasing the initial window
            settings.InitialWindowSize = 0;
            await inPipe.WriteSettings(settings);

            await outPipe.AssertSettingsAck();

            // Increase to 0 with window update
            await inPipe.WriteWindowUpdate(1u, 10);

            // Check that we get no data so far by ping/pong
            // If the negative window is not applied we would get new data here
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // Increase to 10 with window update
            await inPipe.WriteWindowUpdate(1u, 10);

            // Expect the remaining 10 bytes of data
            await outPipe.ReadAndDiscardData(1u, true, 10);

            Assert.Equal(StreamState.HalfClosedLocal, res.stream.State);
        }
Exemplo n.º 4
0
        public async Task ReceivingResetShouldYieldAResetException()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var conn = await ConnectionUtils.BuildEstablishedConnection(
                false, inPipe, outPipe, loggerProvider);

            IStream stream = await conn.CreateStreamAsync(DefaultGetHeaders);

            await outPipe.ReadAndDiscardHeaders(1u, false);

            var readTask = stream.ReadWithTimeout(new ArraySegment <byte>(new byte[1]));
            await inPipe.WriteResetStream(1u, ErrorCode.Cancel);

            var ex = await Assert.ThrowsAsync <AggregateException>(
                () => readTask);

            Assert.IsType <StreamResetException>(ex.InnerException);
            Assert.Equal(StreamState.Reset, stream.State);
        }
Exemplo n.º 5
0
        public async Task SendingEmptyDataFramesShouldBePossibleWithoutFlowWindow(
            bool emptyFrameIsEndOfStream)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            // Create a stream. It will have a flow control window of 64kb
            // for stream and connection
            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Initiate response by sending and consuming headers
            await res.stream.WriteHeadersAsync(
                DefaultStatusHeaders, false);

            await outPipe.ReadAndDiscardHeaders(1u, false);

            var writeTask = Task.Run(async() =>
            {
                // Consume the complete flow control window
                await res.stream.WriteAsync(new ArraySegment <byte>(new byte[65535]));
                // And try to send an empty data frame
                await res.stream.WriteAsync(
                    new ArraySegment <byte>(new byte[0]), emptyFrameIsEndOfStream);
            });
            // Expect to read the sent frames
            await outPipe.ReadAndDiscardData(1u, false, 16384);

            await outPipe.ReadAndDiscardData(1u, false, 16384);

            await outPipe.ReadAndDiscardData(1u, false, 16384);

            await outPipe.ReadAndDiscardData(1u, false, 16383);

            await outPipe.ReadAndDiscardData(1u, emptyFrameIsEndOfStream, 0);

            // Expect the writer to finish
            var doneTask = await Task.WhenAny(writeTask, Task.Delay(250));

            Assert.True(writeTask == doneTask, "Expected write task to finish");
        }
Exemplo n.º 6
0
        public async Task BlockedWritesShouldUnblockOnStreamCancel()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            // Create a stream. It will have a flow control window of 64kb
            // for stream and connection
            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Initiate response by sending and consuming headers
            await res.stream.WriteHeadersAsync(
                DefaultStatusHeaders, false);

            await outPipe.ReadAndDiscardHeaders(1u, false);

            // Start discarding all ougoing data -> Not needed for this test
            // and pipe may not be blocked
            var readTask = Task.Run(async() =>
            {
                await outPipe.ReadAllToArrayWithTimeout();
            });
            // Write flow control window amount of data
            await res.stream.WriteWithTimeout(new ArraySegment <byte>(new byte[65535]));

            var resetTask = Task.Run(async() =>
            {
                await Task.Delay(20);
                res.stream.Cancel();
            });
            // Write additional bytes. This should block and cause a streamreset
            // exception when the cancel arrives
            await Assert.ThrowsAsync <StreamResetException>(async() =>
            {
                await res.stream.WriteAsync(new ArraySegment <byte>(new byte[1024]));
            });
        }
Exemplo n.º 7
0
        public async Task TheNextOutgoingStreamAfterUpgradeShouldUseId3()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var upgrade = new ClientUpgradeRequestBuilder().Build();
            var config  = new ConnectionConfigurationBuilder(false)
                          .Build();

            var conn = new Connection(
                config, inPipe, outPipe,
                new Connection.Options
            {
                Logger = loggerProvider.CreateLogger("http2Con"),
                ClientUpgradeRequest = upgrade,
            });

            await conn.PerformHandshakes(inPipe, outPipe);

            var stream = await upgrade.UpgradeRequestStream;

            Assert.Equal(1u, stream.Id);

            var readHeadersTask = stream.ReadHeadersAsync();

            Assert.False(readHeadersTask.IsCompleted);

            var nextStream = await conn.CreateStreamAsync(DefaultGetHeaders);

            await outPipe.ReadAndDiscardHeaders(3u, false);

            Assert.Equal(3u, nextStream.Id);
            Assert.True(stream != nextStream);
            Assert.Equal(StreamState.HalfClosedLocal, stream.State);
            Assert.Equal(StreamState.Open, nextStream.State);

            var hEncoder = new Http2.Hpack.Encoder();
            await inPipe.WriteHeaders(hEncoder, 3u, true, DefaultStatusHeaders);

            var nextStreamHeaders = await nextStream.ReadHeadersAsync();

            Assert.True(nextStreamHeaders.SequenceEqual(DefaultStatusHeaders));
            Assert.False(readHeadersTask.IsCompleted);
            Assert.Equal(StreamState.HalfClosedRemote, nextStream.State);
            Assert.Equal(StreamState.HalfClosedLocal, stream.State);
            Assert.Equal(2, conn.ActiveStreamCount);

            await nextStream.WriteAsync(new ArraySegment <byte>(new byte[0]), true);

            await outPipe.ReadAndDiscardData(3u, true, 0);

            Assert.Equal(StreamState.Closed, nextStream.State);
            Assert.Equal(1, conn.ActiveStreamCount);

            var headers2 = DefaultStatusHeaders.Append(
                new HeaderField()
            {
                Name = "hh", Value = "vv"
            });
            await inPipe.WriteHeaders(hEncoder, 1u, false, headers2);

            var streamHeaders = await readHeadersTask;

            Assert.True(streamHeaders.SequenceEqual(headers2));
            await inPipe.WriteData(1u, 10, 0, true);

            var data = await stream.ReadAllToArrayWithTimeout();

            Assert.True(data.Length == 10);
            Assert.Equal(StreamState.Closed, stream.State);
            Assert.Equal(0, conn.ActiveStreamCount);
        }