Exemplo n.º 1
0
        public async Task ReceivingAnInformationalHeaderAfterANormalHeaderShouldBeAnError()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            await inPipe.WriteHeaders(res.hEncoder, 1u, false, DefaultStatusHeaders);

            // Expect to receive the status headers
            var recvdHeaders = await res.stream.ReadHeadersAsync();

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

            // 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);

            // 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());
        }
Exemplo n.º 2
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));
        }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
0
        [InlineData(65535, 100 * 1024, 2, 7)] // Continuations required
        public async Task OutgoingHeadersShouldBeFragmentedIntoContinuationsAccordingToFrameSize(
            int maxFrameSize, int totalHeaderBytes,
            int expectedMinNrOfFrames, int expectedMaxNrOfFrames)
        {
            var inPipe         = new BufferedPipe(1024);
            var outPipe        = new BufferedPipe(1024);
            var remoteSettings = Settings.Default;

            remoteSettings.MaxFrameSize = (uint)maxFrameSize;
            var res = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe,
                remoteSettings : remoteSettings,
                huffmanStrategy : HuffmanStrategy.Never);

            // Create the list of headers that should be sent
            // This must be big enough in order to send multiple frames
            var headers = new List <HeaderField>();

            // The :status header is necessary to avoid an exception on send
            headers.AddRange(
                DefaultStatusHeaders.TakeWhile(sh =>
                                               sh.Name.StartsWith(":")));

            const int headerLen = 3 + 10 + 8; // The calculated size of one header field
            // Calculate the amount of headers of the given size that are needed
            // to be sent based on the required totalHeaderBytes number.
            int requiredHeaderData = totalHeaderBytes - 1; // -1 for :status field
            int amountHeaders      = requiredHeaderData / headerLen;

            for (var i = 0; i < amountHeaders; i++)
            {
                var headerField = new HeaderField
                {
                    Name      = "hd" + i.ToString("D8"),
                    Value     = i.ToString("D8"),
                    Sensitive = true,
                };
                headers.Add(headerField);
            }

            // Send the headers in background task
            var writeHeaderTask = Task.Run(async() =>
            {
                await res.stream.WriteHeadersAsync(headers, false);
            });

            var hDecoder    = new Decoder();
            var hBuf        = new byte[maxFrameSize];
            var expectCont  = false;
            var rcvdFrames  = 0;
            var rcvdHeaders = new List <HeaderField>();

            while (true)
            {
                var fh = await outPipe.ReadFrameHeaderWithTimeout();

                Assert.Equal(expectCont ? FrameType.Continuation : FrameType.Headers, fh.Type);
                Assert.Equal(1u, fh.StreamId);
                Assert.InRange(fh.Length, 1, maxFrameSize);
                // Read header block fragment data
                await outPipe.ReadAllWithTimeout(
                    new ArraySegment <byte>(hBuf, 0, fh.Length));

                // Decode it
                var lastHeadersCount = rcvdHeaders.Count;
                var decodeResult     = hDecoder.DecodeHeaderBlockFragment(
                    new ArraySegment <byte>(hBuf, 0, fh.Length),
                    int.MaxValue,
                    rcvdHeaders);

                Assert.True(
                    rcvdHeaders.Count > lastHeadersCount,
                    "Expected to retrieve at least one header per frame");
                Assert.Equal(DecoderExtensions.DecodeStatus.Success, decodeResult.Status);

                expectCont = true;
                rcvdFrames++;

                if ((fh.Flags & (byte)ContinuationFrameFlags.EndOfHeaders) != 0)
                {
                    break;
                }
            }
            Assert.InRange(rcvdFrames, expectedMinNrOfFrames, expectedMaxNrOfFrames);
            Assert.Equal(headers.Count, rcvdHeaders.Count);
            Assert.True(rcvdHeaders.SequenceEqual(headers));
        }