Exemplo n.º 1
0
    public async static Task DrainAsync(this IReadableByteStream stream)
    {
        var buf       = Buffers.Pool.Rent(8 * 1024);
        var bytesRead = 0;

        try
        {
            while (true)
            {
                var res = await stream.ReadAsync(new ArraySegment <byte>(buf));

                if (res.BytesRead != 0)
                {
                    bytesRead += res.BytesRead;
                }

                if (res.EndOfStream)
                {
                    return;
                }
            }
        }
        finally
        {
            Buffers.Pool.Return(buf);
        }
    }
Exemplo n.º 2
0
        async Task ValidateSettingReception(
            IReadableByteStream stream, Settings expectedSettings)
        {
            var header = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Settings, header.Type);
            Assert.Equal(0, header.Flags);
            Assert.Equal(0u, header.StreamId);
            Assert.Equal(expectedSettings.RequiredSize, header.Length);

            var setBuf = new byte[expectedSettings.RequiredSize];
            await stream.ReadAllWithTimeout(new ArraySegment <byte>(setBuf));

            var settings = new Settings
            {
                EnablePush           = false,
                HeaderTableSize      = 55,
                InitialWindowSize    = 55,
                MaxConcurrentStreams = 55,
                MaxFrameSize         = 55,
                MaxHeaderListSize    = 55,
            };
            var err = settings.UpdateFromData(new ArraySegment <byte>(setBuf));

            Assert.Null(err);
            Assert.Equal(expectedSettings, settings);
        }
Exemplo n.º 3
0
    public async static Task CopyToAsync(
        this IReadableByteStream stream,
        IWriteableByteStream dest)
    {
        var buf       = Buffers.Pool.Rent(64 * 1024);
        var bytesRead = 0;

        try
        {
            while (true)
            {
                var res = await stream.ReadAsync(new ArraySegment <byte>(buf));

                if (res.BytesRead != 0)
                {
                    await dest.WriteAsync(new ArraySegment <byte>(buf, 0, res.BytesRead));

                    bytesRead += res.BytesRead;
                }

                if (res.EndOfStream)
                {
                    return;
                }
            }
        }
        finally
        {
            Buffers.Pool.Return(buf);
        }
    }
Exemplo n.º 4
0
        /// <summary>
        /// Reads the preface from the given stream and compares it to
        /// the expected value.
        /// Will throw an error if the preface could not be read or if the stream
        /// has finished unexpectedly.
        /// </summary>
        public static async ValueTask <DoneHandle> ReadAsync(
            IReadableByteStream stream, int timeoutMillis)
        {
            if (timeoutMillis < 0)
            {
                throw new ArgumentException(nameof(timeoutMillis));
            }
            else if (timeoutMillis == 0)
            {
                // No timeout
                return(await ReadAsync(stream));
            }

            var cts       = new CancellationTokenSource();
            var readTask  = ReadAsync(stream).AsTask();
            var timerTask = Task.Delay(timeoutMillis, cts.Token);

            var finishedTask = await Task.WhenAny(readTask, timerTask);

            var hasTimeout = ReferenceEquals(timerTask, finishedTask);

            // Cancel the timer which might be still running
            cts.Cancel();
            cts.Dispose();

            if (hasTimeout)
            {
                throw new TimeoutException();
            }
            // No timeout occured
            return(readTask.Result);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Reads a frame header from the given stream
        /// </summary>
        public static async ValueTask <FrameHeader> ReceiveAsync(
            IReadableByteStream stream, byte[] headerSpace)
        {
            await stream.ReadAll(new ArraySegment <byte>(headerSpace, 0, HeaderSize));

            return(DecodeFrom(new ArraySegment <byte>(headerSpace, 0, HeaderSize)));
        }
        private Connection BuildConnection(
            bool isServer,
            IReadableByteStream inputStream,
            IWriteAndCloseableByteStream outputStream)
        {
            ILogger logger = null;

            if (loggerProvider != null)
            {
                logger = loggerProvider.CreateLogger("http2Con");
            }

            // Decrease the timeout for the preface,
            // as this speeds the test up
            var config =
                new ConnectionConfigurationBuilder(isServer)
                .UseStreamListener((s) => false)
                .UseClientPrefaceTimeout(200)
                .Build();

            return(new Connection(
                       config, inputStream, outputStream,
                       new Connection.Options
            {
                Logger = logger,
            }));
        }
Exemplo n.º 7
0
        /// <summary>
        /// Tries to read exactly the given amount of data from a stream.
        /// The method will only return if all data was read, the stream
        /// closed or the an error happened.
        /// If the input is a 0 byte buffer the method will always succeed,
        /// even if the underlying stream was already closed.
        /// </summary>
        /// <param name="stream">The stream to read data from</param>
        /// <param name="buffer">The destination buffer</param>
        /// <returns>Awaitable task object</returns>
        public async static ValueTask <DoneHandle> ReadAll(
            this IReadableByteStream stream, ArraySegment <byte> buffer)
        {
            var array  = buffer.Array;
            var offset = buffer.Offset;
            var count  = buffer.Count;

            // Remark: This will not perform actual 0 byte reads to the underlying
            // stream, which means it won't detect closed streams on 0 byte reads.

            while (count != 0)
            {
                var segment = new ArraySegment <byte>(array, offset, count);
                var res     = await stream.ReadAsync(segment);

                if (res.EndOfStream)
                {
                    throw new System.IO.EndOfStreamException();
                }
                offset += res.BytesRead;
                count  -= res.BytesRead;
            }

            return(DoneHandle.Instance);
        }
        public static async Task AssertSettingsAck(
            this IReadableByteStream stream)
        {
            var header = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Settings, header.Type);
            Assert.Equal(0, header.Length);
            Assert.Equal((byte)SettingsFrameFlags.Ack, header.Flags);
            Assert.Equal(0u, header.StreamId);
        }
        public static async Task ReadAndDiscardSettings(
            this IReadableByteStream stream)
        {
            var header = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Settings, header.Type);
            Assert.InRange(header.Length, 0, 256);
            await stream.ReadAllWithTimeout(
                new ArraySegment <byte>(new byte[header.Length]));
        }
Exemplo n.º 10
0
 public HeaderReader(
     HPack.Decoder hpackDecoder,
     uint maxFrameSize, uint maxHeaderFieldsSize,
     IReadableByteStream reader
     )
 {
     this.reader              = reader;
     this.hpackDecoder        = hpackDecoder;
     this.maxFrameSize        = maxFrameSize;
     this.maxHeaderFieldsSize = maxHeaderFieldsSize;
 }
        public static async Task ReadAndDiscardPong(
            this IReadableByteStream stream)
        {
            var header = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Ping, header.Type);
            Assert.Equal(8, header.Length);
            Assert.Equal((byte)PingFrameFlags.Ack, header.Flags);
            Assert.Equal(0u, header.StreamId);
            await stream.ReadAllWithTimeout(
                new ArraySegment <byte>(new byte[8]));
        }
Exemplo n.º 12
0
 public HeaderReader(
     Decoder hpackDecoder,
     uint maxFrameSize, uint maxHeaderFieldsSize,
     IReadableByteStream reader,
     ILogger logger
     )
 {
     this.reader              = reader;
     this.hpackDecoder        = hpackDecoder;
     this.maxFrameSize        = maxFrameSize;
     this.maxHeaderFieldsSize = maxHeaderFieldsSize;
     this.logger              = logger;
 }
        public static async Task <StreamReadResult> ReadWithTimeout(
            this IReadableByteStream stream, ArraySegment <byte> buf)
        {
            var readTask    = stream.ReadAsync(buf).AsTask();
            var timeoutTask = Task.Delay(ReadTimeout);
            var combined    = Task.WhenAny(new Task[] { readTask, timeoutTask });
            var done        = await combined;

            if (done == readTask)
            {
                return(readTask.Result);
            }
            throw new TimeoutException();
        }
        public static async Task <byte[]> ReadAllToArrayWithTimeout(
            this IReadableByteStream stream)
        {
            var readTask    = stream.ReadAllToArray();
            var timeoutTask = Task.Delay(ReadTimeout);
            var combined    = Task.WhenAny(new Task[] { readTask, timeoutTask });
            var done        = await combined;

            if (done == readTask)
            {
                return(readTask.Result);
            }
            throw new TimeoutException();
        }
        public static async Task ReadAndDiscardHeaders(
            this IReadableByteStream stream,
            uint expectedStreamId,
            bool expectEndOfStream)
        {
            var header = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Headers, header.Type);
            Assert.Equal(expectedStreamId, header.StreamId);
            var isEndOfStream = (header.Flags & (byte)HeadersFrameFlags.EndOfStream) != 0;

            Assert.Equal(expectEndOfStream, isEndOfStream);
            var hbuf = new ArraySegment <byte>(new byte[header.Length]);
            await stream.ReadAllWithTimeout(hbuf);
        }
        public static async Task <FrameHeader> ReadFrameHeaderWithTimeout(
            this IReadableByteStream stream)
        {
            var headerSpace = new byte[FrameHeader.HeaderSize];
            var readTask    = FrameHeader.ReceiveAsync(stream, headerSpace).AsTask();
            var timeoutTask = Task.Delay(5000);
            var combined    = Task.WhenAny(new Task[] { readTask, timeoutTask });
            var done        = await combined;

            if (done == readTask)
            {
                return(readTask.Result);
            }
            throw new TimeoutException();
        }
        public static async Task AssertStreamEnd(
            this IReadableByteStream stream)
        {
            var headerBytes = new byte[FrameHeader.HeaderSize];
            var res         = await ReadWithTimeout(stream, new ArraySegment <byte>(headerBytes));

            if (!res.EndOfStream)
            {
                var hdr = FrameHeader.DecodeFrom(
                    new ArraySegment <byte>(headerBytes));
                var msg = "Expected end of stream, but got " +
                          FramePrinter.PrintFrameHeader(hdr);
                Assert.True(res.EndOfStream, msg);
            }
            Assert.Equal(0, res.BytesRead);
        }
Exemplo n.º 18
0
        /// <summary>
        /// Reads the preface from the given stream and compares it to
        /// the expected value.
        /// Will throw an error if the preface could not be read or if the stream
        /// has finished unexpectedly.
        /// </summary>
        public static async ValueTask <DoneHandle> ReadAsync(IReadableByteStream stream)
        {
            var buffer = new byte[Length];
            await stream.ReadAll(new ArraySegment <byte>(buffer));

            // Compare with the expected preface
            for (var i = 0; i < buffer.Length; i++)
            {
                if (buffer[i] != Bytes[i])
                {
                    throw new Exception("Invalid prefix received");
                }
            }

            return(DoneHandle.Instance);
        }
Exemplo n.º 19
0
        /// <summary>
        /// 从给定流读取序言并将其与预期值进行比较。
        /// </summary>
        public static async ValueTask <DoneHandle> ReadAsync(IReadableByteStream stream)
        {
            var buffer = new byte[Length];

            await stream.ReadAll(new ArraySegment <byte>(buffer));

            for (var i = 0; i < buffer.Length; i++)
            {
                if (buffer[i] != Bytes[i])
                {
                    throw new Exception("接收到无效前缀");
                }
            }

            return(DoneHandle.Instance);
        }
        public static async Task AssertReadTimeout(
            this IReadableByteStream stream)
        {
            var buf = new byte[1];

            try
            {
                await stream.ReadAllWithTimeout(
                    new ArraySegment <byte>(buf));
            }
            catch (Exception e)
            {
                Assert.IsType <TimeoutException>(e);
                return;
            }
            Assert.False(true, "Expected no more data but received a byte");
        }
        public static async Task AssertWindowUpdate(
            this IReadableByteStream stream,
            uint expectedStreamId,
            int increment)
        {
            var header = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.WindowUpdate, header.Type);
            Assert.Equal(WindowUpdateData.Size, header.Length);
            Assert.Equal(0, header.Flags);
            Assert.Equal(expectedStreamId, header.StreamId);
            var buf = new byte[WindowUpdateData.Size];
            await stream.ReadAllWithTimeout(new ArraySegment <byte>(buf));

            var wu = WindowUpdateData.DecodeFrom(new ArraySegment <byte>(buf));

            Assert.Equal(increment, wu.WindowSizeIncrement);
        }
        public static async Task AssertResetStreamReception(
            this IReadableByteStream stream,
            uint expectedStreamId,
            ErrorCode expectedErrorCode)
        {
            var hdr = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.ResetStream, hdr.Type);
            Assert.Equal(expectedStreamId, hdr.StreamId);
            Assert.Equal(0, hdr.Flags);
            Assert.Equal(ResetFrameData.Size, hdr.Length);
            var resetBytes = new byte[hdr.Length];
            await stream.ReadAllWithTimeout(new ArraySegment <byte>(resetBytes));

            var resetData = ResetFrameData.DecodeFrom(new ArraySegment <byte>(resetBytes));

            Assert.Equal(expectedErrorCode, resetData.ErrorCode);
        }
        public static async Task AssertGoAwayReception(
            this IReadableByteStream stream,
            ErrorCode expectedErrorCode,
            uint lastStreamId)
        {
            var hdr = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.GoAway, hdr.Type);
            Assert.Equal(0u, hdr.StreamId);
            Assert.Equal(0, hdr.Flags);
            Assert.InRange(hdr.Length, 8, 256);
            var goAwayBytes = new byte[hdr.Length];
            await stream.ReadAllWithTimeout(new ArraySegment <byte>(goAwayBytes));

            var goAwayData = GoAwayFrameData.DecodeFrom(new ArraySegment <byte>(goAwayBytes));

            Assert.Equal(lastStreamId, goAwayData.Reason.LastStreamId);
            Assert.Equal(expectedErrorCode, goAwayData.Reason.ErrorCode);
        }
Exemplo n.º 24
0
        Connection BuildConnection(
            bool isServer,
            Settings settings,
            IReadableByteStream inputStream,
            IWriteAndCloseableByteStream outputStream)
        {
            var config =
                new ConnectionConfigurationBuilder(isServer)
                .UseSettings(settings)
                .UseStreamListener((s) => false)
                .Build();

            return(new Connection(
                       config, inputStream, outputStream,
                       new Connection.Options
            {
                Logger = loggerProvider.CreateLogger("http2Con"),
            }));
        }
        public static async Task ReadAndDiscardData(
            this IReadableByteStream stream,
            uint expectedStreamId,
            bool expectEndOfStream,
            int?expectedAmount)
        {
            var header = await stream.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Data, header.Type);
            Assert.Equal(expectedStreamId, header.StreamId);
            var isEndOfStream = (header.Flags & (byte)DataFrameFlags.EndOfStream) != 0;

            Assert.Equal(expectEndOfStream, isEndOfStream);
            if (expectedAmount.HasValue)
            {
                Assert.Equal(expectedAmount.Value, header.Length);
            }
            var dataBuf = new ArraySegment <byte>(new byte[header.Length]);
            await stream.ReadAllWithTimeout(dataBuf);
        }
        public static async Task <byte[]> ReadAllToArray(
            this IReadableByteStream stream)
        {
            var totalBuf = new MemoryStream();
            var buf      = new byte[16 * 1024];

            while (true)
            {
                var res = await stream.ReadAsync(new ArraySegment <byte>(buf));

                if (res.BytesRead > 0)
                {
                    totalBuf.Write(buf, 0, res.BytesRead);
                }
                if (res.EndOfStream)
                {
                    return(totalBuf.ToArray());
                }
            }
        }
Exemplo n.º 27
0
        static async Task <byte[]> ReadAllToArray(
            this IReadableByteStream stream)
        {
            var readBuffer = Buffers.Pool.Rent(ReadBufferSize);

            using (var memoryStream = new MemoryStream())
            {
                while (true)
                {
                    var streamReadResult = await stream.ReadAsync(new ArraySegment <byte>(readBuffer));

                    if (streamReadResult.BytesRead > 0)
                    {
                        memoryStream.Write(readBuffer, 0, streamReadResult.BytesRead);
                    }
                    if (streamReadResult.EndOfStream)
                    {
                        return(memoryStream.ToArray());
                    }
                }
            }
        }
Exemplo n.º 28
0
        public async static ValueTask <DoneHandle> ReadAll(
            this IReadableByteStream stream, ArraySegment <byte> buffer)
        {
            var array  = buffer.Array;
            var offset = buffer.Offset;
            var count  = buffer.Count;


            while (count != 0)
            {
                var segment = new ArraySegment <byte>(array, offset, count);
                var res     = await stream.ReadAsync(segment);

                if (res.EndOfStream)
                {
                    throw new System.IO.EndOfStreamException();
                }
                offset += res.BytesRead;
                count  -= res.BytesRead;
            }

            return(DoneHandle.Instance);
        }
Exemplo n.º 29
0
 public HttpStream(IReadableByteStream stream)
 {
     _stream = stream;
 }
Exemplo n.º 30
0
        /// <summary>
        /// 在双向流的顶部创建新的HTTP/2连接
        /// </summary>
        /// <param name="config"></param>
        /// <param name="inputStream"></param>
        /// <param name="outputStream"></param>
        /// <param name="options"></param>
        public Connection(ConnectionConfiguration config, IReadableByteStream inputStream, IWriteAndCloseableByteStream outputStream, Options?options = null)
        {
            if (config == null)
            {
                throw new ArgumentNullException(nameof(config));
            }
            this.config = config;

            if (!config.IsServer)
            {
                clientState = new ClientState();
            }

            localSettings = config.Settings;

            localSettings.EnablePush = false;


            if (IsServer && options?.ServerUpgradeRequest != null)
            {
                serverUpgradeRequest = options.Value.ServerUpgradeRequest;
                if (!serverUpgradeRequest.IsValid)
                {
                    throw new ArgumentException(
                              "ServerUpgradeRequest无效.\n" +
                              "无效的HTTP/1升级请求必须被拒绝");
                }
                else
                {
                    remoteSettings = serverUpgradeRequest.Settings;
                }
            }

            if (inputStream == null)
            {
                throw new ArgumentNullException(nameof(inputStream));
            }
            if (outputStream == null)
            {
                throw new ArgumentNullException(nameof(outputStream));
            }
            this.inputStream = inputStream;


            shared.Mutex                = new object();
            shared.streamMap            = new Dictionary <uint, StreamImpl>();
            shared.LastOutgoingStreamId = 0u;
            shared.LastIncomingStreamId = 0u;
            shared.GoAwaySent           = false;
            shared.Closed               = false;
            shared.PingState            = null;


            if (!IsServer && options?.ClientUpgradeRequest != null)
            {
                var upgrade = options.Value.ClientUpgradeRequest;
                if (!upgrade.IsValid)
                {
                    throw new ArgumentException(
                              "ClientUpgradeRequest无效。\n" +
                              "无效的升级请求必须被HTTP/1处理程序拒绝");
                }

                localSettings = upgrade.Settings;

                var newStream = new StreamImpl(
                    this,
                    1u,
                    StreamState.HalfClosedLocal,
                    (int)localSettings.InitialWindowSize);

                shared.streamMap[1u]        = newStream;
                shared.LastOutgoingStreamId = 1u;
                var setStream =
                    upgrade.UpgradeRequestStreamTcs.TrySetResult(newStream);
            }

            var dynTableSizeLimit = Math.Min(localSettings.HeaderTableSize, int.MaxValue);

            writer = new ConnectionWriter(
                this, outputStream,
                new ConnectionWriter.Options
            {
                MaxFrameSize          = (int)remoteSettings.MaxFrameSize,
                MaxHeaderListSize     = (int)remoteSettings.MaxHeaderListSize,
                InitialWindowSize     = (int)remoteSettings.InitialWindowSize,
                DynamicTableSizeLimit = (int)dynTableSizeLimit,
            },
                new HPack.Encoder.Options
            {
                DynamicTableSize = (int)remoteSettings.HeaderTableSize,
                HuffmanStrategy  = config.HuffmanStrategy,
            }
                );

            nrUnackedSettings++;

            headerReader = new HeaderReader(
                new HPack.Decoder(new HPack.Decoder.Options
            {
                DynamicTableSizeLimit = (int)dynTableSizeLimit,
                BufferPool            = config.BufferPool,
            }),
                localSettings.MaxFrameSize,
                localSettings.MaxHeaderListSize,
                inputStream
                );

            readerDone = Task.Run(() => this.RunReaderAsync());
        }