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