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