internal async Task <bool> Parse(Uri serverAddress, Stream request, NHError error) { bool needsInput; try { // the following parsing methods return false if they read the stream, but didn't like the request, // in which case they keep reading to the end. If there is a parsing error that means the stream is // now unsynchronized, they throw an exception MemoryStream headerStream = await FetchHeaders(request); if (headerStream == null || headerStream.Length == 0) { closedTask.SetResult(false); return(false); } using (StreamReader reader = new StreamReader(headerStream, Encoding.UTF8, false, 1024, true)) { needsInput = ParsePreamble(serverAddress, reader, error); ParseHeaders(reader, error); } if (needsInput) { needsInput = await MaybeContinue(request, error); } } catch (Exception e) { closedTask.SetResult(false); throw e; } if (needsInput) { if (headers[HttpRequestHeader.TransferEncoding] == "chunked") { length = -1; currentChunkRemaining = -1; } else { length = long.Parse(headers[HttpRequestHeader.ContentLength]); currentChunkRemaining = length; } socketStream = request; } else { length = 0; currentChunkRemaining = 0; closedTask.SetResult(true); } return(true); }
private void AddHeader(string headerLine, NHError error) { int colonPos = headerLine.IndexOf(':'); if (colonPos == -1) { throw new ApplicationException("Bad header field " + headerLine); } string key = headerLine.Substring(0, colonPos).Trim(); string value = headerLine.Substring(colonPos + 1).Trim(); try { headers.Add(key, value); } catch (Exception e) { logger.Log("Parsing header line " + headerLine + " got exception " + e.ToString()); throw new ApplicationException("Bad header field " + headerLine + " threw exception", e); } }
private void ParseHeaders(StreamReader reader, NHError error) { string currentHeader = null; while (true) { string headerLine = reader.ReadLine(); if (headerLine.Length == 0) { if (currentHeader == null) { throw new ApplicationException("No headers"); } AddHeader(currentHeader, error); return; } if (headerLine.StartsWith(" ") || headerLine.StartsWith("\t")) { if (currentHeader == null) { throw new ApplicationException("Continuation header without preceding header"); } currentHeader = currentHeader + headerLine; } else { if (currentHeader != null) { AddHeader(currentHeader, error); } currentHeader = headerLine; } } }
protected abstract Task <bool> MaybeContinue(Stream request, NHError error);
protected abstract bool ParsePreamble(Uri serverAddress, StreamReader stream, NHError error);