bool ParseBody(MultipartMimeParsingContex context) { bool result = this.FindBoundary(context); if (result) { byte[] body = new byte[context.ParsingIndex]; Buffer.BlockCopy(this.buffer, this.offset, body, 0, context.ParsingIndex); context.Message.Body = new MemoryStream(body); this.ConsumeBytes(context.ParsingIndex + context.Boundary.Length); context.ParsingIndex = 0; context.State = ParsingState.AfterBoundary; } return(result); }
void ParseMultipartMime(int read, MultipartMimeParsingContex context) { this.count += read; bool continueParsing = true; while (continueParsing) { switch (context.State) { case ParsingState.FirstBoundary: continueParsing = this.ParseFirstMimeBoundary(context); break; case ParsingState.ContentTypeHeader: continueParsing = this.ParseContentTypeHeader(context); break; case ParsingState.ContentDescriptionHeader: continueParsing = this.ParseContentDescriptionHeader(context); break; case ParsingState.CRLF: continueParsing = this.ParseCRLF(context); break; case ParsingState.Body: continueParsing = this.ParseBody(context); if (continueParsing) { this.DispatchMessage(context.Message); context.Message = null; } break; case ParsingState.AfterBoundary: continueParsing = this.ParseAfterBoundary(context); break; case ParsingState.Epilogue: // ignore all data after the final MIME boundary continueParsing = false; this.ConsumeBytes(this.count); break; } ; } }
bool ParseCRLF(MultipartMimeParsingContex context) { bool result = this.FindCRLF(context); if (result) { if (context.ParsingIndex != 0) { throw new InvalidOperationException("Malformed HTTP long poll response. Unexpected MIME part header."); } this.ConsumeBytes(2); context.ParsingIndex = 0; context.State = ParsingState.Body; } return(result); }
bool FindCRLF(MultipartMimeParsingContex context) { bool result = false; while (!result && context.ParsingIndex < (this.count - 1)) { if (this.buffer[this.offset + context.ParsingIndex] == 0x0D && this.buffer[this.offset + context.ParsingIndex + 1] == 0x0A) { result = true; } else { context.ParsingIndex++; } } return(result); }
bool FindBoundary(MultipartMimeParsingContex context) { bool result = false; while (!result && context.ParsingIndex <= (this.count - context.Boundary.Length)) { result = true; int i = 0; while (result && i < context.Boundary.Length) { result = this.buffer[this.offset + context.ParsingIndex + i] == context.Boundary[i]; i++; } if (!result) { context.ParsingIndex++; } } return(result); }
bool ParseContentDescriptionHeader(MultipartMimeParsingContex context) { bool result = this.FindCRLF(context); if (result) { string header = Encoding.UTF8.GetString(this.buffer, this.offset, context.ParsingIndex); Match m = contentDescriptionRegex.Match(header); if (!m.Success) { throw new InvalidOperationException("Malformed HTTP long poll response. Connot determine topicId and messageId of the MIME part."); } context.Message.TopicId = int.Parse(m.Groups[1].Value, CultureInfo.InvariantCulture); context.Message.MessageId = int.Parse(m.Groups[2].Value, CultureInfo.InvariantCulture); this.ConsumeBytes(context.ParsingIndex + 2); context.ParsingIndex = 0; context.State = ParsingState.CRLF; } return(result); }
bool ParseContentTypeHeader(MultipartMimeParsingContex context) { bool result = this.FindCRLF(context); if (result) { string header = Encoding.UTF8.GetString(this.buffer, this.offset, context.ParsingIndex); Match m = contentTypeRegex.Match(header); if (!m.Success) { throw new InvalidOperationException("Malformed HTTP long poll response. Cannot determine the content type of the MIME part."); } context.Message = new PubsubMessage(); context.Message.ContentType = m.Groups[1].Value; this.ConsumeBytes(context.ParsingIndex + 2); context.ParsingIndex = 0; context.State = ParsingState.ContentDescriptionHeader; } return(result); }
bool ParseFirstMimeBoundary(MultipartMimeParsingContex context) { bool result = this.FindCRLF(context); if (result) { if (context.ParsingIndex < 3 || this.buffer[this.offset] != 0x2D || this.buffer[this.offset + 1] != 0x2D) { // boundary does not start with "--" or is shorter than 1 character throw new InvalidOperationException("Malformed HTTP long poll response. Cannot determine multipart/mixed boundary."); } context.Boundary = new byte[2 + context.ParsingIndex]; context.Boundary[0] = 0x0D; context.Boundary[1] = 0x0A; Buffer.BlockCopy(this.buffer, this.offset, context.Boundary, 2, context.ParsingIndex); this.ConsumeBytes(context.ParsingIndex + 2); context.ParsingIndex = 0; context.State = ParsingState.ContentTypeHeader; } return(result); }
bool ParseAfterBoundary(MultipartMimeParsingContex context) { if (this.count >= 2) { if (this.buffer[this.offset] == 0x0D && this.buffer[this.offset + 1] == 0x0A) { // another MIME part is expected this.ConsumeBytes(2); context.State = ParsingState.ContentTypeHeader; } else if (this.buffer[this.offset] == 0x2D && this.buffer[this.offset + 1] == 0x2D) { // another MIME part is not expected this.ConsumeBytes(2); context.State = ParsingState.Epilogue; } else { throw new InvalidOperationException("Malformed HTTP long poll response. Protocol violation after MIME boundary."); } } return(this.count > 0); }