public async Task ServerShouldCloseTheConnectionIfCorrectPrefaceIsNotReceived() { var inPipe = new BufferedPipe(1024); var outPipe = new BufferedPipe(1024); var http2Con = BuildConnection(true, inPipe, outPipe); var b = new byte[ClientPreface.Length]; // Initialize with non-preface data for (var i = 0; i < b.Length; i++) { b[i] = 10; } await inPipe.WriteAsync(new ArraySegment <byte>(b)); // Wait for the response - a settings frame is expected first // But as there's a race condition the connection could be closed // before or after the settings frame was fully received try { await outPipe.ReadAndDiscardSettings(); var hdrBuf = new byte[FrameHeader.HeaderSize + 50]; var header = await FrameHeader.ReceiveAsync(outPipe, hdrBuf); Assert.Equal(FrameType.GoAway, header.Type); } catch (Exception e) { Assert.IsType <System.IO.EndOfStreamException>(e); } }
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(); }
private async ValueTask <Http2Error?> ReadOneFrame() { var fh = await FrameHeader.ReceiveAsync(inputStream, receiveBuffer); if (!settingsReceived) { if (fh.Type != FrameType.Settings || (fh.Flags & (byte)SettingsFrameFlags.Ack) != 0) { return(new Http2Error { StreamId = 0, Code = ErrorCode.ProtocolError, Message = "预期设置帧为第一帧", }); } } switch (fh.Type) { case FrameType.Settings: return(await HandleSettingsFrame(fh)); case FrameType.Priority: return(await HandlePriorityFrame(fh)); case FrameType.Ping: return(await HandlePingFrame(fh)); case FrameType.WindowUpdate: return(await HandleWindowUpdateFrame(fh)); case FrameType.PushPromise: return(await HandlePushPromiseFrame(fh)); case FrameType.ResetStream: return(await HandleResetFrame(fh)); case FrameType.GoAway: return(await HandleGoAwayFrame(fh)); case FrameType.Continuation: return(new Http2Error { StreamId = 0, Code = ErrorCode.ProtocolError, Message = "意外的继续帧", }); case FrameType.Data: return(await HandleDataFrame(fh)); case FrameType.Headers: var headerRes = await headerReader.ReadHeaders(fh, GetBuffer); if (headerRes.Error != null) { return(headerRes.Error); } return(await HandleHeaders(headerRes.HeaderData)); default: return(await HandleUnknownFrame(fh)); } }
/// <summary> /// 读取和解码包含单个头段帧和0个或多个连续帧的头段块。 /// </summary> /// <param name="firstHeader"></param> /// <param name="ensureBuffer"></param> /// <returns></returns> public async ValueTask <Result> ReadHeaders( FrameHeader firstHeader, Func <int, byte[]> ensureBuffer) { if (firstHeader.Length > maxFrameSize) { return(new Result { Error = new Http2Error { StreamId = 0, Code = ErrorCode.FrameSizeError, Message = "超过最大帧大小", }, }); } PriorityData?prioData = null; var allowedHeadersSize = maxHeaderFieldsSize; var headers = new List <HeaderField>(); var initialFlags = firstHeader.Flags; var f = (HeadersFrameFlags)firstHeader.Flags; var isEndOfStream = f.HasFlag(HeadersFrameFlags.EndOfStream); var isEndOfHeaders = f.HasFlag(HeadersFrameFlags.EndOfHeaders); var isPadded = f.HasFlag(HeadersFrameFlags.Padded); var hasPriority = f.HasFlag(HeadersFrameFlags.Priority); var minLength = 0; if (isPadded) { minLength += 1; } if (hasPriority) { minLength += 5; } if (firstHeader.Length < minLength) { return(new Result { Error = new Http2Error { StreamId = 0, Code = ErrorCode.ProtocolError, Message = "帧内容大小无效", }, }); } byte[] buffer = ensureBuffer(firstHeader.Length); await reader.ReadAll(new ArraySegment <byte>(buffer, 0, firstHeader.Length)); var offset = 0; var padLen = 0; if (isPadded) { padLen = buffer[0]; offset++; } if (hasPriority) { prioData = PriorityData.DecodeFrom( new ArraySegment <byte>(buffer, offset, 5)); offset += 5; } var contentLen = firstHeader.Length - offset - padLen; if (contentLen < 0) { return(new Result { Error = new Http2Error { StreamId = 0, Code = ErrorCode.ProtocolError, Message = "帧内容大小无效", }, }); } hpackDecoder.AllowTableSizeUpdates = true; var decodeResult = hpackDecoder.DecodeHeaderBlockFragment( new ArraySegment <byte>(buffer, offset, contentLen), allowedHeadersSize, headers); var err = DecodeResultToError(decodeResult); if (err != null) { return(new Result { Error = err }); } allowedHeadersSize -= decodeResult.HeaderFieldsSize; while (!isEndOfHeaders) { var contHeader = await FrameHeader.ReceiveAsync(reader, buffer); if (contHeader.Type != FrameType.Continuation || contHeader.StreamId != firstHeader.StreamId || contHeader.Length > maxFrameSize || contHeader.Length == 0) { return(new Result { Error = new Http2Error { StreamId = 0, Code = ErrorCode.ProtocolError, Message = "延续帧无效", }, }); } var contFlags = ((ContinuationFrameFlags)contHeader.Flags); isEndOfHeaders = contFlags.HasFlag(ContinuationFrameFlags.EndOfHeaders); buffer = ensureBuffer(contHeader.Length); await reader.ReadAll(new ArraySegment <byte>(buffer, 0, contHeader.Length)); offset = 0; contentLen = contHeader.Length; decodeResult = hpackDecoder.DecodeHeaderBlockFragment( new ArraySegment <byte>(buffer, offset, contentLen), allowedHeadersSize, headers); var err2 = DecodeResultToError(decodeResult); if (err2 != null) { return(new Result { Error = err2 }); } allowedHeadersSize -= decodeResult.HeaderFieldsSize; } if (!hpackDecoder.HasInitialState) { return(new Result { Error = new Http2Error { Code = ErrorCode.CompressionError, StreamId = 0u, Message = "接收到不完整的头块", }, }); } return(new Result { Error = null, HeaderData = new CompleteHeadersFrameData { StreamId = firstHeader.StreamId, Headers = headers, Priority = prioData, EndOfStream = isEndOfStream, }, }); }