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 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);
        }
        public async Task ConnectionShouldCloseAndSignalDoneWhenReadingFromInputFails(bool isServer)
        {
            var inPipe         = new BufferedPipe(1024);
            var outPipe        = new BufferedPipe(1024);
            var failableInPipe = new FailingPipe(inPipe);
            var http2Con       = await ConnectionUtils.BuildEstablishedConnection(
                isServer, failableInPipe, outPipe, loggerProvider);

            // Make the next write attempt fail
            failableInPipe.FailNextRead = true;
            // Send something which triggers no response but will start a new read call
            await inPipe.WriteWindowUpdate(0, 128);

            // Wait for the connection to close the outgoing part
            await outPipe.AssertStreamEnd();

            // If the connection was successfully closed close the incoming data
            // stream, since this is expected from a bidirectional stream implementation
            await inPipe.CloseAsync();

            // Expect the connection to close within timeout
            var closed = http2Con.Done;

            Assert.True(
                closed == await Task.WhenAny(closed, Task.Delay(1000)),
                "Expected connection to close");
        }
Exemplo n.º 4
0
        public async Task ShouldGoAwayWhenStreamWindowIsOverflowedThroughSettingsUpdate()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Let the remote increase the flow control window of the stream
            await inPipe.WriteWindowUpdate(
                1u,
                (int)(int.MaxValue - Settings.Default.InitialWindowSize));

            // Should be still alive
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // And now write new settings which overflow the window
            var newSettings = Settings.Default;

            newSettings.InitialWindowSize++;
            await inPipe.WriteSettings(newSettings);

            // Dead through overflow
            await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 1u);
        }
Exemplo n.º 5
0
        public async Task ReceivingWindowUpdatesOnIdleStreamsShouldTriggerGoAway(
            uint streamId)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            await inPipe.WriteWindowUpdate(streamId, 0);

            await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 1);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 6
0
        public async Task ShouldGoAwayWhenConnectionFlowControlWindowIsOverloaded(
            int amount)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, null);

            await inPipe.WriteWindowUpdate(0, amount);

            await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 0);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 7
0
        public async Task ShouldAllowToSetTheMaxPossibleConnectionFlowControlWindowSize()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, null);

            var amount = int.MaxValue - 65535;
            await inPipe.WriteWindowUpdate(0, amount);

            // Check aliveness with ping/pong
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();
        }
Exemplo n.º 8
0
        public async Task ShouldResetStreamWhenStreamFlowControlWindowIsOverloaded(
            int amount)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            Func <IStream, bool> listener = (s) => true;
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, listener);

            var hEncoder = new Encoder();
            await inPipe.WriteHeaders(hEncoder, 1, false, DefaultGetHeaders);

            await inPipe.WriteWindowUpdate(1, amount);

            await outPipe.AssertResetStreamReception(1, ErrorCode.FlowControlError);
        }
Exemplo n.º 9
0
        public async Task ShouldAllowToSetTheMaxPossibleStreamFlowControlWindowSize()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            Func <IStream, bool> listener = (s) => true;
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, listener);

            var hEncoder = new Encoder();
            await inPipe.WriteHeaders(hEncoder, 1, false, DefaultGetHeaders);

            var amount = int.MaxValue - 65535;
            await inPipe.WriteWindowUpdate(1, amount);

            // Check aliveness with ping/pong
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();
        }
Exemplo n.º 10
0
        public async Task ReceivingWindowUpdatesWith0AmountShouldTriggerGoAwayOrReset(
            uint streamId)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            await inPipe.WriteWindowUpdate(streamId, 0);

            if (streamId == 0)
            {
                await outPipe.AssertGoAwayReception(ErrorCode.ProtocolError, 1);

                await outPipe.AssertStreamEnd();
            }
            else
            {
                await outPipe.AssertResetStreamReception(1u, ErrorCode.ProtocolError);
            }
        }