Beispiel #1
0
        // Accept connection and handle connection setup
        public async Task EstablishConnectionAsync(params SettingsEntry[] settingsEntries)
        {
            await AcceptConnectionAsync().ConfigureAwait(false);

            // Receive the initial client settings frame.
            Frame receivedFrame = await ReadFrameAsync(Timeout).ConfigureAwait(false);

            Assert.Equal(FrameType.Settings, receivedFrame.Type);
            Assert.Equal(FrameFlags.None, receivedFrame.Flags);
            Assert.Equal(0, receivedFrame.StreamId);

            // Receive the initial client window update frame.
            receivedFrame = await ReadFrameAsync(Timeout).ConfigureAwait(false);

            Assert.Equal(FrameType.WindowUpdate, receivedFrame.Type);
            Assert.Equal(FrameFlags.None, receivedFrame.Flags);
            Assert.Equal(0, receivedFrame.StreamId);

            // Send the initial server settings frame.
            SettingsFrame settingsFrame = new SettingsFrame(settingsEntries);

            await WriteFrameAsync(settingsFrame).ConfigureAwait(false);

            // Send the client settings frame ACK.
            Frame settingsAck = new Frame(0, FrameType.Settings, FrameFlags.Ack, 0);

            await WriteFrameAsync(settingsAck).ConfigureAwait(false);

            // The client will send us a SETTINGS ACK eventually, but not necessarily right away.
            ExpectSettingsAck();
        }
        // Accept connection and handle connection setup
        public async Task EstablishConnectionAsync(params SettingsEntry[] settingsEntries)
        {
            await AcceptConnectionAsync();

            // Receive the initial client settings frame.
            Frame receivedFrame = await ReadFrameAsync(TimeSpan.FromSeconds(30));

            Assert.Equal(FrameType.Settings, receivedFrame.Type);
            Assert.Equal(FrameFlags.None, receivedFrame.Flags);
            Assert.Equal(0, receivedFrame.StreamId);

            // Receive the initial client window update frame.
            receivedFrame = await ReadFrameAsync(TimeSpan.FromSeconds(30));

            Assert.Equal(FrameType.WindowUpdate, receivedFrame.Type);
            Assert.Equal(FrameFlags.None, receivedFrame.Flags);
            Assert.Equal(0, receivedFrame.StreamId);

            // Send the initial server settings frame.
            SettingsFrame settingsFrame = new SettingsFrame(settingsEntries);

            await WriteFrameAsync(settingsFrame).ConfigureAwait(false);

            // Send the client settings frame ACK.
            Frame settingsAck = new Frame(0, FrameType.Settings, FrameFlags.Ack, 0);

            await WriteFrameAsync(settingsAck).ConfigureAwait(false);

            // The client will send us a SETTINGS ACK eventually, but not necessarily right away.
            // To simplify frame processing, set this flag to true so we will ignore the next SETTINGS ACK in ReadNextFrame.
            _ignoreSettingsAck = true;
        }
Beispiel #3
0
        public async Task <(Http2LoopbackConnection, SettingsFrame)> EstablishConnectionGetSettingsAsync(TimeSpan?timeout, TimeSpan?ackTimeout, params SettingsEntry[] settingsEntries)
        {
            Http2LoopbackConnection connection = await AcceptConnectionAsync(timeout).ConfigureAwait(false);

            SettingsFrame clientSettingsFrame = await connection.ReadAndSendSettingsAsync(ackTimeout, settingsEntries).ConfigureAwait(false);

            return(connection, clientSettingsFrame);
        }
        public async Task <Frame> ReadFrameAsync(CancellationToken cancellationToken)
        {
            // First read the frame headers, which should tell us how long the rest of the frame is.
            byte[] headerBytes = new byte[Frame.FrameHeaderLength];

            try
            {
                if (!await FillBufferAsync(headerBytes, cancellationToken).ConfigureAwait(false))
                {
                    return(null);
                }
            }
            catch (IOException)
            {
                // eat errors when client aborts connection and return null.
                return(null);
            }

            Frame header = Frame.ReadFrom(headerBytes);

            // Read the data segment of the frame, if it is present.
            byte[] data = new byte[header.Length];
            if (header.Length > 0 && !await FillBufferAsync(data, cancellationToken).ConfigureAwait(false))
            {
                throw new Exception("Connection stream closed while attempting to read frame body.");
            }

            if (_ignoredSettingsAckPromise != null && header.Type == FrameType.Settings && header.Flags == FrameFlags.Ack)
            {
                _ignoredSettingsAckPromise.TrySetResult(true);
                _ignoredSettingsAckPromise = null;
                return(await ReadFrameAsync(cancellationToken).ConfigureAwait(false));
            }

            if (_ignoreWindowUpdates && header.Type == FrameType.WindowUpdate)
            {
                return(await ReadFrameAsync(cancellationToken).ConfigureAwait(false));
            }

            if (header.Type == FrameType.Ping && _transparentPingResponse)
            {
                PingFrame pingFrame = PingFrame.ReadFrom(header, data);

                bool processed = await TryProcessExpectedPingFrameAsync(pingFrame);

                return(processed ? await ReadFrameAsync(cancellationToken).ConfigureAwait(false) : pingFrame);
            }

            // Construct the correct frame type and return it.
            switch (header.Type)
            {
            case FrameType.Settings:
                return(SettingsFrame.ReadFrom(header, data));

            case FrameType.Data:
                return(DataFrame.ReadFrom(header, data));

            case FrameType.Headers:
                return(HeadersFrame.ReadFrom(header, data));

            case FrameType.Priority:
                return(PriorityFrame.ReadFrom(header, data));

            case FrameType.RstStream:
                return(RstStreamFrame.ReadFrom(header, data));

            case FrameType.Ping:
                return(PingFrame.ReadFrom(header, data));

            case FrameType.GoAway:
                return(GoAwayFrame.ReadFrom(header, data));

            case FrameType.Continuation:
                return(ContinuationFrame.ReadFrom(header, data));

            case FrameType.WindowUpdate:
                return(WindowUpdateFrame.ReadFrom(header, data));

            default:
                return(header);
            }
        }
Beispiel #5
0
        private async Task <Frame> ReadFrameAsync(CancellationToken cancellationToken)
        {
            // First read the frame headers, which should tell us how long the rest of the frame is.
            byte[] headerBytes = new byte[Frame.FrameHeaderLength];

            try
            {
                if (!await FillBufferAsync(headerBytes, cancellationToken).ConfigureAwait(false))
                {
                    return(null);
                }
            }
            catch (IOException)
            {
                // eat errors when client aborts connection and return null.
                return(null);
            }

            Frame header = Frame.ReadFrom(headerBytes);

            // Read the data segment of the frame, if it is present.
            byte[] data = new byte[header.Length];
            if (header.Length > 0 && !await FillBufferAsync(data, cancellationToken).ConfigureAwait(false))
            {
                throw new Exception("Connection stream closed while attempting to read frame body.");
            }

            if (_ignoreSettingsAck && header.Type == FrameType.Settings && header.Flags == FrameFlags.Ack)
            {
                _ignoreSettingsAck = false;
                return(await ReadFrameAsync(cancellationToken).ConfigureAwait(false));
            }

            if (_ignoreWindowUpdates && header.Type == FrameType.WindowUpdate)
            {
                return(await ReadFrameAsync(cancellationToken).ConfigureAwait(false));
            }

            // Construct the correct frame type and return it.
            switch (header.Type)
            {
            case FrameType.Settings:
                return(SettingsFrame.ReadFrom(header, data));

            case FrameType.Data:
                return(DataFrame.ReadFrom(header, data));

            case FrameType.Headers:
                return(HeadersFrame.ReadFrom(header, data));

            case FrameType.Priority:
                return(PriorityFrame.ReadFrom(header, data));

            case FrameType.RstStream:
                return(RstStreamFrame.ReadFrom(header, data));

            case FrameType.Ping:
                return(PingFrame.ReadFrom(header, data));

            case FrameType.GoAway:
                return(GoAwayFrame.ReadFrom(header, data));

            default:
                return(header);
            }
        }