public HttpData Receive(IDataStream s) { lock (contentLock) { if (useContentData) { contentData.Add(s); } dataBuilder.Append(s); if (state == ParsingState.Header) { try { if (parser.Parse(contentData, isResponse)) { state = ParsingState.Body; try { var code = parser.StatusCode; // header parsing is finished if (LastRequestMethod == HttpRequestMethod.HEAD) { info = new HttpBodyLengthInfo((long)0); } else if (LastRequestMethod == HttpRequestMethod.CONNECT && code > 199 && code < 300) { info = new HttpBodyLengthInfo((long)0); } else { info = parser.GetBodyLengthInfo(!isResponse); } useContentData = info.Type == HttpBodyLengthInfo.LengthType.Chunked; headerLength = parser.HeaderLength; if (contentData.Length - parser.HeaderLength > 0) { var tmpList = new StreamList(); var contentStart = new ByteArray(contentData, parser.HeaderLength); tmpList.Add(contentStart); contentData = tmpList; } else { contentData = new StreamList(); } } catch (BadRequestException) { throw new HttpInvalidMessageException(); } } } catch (HttpHeaderParserException) { throw new HttpInvalidMessageException(); } } if (state == ParsingState.Body) { if (info.Type == HttpBodyLengthInfo.LengthType.Exact && info.Length <= dataBuilder.Length - headerLength) { var resStream = dataBuilder.Close(); return(parser.Create(new StreamSegment(resStream, 0, headerLength), new StreamSegment(resStream, headerLength, info.Length), resStream)); } else if (info.Type == HttpBodyLengthInfo.LengthType.Chunked) { parseChunkedBody(); } } } if (state == ParsingState.CheckingChunedTrailer) { if (contentData.Length >= 2) { // check CRLF bool chunkedEnd = contentData.ReadByte(0) == 13 && contentData.ReadByte(1) == 10; if (chunkedEnd) { contentData = new StreamList(); var resStream = dataBuilder.Close(); return(parser.Create(new StreamSegment(resStream, 0, headerLength), new StreamSegment(resStream, headerLength), resStream)); } else { parser.ParseChunkedTrailer(); state = ParsingState.ParsingChunkedTrailer; } } } if (state == ParsingState.ParsingChunkedTrailer) { if (parser.Parse(contentData, isResponse)) { contentData = new StreamList(); var resStream = dataBuilder.Close(); return(parser.Create(new StreamSegment(resStream, 0, headerLength), new StreamSegment(resStream, headerLength), resStream)); } } return(null); }