Exemplo n.º 1
0
        public async Task IncompleteHeaderBlocksShouldBeDetected(
            int nrContinuations)
        {
            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();
            // Construct a proper set of header here, where a single headerfield could
            // by splitted over more than 1 fragment
            var totalHeaders = DefaultGetHeaders.TakeWhile(
                h => h.Name.StartsWith(":"));

            totalHeaders = totalHeaders.Append(
                new HeaderField {
                Name = "longname", Value = "longvalue"
            });
            totalHeaders = totalHeaders.Append(
                new HeaderField {
                Name = "abc", Value = "xyz"
            });

            // Encode all headers in a single header block
            var hBuf      = new byte[32 * 1024];
            var encodeRes =
                hEncoder.EncodeInto(new ArraySegment <byte>(hBuf), totalHeaders);

            Assert.Equal(totalHeaders.Count(), encodeRes.FieldCount);
            Assert.True(
                encodeRes.UsedBytes >= 5,
                "Test must encode headers with at least 5 bytes to work properly");

            // Write header data in multiple parts
            // The last part will miss one byte
            var offset = 0;
            var length = encodeRes.UsedBytes;

            var isLast     = nrContinuations == 0;
            var dataLength = isLast ? (length - 1) : 3;
            var fh         = new FrameHeader
            {
                Type     = FrameType.Headers,
                Length   = dataLength,
                StreamId = 1u,
                Flags    = (byte)(isLast ? HeadersFrameFlags.EndOfHeaders : 0),
            };
            await inPipe.WriteFrameHeader(fh);

            await inPipe.WriteAsync(new ArraySegment <byte>(hBuf, offset, dataLength));

            offset += dataLength;
            length -= dataLength;

            for (var i = 0; i < nrContinuations; i++)
            {
                isLast     = i == nrContinuations - 1;
                dataLength = isLast ? (length - 1) : 1;
                fh         = new FrameHeader
                {
                    Type     = FrameType.Continuation,
                    Length   = dataLength,
                    StreamId = 1u,
                    Flags    = (byte)(isLast ? ContinuationFrameFlags.EndOfHeaders : 0),
                };
                await inPipe.WriteFrameHeader(fh);

                await inPipe.WriteAsync(new ArraySegment <byte>(hBuf, offset, dataLength));

                offset += dataLength;
                length -= dataLength;
            }

            Assert.True(1 == length, "Expected to send all but 1 byte");

            // Expect a GoAway as reaction to incomplete headers
            await outPipe.AssertGoAwayReception(ErrorCode.CompressionError, 0u);

            await outPipe.AssertStreamEnd();
        }
Exemplo n.º 2
0
        public async Task ContinuationsWherePartsDontContainFullHeaderMustBeSupported(
            int nrContinuations)
        {
            var     inPipe  = new BufferedPipe(1024);
            var     outPipe = new BufferedPipe(1024);
            IStream stream  = null;
            IEnumerable <HeaderField> receivedHeaders = null;
            SemaphoreSlim             handlerDone     = new SemaphoreSlim(0);

            Func <IStream, bool> listener = (s) =>
            {
                stream = s;
                Task.Run(async() =>
                {
                    receivedHeaders = await s.ReadHeadersAsync();
                    handlerDone.Release();
                });
                return(true);
            };
            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, listener);

            var hEncoder = new Encoder();
            // Construct a proper set of header here, where a single headerfield could
            // by splitted over more than 1 fragment
            var totalHeaders = DefaultGetHeaders.TakeWhile(
                h => h.Name.StartsWith(":"));

            totalHeaders = totalHeaders.Append(
                new HeaderField {
                Name = "longname", Value = "longvalue"
            });
            totalHeaders = totalHeaders.Append(
                new HeaderField {
                Name = "abc", Value = "xyz"
            });

            // Encode all headers in a single header block
            var hBuf      = new byte[32 * 1024];
            var encodeRes =
                hEncoder.EncodeInto(new ArraySegment <byte>(hBuf), totalHeaders);

            Assert.Equal(totalHeaders.Count(), encodeRes.FieldCount);
            Assert.True(
                encodeRes.UsedBytes >= 5,
                "Test must encode headers with at least 5 bytes to work properly");

            // Write the first 3 bytes in a header frame
            // These cover all pseudoheaders, which wouldn't be affected by
            // possible bugs anyway
            var fh = new FrameHeader
            {
                Type     = FrameType.Headers,
                Length   = 3,
                StreamId = 1u,
                Flags    = (byte)0,
            };
            await inPipe.WriteFrameHeader(fh);

            await inPipe.WriteAsync(new ArraySegment <byte>(hBuf, 0, 3));

            var offset = 3;
            var length = encodeRes.UsedBytes - 3;

            for (var i = 0; i < nrContinuations; i++)
            {
                var isLast     = i == nrContinuations - 1;
                var dataLength = isLast ? length : 1;
                fh = new FrameHeader
                {
                    Type     = FrameType.Continuation,
                    Length   = dataLength,
                    StreamId = 1u,
                    Flags    = (byte)(isLast ? ContinuationFrameFlags.EndOfHeaders : 0),
                };
                await inPipe.WriteFrameHeader(fh);

                await inPipe.WriteAsync(new ArraySegment <byte>(hBuf, offset, dataLength));

                offset += dataLength;
                length -= dataLength;
            }

            var handlerCompleted = await handlerDone.WaitAsync(
                ReadableStreamTestExtensions.ReadTimeout);

            Assert.True(handlerCompleted, "Expected stream handler to complete");
            Assert.True(
                totalHeaders.SequenceEqual(receivedHeaders),
                "Expected to receive all sent headers");
        }