Пример #1
0
        public async Task TrailersShouldBeCorrectlySent(bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            await r.stream.WriteAsync(new ArraySegment <byte>(new byte[0]));

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

            // Send trailers
            await r.stream.WriteTrailersAsync(DefaultTrailingHeaders);

            // Check the received trailers
            var fh = await outPipe.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Headers, fh.Type);
            Assert.Equal(1u, fh.StreamId);
            var expectedFlags =
                HeadersFrameFlags.EndOfHeaders | HeadersFrameFlags.EndOfStream;

            Assert.Equal((byte)expectedFlags, fh.Flags);
            Assert.InRange(fh.Length, 1, 1024);
            var headerData = new byte[fh.Length];
            await outPipe.ReadAllWithTimeout(new ArraySegment <byte>(headerData));

            Assert.Equal(EncodedDefaultTrailingHeaders, headerData);
        }
Пример #2
0
        public async Task OutgoingDataShouldRespectMaxFrameSize(
            bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            var dataSize  = Settings.Default.MaxFrameSize + 10;
            var writeTask = Task.Run(async() =>
            {
                var data = new byte[dataSize];
                await r.stream.WriteAsync(new ArraySegment <byte>(data), true);
            });

            // Expect to receive the data in fragments
            await outPipe.ReadAndDiscardData(1u, false, (int)Settings.Default.MaxFrameSize);

            await outPipe.ReadAndDiscardData(1u, true, 10);

            var doneTask = await Task.WhenAny(writeTask, Task.Delay(250));

            Assert.True(writeTask == doneTask, "Expected write task to finish");
        }
Пример #3
0
        public async Task ReceivingHeadersOrDataOnAClosedStreamShouldTriggerAStreamReset(
            StreamState streamState,
            bool sendHeaders, bool sendData, bool sendTrailers)
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var localCloseDone = new SemaphoreSlim(0);

            var res = await StreamCreator.CreateConnectionAndStream(
                streamState, loggerProvider, inPipe, outPipe);

            if (sendHeaders)
            {
                await inPipe.WriteHeaders(res.hEncoder, 1, false, DefaultGetHeaders);
            }
            if (sendData)
            {
                await inPipe.WriteData(1u, 0);
            }
            if (sendTrailers)
            {
                await inPipe.WriteHeaders(res.hEncoder, 1, true, DefaultGetHeaders);
            }

            await outPipe.AssertResetStreamReception(1u, ErrorCode.StreamClosed);
            var expectedState =
                streamState == StreamState.Closed
                ? StreamState.Closed
                : StreamState.Reset;
            Assert.Equal(expectedState, res.stream.State);
        }
Пример #4
0
        public async Task ReceivingDataDirectlyAfterInformationalHeadersShouldBeAnError()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Send informational headers to the client
            var infoHeaders = new HeaderField[]
            {
                new HeaderField {
                    Name = ":status", Value = "100"
                },
                new HeaderField {
                    Name = "extension-field", Value = "bar"
                },
            };
            await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders);

            var recvdHeaders = await res.stream.ReadHeadersAsync();

            Assert.True(infoHeaders.SequenceEqual(recvdHeaders));

            // Try to send data
            await inPipe.WriteData(1u, 100, null, true);

            // Expect to receive an error
            await outPipe.AssertResetStreamReception(1u, ErrorCode.ProtocolError);

            Assert.Equal(StreamState.Reset, res.stream.State);

            await Assert.ThrowsAsync <StreamResetException>(
                () => res.stream.ReadHeadersAsync());
        }
Пример #5
0
        public async Task ClientsShouldBeAbleToReceiveInformationalHeaders()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Send and receive first set of informational headers
            var readInfoHeaders1Task = res.stream.ReadHeadersAsync();

            Assert.False(readInfoHeaders1Task.IsCompleted);

            var infoHeaders1 = new HeaderField[]
            {
                new HeaderField {
                    Name = ":status", Value = "100"
                },
                new HeaderField {
                    Name = "extension-field", Value = "bar"
                },
            };
            await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders1);

            var recvdInfoHeaders1 = await readInfoHeaders1Task;

            Assert.True(infoHeaders1.SequenceEqual(recvdInfoHeaders1));

            // Send and receive second set of informational headers
            var readInfoHeaders2Task = res.stream.ReadHeadersAsync();

            Assert.False(readInfoHeaders2Task.IsCompleted);

            var infoHeaders2 = new HeaderField[]
            {
                new HeaderField {
                    Name = ":status", Value = "108"
                },
                new HeaderField {
                    Name = "extension-field-b", Value = "bar2"
                },
            };
            await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders2);

            var recvdInfoHeaders2 = await readInfoHeaders2Task;

            Assert.True(infoHeaders2.SequenceEqual(recvdInfoHeaders2));

            // Send and receive final headers
            var recvHeadersTask = res.stream.ReadHeadersAsync();

            Assert.False(recvHeadersTask.IsCompleted);
            await inPipe.WriteHeaders(res.hEncoder, 1u, true, DefaultStatusHeaders);

            var recvdHeaders = await recvHeadersTask;

            Assert.True(DefaultStatusHeaders.SequenceEqual(recvdHeaders));
        }
Пример #6
0
 public async Task StreamCreatorShouldCreateStreamInCorrectState(
     StreamState state)
 {
     var inPipe = new BufferedPipe(1024);
     var outPipe = new BufferedPipe(1024);
     var res = await StreamCreator.CreateConnectionAndStream(
         state, loggerProvider, inPipe, outPipe);
     Assert.NotNull(res.stream);
     Assert.Equal(state, res.stream.State);
 }
Пример #7
0
        public async Task RespondingTrailersWithoutHeadersShouldThrowAnException()
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

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

            var ex = await Assert.ThrowsAsync<Exception>(async () =>
                await r.stream.WriteTrailersAsync(DefaultTrailingHeaders));

            Assert.Equal("Attempted to write trailers without data", ex.Message);
        }
Пример #8
0
        public async Task CancellingAStreamShouldSendAResetFrame(
            bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            r.stream.Cancel();
            await outPipe.AssertResetStreamReception(1, ErrorCode.Cancel);

            Assert.Equal(StreamState.Reset, r.stream.State);
        }
Пример #9
0
        public async Task RespondingDataWithoutHeadersShouldThrowAnException(
            bool useEndOfStream)
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

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

            var ex = await Assert.ThrowsAsync<Exception>(async () =>
                await r.stream.WriteAsync(
                    new ArraySegment<byte>(new byte[8]), useEndOfStream));

            Assert.Equal("Attempted to write data before headers", ex.Message);
        }
Пример #10
0
        public async Task ReceivingHeaders2TimesShouldTriggerAStreamReset(
            bool isServer, bool headersAreEndOfStream)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            // Establish open streams, which means headers are sent in both
            // directions
            var res = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            // Write a second header
            await inPipe.WriteHeaders(
                res.hEncoder, 1, headersAreEndOfStream, DefaultGetHeaders);

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

            Assert.Equal(StreamState.Reset, res.stream.State);
        }
Пример #11
0
        public async Task ReceivingHeadersAndNoDataShouldBlockTheReader()
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

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

            var buf = new byte[1024];
            try
            {
                await res.stream.ReadWithTimeout(new ArraySegment<byte>(buf));
            }
            catch (TimeoutException)
            {
                return;
            }
            Assert.True(false, "Expected read timeout, but got data");
        }
Пример #12
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);
        }
Пример #13
0
        public async Task ReceivingDataBeforeHeadersShouldYieldAResetException()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

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

            await inPipe.WriteData(1u, 1);

            await outPipe.AssertResetStreamReception(1u, ErrorCode.ProtocolError);

            var ex = await Assert.ThrowsAsync <AggregateException>(
                () => res.stream.ReadWithTimeout(new ArraySegment <byte>(
                                                     new byte[1])));

            Assert.IsType <StreamResetException>(ex.InnerException);
            Assert.Equal(StreamState.Reset, res.stream.State);
        }
Пример #14
0
        public async Task EmptyDataFramesShouldBeValidSeperatorsBeforeTrailers(
            bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            // Send a 0byte data frame
            await inPipe.WriteData(1u, 0);

            // Send trailers
            await inPipe.WriteHeaders(res.hEncoder, 1u, true,
                                      DefaultTrailingHeaders);

            // Check for no stream error
            await inPipe.WritePing(new byte[8], false);

            await outPipe.ReadAndDiscardPong();
        }
Пример #15
0
        public async Task EmptyDataFramesShouldNotWakeupPendingReads(
            bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            // Send a 0byte data frame
            await inPipe.WriteData(1u, 0);

            // Try to read - this should not unblock
            var readTask = res.stream.ReadAsync(
                new ArraySegment <byte>(new byte[1])).AsTask();

            var doneTask = await Task.WhenAny(readTask, Task.Delay(100));

            Assert.True(
                doneTask != readTask,
                "Expected read timeout but read finished");
        }
Пример #16
0
        public async Task ReceivingTrailersShouldUnblockDataReceptionAndPresentThem(
            bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            var readDataTask = res.stream.ReadAllToArrayWithTimeout();

            var fh = new FrameHeader
            {
                Type     = FrameType.Data,
                Length   = 4,
                StreamId = 1,
                Flags    = (byte)0,
            };
            await inPipe.WriteFrameHeader(fh);

            await inPipe.WriteAsync(
                new ArraySegment <byte>(
                    System.Text.Encoding.ASCII.GetBytes("ABCD")));

            var trailers = new HeaderField[] {
                new HeaderField {
                    Name = "trai", Value = "ler"
                },
            };
            await inPipe.WriteHeaders(res.hEncoder, 1, true, trailers);

            var bytes = await readDataTask;

            Assert.Equal(4, bytes.Length);
            Assert.Equal("ABCD", System.Text.Encoding.ASCII.GetString(bytes));
            Assert.Equal(StreamState.HalfClosedRemote, res.stream.State);
            var rcvdTrailers = await res.stream.ReadTrailersAsync();

            Assert.Equal(trailers, rcvdTrailers);
        }
Пример #17
0
        public async Task ResponseHeadersShouldBeCorrectlySent(
            bool useEndOfStream)
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);
            await r.stream.WriteHeadersAsync(DefaultStatusHeaders, useEndOfStream);

            // Check the received headers
            var fh = await outPipe.ReadFrameHeaderWithTimeout();
            Assert.Equal(FrameType.Headers, fh.Type);
            Assert.Equal(1u, fh.StreamId);
            var expectedFlags = HeadersFrameFlags.EndOfHeaders;
            if (useEndOfStream) expectedFlags |= HeadersFrameFlags.EndOfStream;
            Assert.Equal((byte)expectedFlags, fh.Flags);
            Assert.InRange(fh.Length, 1, 1024);
            var headerData = new byte[fh.Length];
            await outPipe.ReadAllWithTimeout(new ArraySegment<byte>(headerData));
            Assert.Equal(EncodedDefaultStatusHeaders, headerData);
        }
Пример #18
0
        public async Task ReceivingHeadersOrDataOnAResetStreamShouldProduceAClosedStreamError(
            bool sendHeaders, bool sendData, bool sendTrailers)
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                StreamState.Reset, loggerProvider, inPipe, outPipe);

            if (sendHeaders)
            {
                await inPipe.WriteHeaders(r.hEncoder, 1, false, DefaultGetHeaders);
            }
            if (sendData)
            {
                await inPipe.WriteData(1u, 0);
            }
            if (sendTrailers)
            {
                await inPipe.WriteHeaders(r.hEncoder, 1, true, DefaultGetHeaders);
            }
            await outPipe.AssertResetStreamReception(1, ErrorCode.StreamClosed);
        }
Пример #19
0
        public async Task DataFromDataFramesShouldBeReceived(
            bool isServer, int[] dataLength)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            var readTask = res.stream.ReadAllToArrayWithTimeout();

            var totalToSend = dataLength.Aggregate(0, (sum, n) => sum + n);

            byte nr = 0;

            for (var i = 0; i < dataLength.Length; i++)
            {
                var toSend        = dataLength[i];
                var isEndOfStream = i == (dataLength.Length - 1);
                var flags         = isEndOfStream ? DataFrameFlags.EndOfStream : 0;
                var fh            = new FrameHeader
                {
                    Type     = FrameType.Data,
                    StreamId = 1,
                    Flags    = (byte)flags,
                    Length   = toSend,
                };
                await inPipe.WriteFrameHeaderWithTimeout(fh);

                var fdata = new byte[toSend];
                for (var j = 0; j < toSend; j++)
                {
                    fdata[j] = nr;
                    nr++;
                    if (nr > 122)
                    {
                        nr = 0;
                    }
                }
                await inPipe.WriteWithTimeout(new ArraySegment <byte>(fdata));

                // Wait for a short amount of time between DATA frames
                if (!isEndOfStream)
                {
                    await Task.Delay(10);
                }
            }

            var doneTask = await Task.WhenAny(
                readTask, Task.Delay(ReadableStreamTestExtensions.ReadTimeout));

            Assert.True(doneTask == readTask, "Expected read task to complete within timeout");

            byte[] receivedData = await readTask;
            Assert.NotNull(receivedData);
            Assert.Equal(totalToSend, receivedData.Length);
            var expected = 0;

            for (var j = 0; j < totalToSend; j++)
            {
                Assert.Equal(expected, receivedData[j]);
                expected++;
                if (expected > 122)
                {
                    expected = 0;
                }
            }
        }
Пример #20
0
        public async Task DataShouldBeCorrectlySent(
            bool isServer, int[] dataLength)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            var totalToSend = dataLength.Aggregate(0, (sum, n) => sum + n);

            var writeTask = Task.Run(async() =>
            {
                byte nr = 0;
                for (var i = 0; i < dataLength.Length; i++)
                {
                    var toSend        = dataLength[i];
                    var isEndOfStream = i == (dataLength.Length - 1);
                    var buffer        = new byte[toSend];
                    for (var j = 0; j < toSend; j++)
                    {
                        buffer[j] = nr;
                        nr++;
                        if (nr > 122)
                        {
                            nr = 0;
                        }
                    }
                    await r.stream.WriteAsync(
                        new ArraySegment <byte>(buffer), isEndOfStream);
                }
            });

            var data   = new byte[totalToSend];
            var offset = 0;

            for (var i = 0; i < dataLength.Length; i++)
            {
                var fh = await outPipe.ReadFrameHeaderWithTimeout();

                Assert.Equal(FrameType.Data, fh.Type);
                Assert.Equal(1u, fh.StreamId);
                var expectEOS = i == dataLength.Length - 1;
                var gotEOS    = (fh.Flags & (byte)DataFrameFlags.EndOfStream) != 0;
                Assert.Equal(expectEOS, gotEOS);
                Assert.Equal(dataLength[i], fh.Length);

                var part = new byte[fh.Length];
                await outPipe.ReadAllWithTimeout(new ArraySegment <byte>(part));

                Array.Copy(part, 0, data, offset, fh.Length);
                offset += fh.Length;
            }

            var doneTask = await Task.WhenAny(writeTask, Task.Delay(250));

            Assert.True(writeTask == doneTask, "Expected write task to finish");

            // Check if the correct data was received
            var expected = 0;

            for (var j = 0; j < totalToSend; j++)
            {
                Assert.Equal(expected, data[j]);
                expected++;
                if (expected > 122)
                {
                    expected = 0;
                }
            }
        }
Пример #21
0
        public async Task DataFramesWithPaddingShouldBeCorrectlyReceived(
            bool isServer, int nrFrames, byte numPadding, int bytesToSend)
        {
            var inPipe    = new BufferedPipe(10 * 1024);
            var outPipe   = new BufferedPipe(10 * 1024);
            var receiveOk = true;

            var settings = Settings.Default;

            settings.MaxFrameSize      = 100 * 1024;
            settings.InitialWindowSize = int.MaxValue;
            var r = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe,
                localSettings : settings);

            for (var nrSends = 0; nrSends < nrFrames; nrSends++)
            {
                var buf = new byte[1 + bytesToSend + numPadding];
                buf[0] = numPadding;
                byte nr = 0;
                for (var i = 0; i < bytesToSend; i++)
                {
                    buf[1 + i] = nr;
                    nr++;
                    if (nr > 123)
                    {
                        nr = 0;
                    }
                }
                var fh = new FrameHeader
                {
                    Type     = FrameType.Data,
                    StreamId = 1,
                    Flags    = (byte)DataFrameFlags.Padded,
                    Length   = buf.Length,
                };
                await inPipe.WriteFrameHeaderWithTimeout(fh);

                await inPipe.WriteWithTimeout(new ArraySegment <byte>(buf));
            }

            for (var nrSends = 0; nrSends < nrFrames; nrSends++)
            {
                var buf1 = new byte[bytesToSend];
                await r.stream.ReadAllWithTimeout(new ArraySegment <byte>(buf1));

                var expected = 0;
                for (var j = 0; j < bytesToSend; j++)
                {
                    if (buf1[j] != expected)
                    {
                        receiveOk = false;
                    }
                    expected++;
                    if (expected > 123)
                    {
                        expected = 0;
                    }
                }
            }

            Assert.True(receiveOk, "Expected to receive correct data");
        }