/// <summary> /// Reads a single message from the protocol buffer. First reads in any headers until a blank /// line is received. Then reads in the body of the message. The headers must include a Content-Length /// header specifying the length of the body. /// </summary> private static async Task <string> ReadPacket(ProtocolReader reader) { Dictionary <string, string> headers = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); string line; while ((line = await reader.ReadHeaderLineAsync().ConfigureAwait(false)) != null) { if (String.IsNullOrEmpty(line)) { // end of headers for this request... break; } var split = line.Split(_headerSeparator, 2); if (split.Length != 2) { // Probably getting an error message, so read all available text var error = line; try { // Encoding is uncertain since this is malformed error += Encoding.UTF8.GetString(await reader.ReadToEndAsync()); } catch (ArgumentException) { } throw new InvalidDataException("Malformed header, expected 'name: value'" + Environment.NewLine + error); } headers[split[0]] = split[1]; } if (line == null) { return(null); } string contentLengthStr; int contentLength; if (!headers.TryGetValue(Headers.ContentLength, out contentLengthStr)) { throw new InvalidDataException("Content-Length not specified on request"); } if (!Int32.TryParse(contentLengthStr, out contentLength) || contentLength < 0) { throw new InvalidDataException("Invalid Content-Length: " + contentLengthStr); } var contentBinary = await reader.ReadContentAsync(contentLength); if (contentBinary.Length != contentLength) { throw new InvalidDataException(string.Format("Content length does not match Content-Length header. Expected {0} bytes but read {1} bytes.", contentLength, contentBinary.Length)); } try { var text = Encoding.UTF8.GetString(contentBinary); return(text); } catch (ArgumentException ex) { throw new InvalidDataException("Content is not valid UTF-8.", ex); } }
/// <summary> /// Reads a single message from the protocol buffer. First reads in any headers until a blank /// line is received. Then reads in the body of the message. The headers must include a Content-Length /// header specifying the length of the body. /// </summary> private static async Task <string> ReadPacket(ProtocolReader reader) { var headers = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); var lines = new List <string>(); string line; while ((line = await reader.ReadHeaderLineAsync().ConfigureAwait(false)) != null) { lines.Add(line ?? "(null)"); if (String.IsNullOrEmpty(line)) { if (headers.Count == 0) { continue; } // end of headers for this request... break; } var split = line.Split(_headerSeparator, 2); if (split.Length != 2) { // Probably getting an error message, so read all available text var error = line; try { // Encoding is uncertain since this is malformed error += TextEncoding.GetString(await reader.ReadToEndAsync()); } catch (ArgumentException) { } throw new InvalidDataException("Malformed header, expected 'name: value'" + Environment.NewLine + error); } headers[split[0]] = split[1]; } if (line == null) { return(null); } string contentLengthStr; int contentLength; if (!headers.TryGetValue(Headers.ContentLength, out contentLengthStr)) { // HACK: Attempting to find problem with message content Console.Error.WriteLine("Content-Length not specified on request. Lines follow:"); foreach (var l in lines) { Console.Error.WriteLine($"> {l}"); } Console.Error.Flush(); throw new InvalidDataException("Content-Length not specified on request"); } if (!Int32.TryParse(contentLengthStr, out contentLength) || contentLength < 0) { throw new InvalidDataException("Invalid Content-Length: " + contentLengthStr); } var contentBinary = await reader.ReadContentAsync(contentLength); if (contentBinary.Length == 0 && contentLength > 0) { // The stream was closed, so let's abort safely return(null); } if (contentBinary.Length != contentLength) { throw new InvalidDataException(string.Format("Content length does not match Content-Length header. Expected {0} bytes but read {1} bytes.", contentLength, contentBinary.Length)); } try { var text = TextEncoding.GetString(contentBinary); return(text); } catch (ArgumentException ex) { throw new InvalidDataException("Content is not valid UTF-8.", ex); } }