private async Task HandleFrameProcessingError( Http2Error err) { if (err.StreamId == 0) { await InitiateGoAway(err.Code, true); } else { StreamImpl stream = null; lock (shared.Mutex) { shared.streamMap.TryGetValue(err.StreamId, out stream); } if (stream != null) { await stream.Reset(err.Code, false); } else { var fh = new FrameHeader { StreamId = err.StreamId, Type = FrameType.ResetStream, Flags = 0, }; var resetData = new ResetFrameData { ErrorCode = err.Code, }; await writer.WriteResetStream(fh, resetData); } } }
private async ValueTask <Http2Error?> HandleResetFrame(FrameHeader fh) { if (fh.StreamId == 0 || fh.Length != ResetFrameData.Size) { var errc = ErrorCode.ProtocolError; if (fh.Length != ResetFrameData.Size) { errc = ErrorCode.FrameSizeError; } return(new Http2Error { StreamId = 0, Code = errc, Message = "接收到无效的RST_STREAM帧头", }); } await inputStream.ReadAll( new ArraySegment <byte>(receiveBuffer, 0, ResetFrameData.Size)); var resetData = ResetFrameData.DecodeFrom( new ArraySegment <byte>(receiveBuffer, 0, ResetFrameData.Size)); StreamImpl stream = null; uint lastOutgoingStream = 0u; uint lastIncomingStream = 0u; lock (shared.Mutex) { lastIncomingStream = shared.LastIncomingStreamId; lastOutgoingStream = shared.LastOutgoingStreamId; shared.streamMap.TryGetValue(fh.StreamId, out stream); if (stream != null) { shared.streamMap.Remove(fh.StreamId); } } if (stream != null) { await stream.Reset(resetData.ErrorCode, true); } else { if (IsIdleStreamId(fh.StreamId, lastOutgoingStream, lastIncomingStream)) { return(new Http2Error { StreamId = 0u, Code = ErrorCode.ProtocolError, Message = "接收到空闲流的RST_STREAM", }); } } return(null); }
public ValueTask <WriteResult> WriteResetStream( FrameHeader header, ResetFrameData data) { return(PerformWriteRequestAsync( header.StreamId, wr => { wr.Header = header; wr.ResetFrameData = data; }, false)); }
internal ValueTask <ConnectionWriter.WriteResult> Reset( ErrorCode errorCode, bool fromRemote) { ValueTask <ConnectionWriter.WriteResult> writeResetTask = new ValueTask <ConnectionWriter.WriteResult>( ConnectionWriter.WriteResult.Success); lock (stateMutex) { if (state == StreamState.Reset || state == StreamState.Closed) { return(writeResetTask); } state = StreamState.Reset; var head = receiveQueueHead; receiveQueueHead = null; FreeReceiveQueue(head); } if (!fromRemote) { var fh = new FrameHeader { StreamId = this.Id, Type = FrameType.ResetStream, Flags = 0, }; var resetData = new ResetFrameData { ErrorCode = errorCode }; writeResetTask = connection.writer.WriteResetStream(fh, resetData); } else { connection.writer.RemoveStream(this.Id); } if (!fromRemote) { this.connection.UnregisterStream(this); } readDataPossible.Set(); readTrailersPossible.Set(); readHeadersPossible.Set(); return(writeResetTask); }
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 WriteResetStream( this IWriteAndCloseableByteStream stream, uint streamId, ErrorCode errc) { var fh = new FrameHeader { Type = FrameType.ResetStream, Flags = 0, Length = ResetFrameData.Size, StreamId = streamId, }; var data = new ResetFrameData { ErrorCode = errc, }; var dataBytes = new byte[ResetFrameData.Size]; data.EncodeInto(new ArraySegment <byte>(dataBytes)); await stream.WriteFrameHeader(fh); await stream.WriteAsync(new ArraySegment <byte>(dataBytes)); }