Exemplo n.º 1
0
        public async Task StreamWindowUpdatesShouldRespectBufferState()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            // Lower the initial window size so that stream window updates are
            // sent earlier than connection window updates
            var settings = Settings.Default;

            settings.InitialWindowSize = 16000;
            settings.MaxFrameSize      = 1000000;
            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe,
                localSettings : settings);

            // Write 12k of data. Buffer amount: 12k. Remaining window: 4k
            await inPipe.WriteData(1u, 12000);

            // Read 5k of data. Buffer amount: 7k
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[5000]));

            // This should not trigger a window update
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // Read 5k of data. Buffer amount: 2k
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[5000]));

            // Expect a window update of 10k. Remaining window: 14k
            await outPipe.AssertWindowUpdate(1u, 10000);

            // Read 2k of data - buffer is now drained
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[2000]));

            // This should not trigger a window update
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // Write 4k of data. Buffer amount: 4k. Remaining window: 10k
            await inPipe.WriteData(1u, 4000);

            // Read 4k of data. Buffer amount: 0k
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[4000]));

            // This should not trigger a window update
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();

            // Write 8k of data. Buffer amount: 8k. Remaining window: 2k
            await inPipe.WriteData(1u, 8000);

            // Read 5k of data. Buffer amount: 3k
            await res.stream.ReadAllWithTimeout(new ArraySegment <byte>(new byte[5000]));

            // Expect a window update of 11k. Remaining window: 13k
            await outPipe.AssertWindowUpdate(1u, 11000);
        }
Exemplo n.º 2
0
        public async Task SendingLargeAmountOfDataShouldTriggerWindowUpdates(
            int[] dataLength,
            int[] expectedStreamWindowUpdates,
            int[] expectedConnWindowUpdates)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            // Lower the initial window size so that stream window updates are
            // sent earlier than connection window updates
            var settings = Settings.Default;

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

            // Consume all data on reader side
            var readTask = Task.Run(async() =>
            {
                await res.stream.ReadHeadersAsync();
                var data = await res.stream.ReadAllToArrayWithTimeout();
            });

            for (var i = 0; i < dataLength.Length; i++)
            {
                var toSend        = dataLength[i];
                var isEndOfStream = i == (dataLength.Length - 1);
                await inPipe.WriteData(1u, toSend, endOfStream : isEndOfStream);

                // Wait for a short amount of time between DATA frames
                if (!isEndOfStream)
                {
                    await Task.Delay(5);
                }
                // Check if window updates were received if required
                if (expectedConnWindowUpdates[i] != 0)
                {
                    await outPipe.AssertWindowUpdate(0, expectedConnWindowUpdates[i]);
                }
                if (expectedStreamWindowUpdates[i] != 0)
                {
                    await outPipe.AssertWindowUpdate(1, expectedStreamWindowUpdates[i]);
                }
            }
        }
Exemplo n.º 3
0
        public async Task ViolationsOfTheConnectionFlowControlWindowShouldBeDetected(
            int?padLen, uint streamId, int dataAmount, bool isError)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            // Use a bigger flow control window for streams so that the connection
            // window errors and streams dont send window updates.
            // Also update maxFrameSize, otherwise the connection will send
            // window updates faster than we can violate the contract
            var settings = Settings.Default;

            settings.InitialWindowSize = 256 * 1024;
            settings.MaxFrameSize      = 1024 * 1024;

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

            // Open an additional stream, so that streamId 3 is not in the IDLE
            // range, which causes a connection error
            await inPipe.WriteHeaders(
                res.hEncoder, 555u, false, DefaultGetHeaders);

            // Try to send the data
            // This might fail, if the connection goes away before
            // everything is read
            try
            {
                await inPipe.WriteData(streamId, dataAmount, padLen : padLen);
            }
            catch (Exception e)
            {
                if (!isError || !(e is TimeoutException))
                {
                    throw;
                }
            }

            if (isError)
            {
                await outPipe.AssertGoAwayReception(ErrorCode.FlowControlError, 555u);

                await outPipe.AssertStreamEnd();

                await res.conn.Done;
                Assert.Equal(StreamState.Reset, res.stream.State);
            }
            else
            {
                // Expect the connection to be alive
                await outPipe.AssertWindowUpdate(0u, 65535);

                if (streamId != 1)
                {
                    // We expect a reset for the unknown stream on which data
                    // was transmitted
                    await outPipe.AssertResetStreamReception(streamId, ErrorCode.StreamClosed);
                }
                await inPipe.WritePing(new byte[8], false);

                await outPipe.ReadAndDiscardPong();

                Assert.Equal(StreamState.Open, res.stream.State);
            }
        }