Exemple #1
0
        public async ValueTask <long> TryReadStreamIdAsync()
        {
            while (true)
            {
                var result = await ReadApplicationInputAsync();

                var readableBuffer = result.Buffer;
                var consumed       = readableBuffer.Start;
                var examined       = readableBuffer.End;

                try
                {
                    if (!readableBuffer.IsEmpty)
                    {
                        var id = VariableLengthIntegerHelper.GetInteger(readableBuffer, out consumed, out examined);
                        if (id != -1)
                        {
                            return(id);
                        }
                    }

                    if (result.IsCompleted)
                    {
                        return(-1);
                    }
                }
                finally
                {
                    Pair.Application.Input.AdvanceTo(consumed, examined);
                }
            }
        }
Exemple #2
0
    private async ValueTask <long> TryReadStreamHeaderAsync()
    {
        // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-6.2
        while (_isClosed == 0)
        {
            var result = await Input.ReadAsync();

            var readableBuffer = result.Buffer;
            var consumed       = readableBuffer.Start;
            var examined       = readableBuffer.End;

            try
            {
                if (!readableBuffer.IsEmpty)
                {
                    var id = VariableLengthIntegerHelper.GetInteger(readableBuffer, out consumed, out examined);
                    if (id != -1)
                    {
                        return(id);
                    }
                }

                if (result.IsCompleted)
                {
                    return(-1);
                }
            }
            finally
            {
                Input.AdvanceTo(consumed, examined);
            }
        }

        return(-1);
    }
Exemple #3
0
        internal async ValueTask <Dictionary <long, long> > ExpectSettingsAsync()
        {
            var http3WithPayload = await ReceiveFrameAsync();

            Http3InMemory.AssertFrameType(http3WithPayload.Type, Http3FrameType.Settings);

            var payload = http3WithPayload.PayloadSequence;

            var settings = new Dictionary <long, long>();

            while (true)
            {
                var id = VariableLengthIntegerHelper.GetInteger(payload, out var consumed, out _);
                if (id == -1)
                {
                    break;
                }

                payload = payload.Slice(consumed);

                var value = VariableLengthIntegerHelper.GetInteger(payload, out consumed, out _);
                if (value == -1)
                {
                    break;
                }

                payload = payload.Slice(consumed);
                settings.Add(id, value);
            }

            return(settings);
        }
Exemple #4
0
        internal void VerifyGoAway(Http3FrameWithPayload frame, long expectedLastStreamId, Http3ErrorCode expectedErrorCode)
        {
            Assert.Equal(Http3FrameType.GoAway, frame.Type);
            var payload = frame.Payload;

            Assert.True(VariableLengthIntegerHelper.TryRead(payload.Span, out var streamId, out var _));
            Assert.Equal(expectedLastStreamId, streamId);
        }
Exemple #5
0
        internal async Task SendGoAwayAsync(long streamId, bool endStream = false)
        {
            var data = new byte[VariableLengthIntegerHelper.GetByteCount(streamId)];

            VariableLengthIntegerHelper.WriteInteger(data, streamId);

            await SendFrameAsync(Http3FrameType.GoAway, data, endStream);
        }
Exemple #6
0
        public void TryWrite_BufferNotEmpty_OneByteLimit(long longToEncode)
        {
            Span <byte> span      = new Span <byte>(new byte[1]);
            bool        isSuccess = VariableLengthIntegerHelper.TryWrite(span,
                                                                         longToEncode, out int bytesWritten);

            Assert.True(isSuccess);
            Assert.Equal(1, bytesWritten);
            Assert.Equal(longToEncode, span[0]);
        }
Exemple #7
0
        public void TryWrite_BufferEmpty()
        {
            Span <byte> span         = new Span <byte>();
            long        longToEncode = 1;
            bool        isSuccess    = VariableLengthIntegerHelper.TryWrite(span,
                                                                            longToEncode, out int bytesWritten);

            Assert.False(isSuccess);
            Assert.Equal(0, bytesWritten);
        }
Exemple #8
0
        public void TryRead_FromReadOnlySpan_BufferEmpty()
        {
            ReadOnlySpan <byte> readOnlySpan = new ReadOnlySpan <byte>();
            bool isSuccess = VariableLengthIntegerHelper.TryRead(readOnlySpan,
                                                                 out long value, out int bytesRead);

            Assert.False(isSuccess);
            Assert.Equal(0, value);
            Assert.Equal(0, bytesRead);
        }
Exemple #9
0
        public void TryWrite_BufferNotSizedCorrectly_EightByteLimit()
        {
            long        longToEncode = 1073741824;
            Span <byte> span         = new Span <byte>(new byte[1]);
            bool        isSuccess    = VariableLengthIntegerHelper.TryWrite(span,
                                                                            longToEncode, out int bytesWritten);

            Assert.False(isSuccess);
            Assert.Equal(0, bytesWritten);
        }
Exemple #10
0
        public void TryWrite_BufferNotEmpty_EightByteLimit(long longToEncode,
                                                           byte[] expected)
        {
            Span <byte> span      = new Span <byte>(new byte[8]);
            bool        isSuccess = VariableLengthIntegerHelper.TryWrite(span,
                                                                         longToEncode, out int bytesWritten);

            Assert.True(isSuccess);
            Assert.Equal(8, bytesWritten);
            Assert.Equal(expected, span.ToArray());
        }
    public void CheckEncoding(long input, byte[] expected)
    {
        var outputBuffer  = new Span <byte>(new byte[8]);
        var encodedLength = VariableLengthIntegerHelper.WriteInteger(outputBuffer, input);

        Assert.Equal(expected.Length, encodedLength);
        for (var i = 0; i < expected.Length; i++)
        {
            Assert.Equal(expected[i], outputBuffer[i]);
        }
    }
Exemple #12
0
        internal static void WriteSettings(List <Http3PeerSetting> settings, Span <byte> destination)
        {
            foreach (var setting in settings)
            {
                var parameterLength = VariableLengthIntegerHelper.WriteInteger(destination, (long)setting.Parameter);
                destination = destination.Slice(parameterLength);

                var valueLength = VariableLengthIntegerHelper.WriteInteger(destination, (long)setting.Value);
                destination = destination.Slice(valueLength);
            }
        }
Exemple #13
0
        internal static int CalculateSettingsSize(List <Http3PeerSetting> settings)
        {
            var length = 0;

            foreach (var setting in settings)
            {
                length += VariableLengthIntegerHelper.GetByteCount((long)setting.Parameter);
                length += VariableLengthIntegerHelper.GetByteCount(setting.Value);
            }
            return(length);
        }
Exemple #14
0
        public void TryRead_FromReadOnlySpan_BufferNotEmpty_InitialFourByteLengthMask_TryReadNotUInt32BigEndian()
        {
            ReadOnlySpan <byte> readOnlySpan = new ReadOnlySpan <byte>(new byte[]
            {
                128
            });
            bool isSuccess = VariableLengthIntegerHelper.TryRead(readOnlySpan,
                                                                 out long value, out int bytesRead);

            Assert.False(isSuccess);
            Assert.Equal(0, value);
            Assert.Equal(0, bytesRead);
        }
Exemple #15
0
        public void GetInteger_NotValidSegmentedSequence()
        {
            MemorySegment <byte>    memorySegment1   = new MemorySegment <byte>(new byte[] { 192 });
            MemorySegment <byte>    memorySegment2   = memorySegment1.Append(new byte[] { 0, 0, 0, 0, 0, 2 });
            ReadOnlySequence <byte> readOnlySequence = new ReadOnlySequence <byte>(
                memorySegment1, 0, memorySegment2, memorySegment2.Memory.Length);
            long result = VariableLengthIntegerHelper.GetInteger(readOnlySequence,
                                                                 out SequencePosition consumed, out SequencePosition examined);

            Assert.Equal(-1, result);
            Assert.Equal(0, consumed.GetInteger());
            Assert.Equal(6, examined.GetInteger());
        }
Exemple #16
0
        public void TryRead_FromReadOnlySpan_BufferNotEmpty_InitialOneByteLengthMask()
        {
            ReadOnlySpan <byte> readOnlySpan = new ReadOnlySpan <byte>(new byte[]
            {
                1
            });
            bool isSuccess = VariableLengthIntegerHelper.TryRead(readOnlySpan,
                                                                 out long value, out int bytesRead);

            Assert.True(isSuccess);
            Assert.Equal(1, value);
            Assert.Equal(1, bytesRead);
        }
Exemple #17
0
        internal void VerifyGoAway(Http3FrameWithPayload frame, long expectedLastStreamId)
        {
            Http3InMemory.AssertFrameType(frame.Type, Http3FrameType.GoAway);
            var payload = frame.Payload;

            if (!VariableLengthIntegerHelper.TryRead(payload.Span, out var streamId, out var _))
            {
                throw new InvalidOperationException("Failed to read GO_AWAY stream ID.");
            }
            if (streamId != expectedLastStreamId)
            {
                throw new InvalidOperationException($"Expected stream ID {expectedLastStreamId}, got {streamId}.");
            }
        }
Exemple #18
0
        public void TryRead_FromReadOnlySpan_BufferNotEmpty_InitialEightByteLengthMask_TryReadUInt64BigEndian()
        {
            ReadOnlySpan <byte> readOnlySpan = new ReadOnlySpan <byte>(
                new byte[]
            {
                192, 0, 0, 0,
                0, 0, 0, 4
            });
            bool isSuccess = VariableLengthIntegerHelper.TryRead(readOnlySpan,
                                                                 out long value, out int bytesRead);

            Assert.True(isSuccess);
            Assert.Equal(4, value);
            Assert.Equal(8, bytesRead);
        }
Exemple #19
0
        public async Task WriteStreamIdAsync(int id)
        {
            var writableBuffer = Pair.Application.Output;

            void WriteSpan(PipeWriter pw)
            {
                var buffer        = pw.GetSpan(sizeHint: 8);
                var lengthWritten = VariableLengthIntegerHelper.WriteInteger(buffer, id);

                pw.Advance(lengthWritten);
            }

            WriteSpan(writableBuffer);

            await FlushAsync(writableBuffer);
        }
Exemple #20
0
    /* https://quicwg.org/base-drafts/draft-ietf-quic-http.html#frame-layout
     *   0                   1                   2                   3
     *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                           Type (i)                          ...
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                          Length (i)                         ...
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                       Frame Payload (*)                     ...
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */
    internal static bool TryReadFrame(ref ReadOnlySequence <byte> readableBuffer, Http3RawFrame frame, out ReadOnlySequence <byte> framePayload)
    {
        framePayload = ReadOnlySequence <byte> .Empty;
        SequencePosition consumed;
        SequencePosition examined;

        var type = VariableLengthIntegerHelper.GetInteger(readableBuffer, out consumed, out examined);

        if (type == -1)
        {
            return(false);
        }

        var firstLengthBuffer = readableBuffer.Slice(consumed);

        var length = VariableLengthIntegerHelper.GetInteger(firstLengthBuffer, out consumed, out examined);

        // Make sure the whole frame is buffered
        if (length == -1)
        {
            return(false);
        }

        var startOfFramePayload = readableBuffer.Slice(consumed);

        if (startOfFramePayload.Length < length)
        {
            return(false);
        }

        frame.Length = length;
        frame.Type   = (Http3FrameType)type;

        // The remaining payload minus the extra fields
        framePayload   = startOfFramePayload.Slice(0, length);
        readableBuffer = readableBuffer.Slice(framePayload.End);

        return(true);
    }
Exemple #21
0
        public void GetByteCountTest(long longToEncode, int expectedLimit)
        {
            int result = VariableLengthIntegerHelper.GetByteCount(longToEncode);

            Assert.Equal(expectedLimit, result);
        }
    public void CheckDecoding(long expected, byte[] input)
    {
        var decoded = VariableLengthIntegerHelper.GetInteger(new ReadOnlySequence <byte>(input), out _, out _);

        Assert.Equal(expected, decoded);
    }
Exemple #23
0
    public async ValueTask <long> ReadNextStreamHeaderAsync(Http3StreamContext context, long streamId, Http3StreamType?advanceOn)
    {
        var Input   = context.Transport.Input;
        var advance = false;
        SequencePosition consumed = default;
        SequencePosition start    = default;

        try
        {
            while (!_isClosed)
            {
                var result = await Input.ReadAsync();

                if (result.IsCanceled)
                {
                    throw new Exception();
                }

                var readableBuffer = result.Buffer;
                consumed = readableBuffer.Start;
                start    = readableBuffer.Start;

                if (!readableBuffer.IsEmpty)
                {
                    var value = VariableLengthIntegerHelper.GetInteger(readableBuffer, out consumed, out _);
                    if (value != -1)
                    {
                        if (!advanceOn.HasValue || value == (long)advanceOn)
                        {
                            advance = true;
                        }
                        return(value);
                    }
                }

                if (result.IsCompleted)
                {
                    return(-1L);
                }
            }
        }
        catch (Exception)
        {
            throw new Http3PendingStreamException(CoreStrings.AttemptedToReadHeaderOnAbortedStream, streamId, _abortedException);
        }
        finally
        {
            if (!_isClosed)
            {
                if (advance)
                {
                    Input.AdvanceTo(consumed);
                }
                else
                {
                    Input.AdvanceTo(start);
                }
            }

            StreamTimeoutTicks = default;
        }

        return(-1L);
    }