public void AppendData(IEnumerable <byte> newData) { if (newData == null) { return; } var data = newData.ToArray(); if (_buffer == null || data.Length == 0) { return; } _buffer.AddRange(data); MultipartReader.MultipartReaderState nextState; do { nextState = MultipartReader.MultipartReaderState.Uninitialized; var bufLen = _buffer.Count; switch (state) { case MultipartReader.MultipartReaderState.AtStart: // The entire message might start with a boundary without a leading CRLF. var boundaryWithoutLeadingCRLF = TrimmedBoundary.ToArray(); if (bufLen >= boundaryWithoutLeadingCRLF.Length) { // if (Arrays.equals(buffer.toByteArray(), boundaryWithoutLeadingCRLF)) { if (Memcmp(_buffer.ToArray(), boundaryWithoutLeadingCRLF, boundaryWithoutLeadingCRLF.Length)) { DeleteUpThrough(boundaryWithoutLeadingCRLF.Length); nextState = MultipartReader.MultipartReaderState.InHeaders; } else { nextState = MultipartReader.MultipartReaderState.InPrologue; } } break; case MultipartReader.MultipartReaderState.InPrologue: case MultipartReader.MultipartReaderState.InBody: // Look for the next part boundary in the data we just added and the ending bytes of // the previous data (in case the boundary string is split across calls) if (bufLen < _boundary.Length) { break; } var start = Math.Max(0, bufLen - data.Length - _boundary.Length); var r = SearchFor(_boundary, start); if (r.Length > 0) { if (state == MultipartReader.MultipartReaderState.InBody) { var dataToAppend = new byte[r.Location]; Array.Copy(_buffer.ToArray(), 0, dataToAppend, 0, dataToAppend.Length); _readerDelegate.AppendToPart(dataToAppend); _readerDelegate.FinishedPart(); } DeleteUpThrough(r.Location + r.Length); nextState = MultipartReader.MultipartReaderState.InHeaders; } else { TrimBuffer(); } break; case MultipartReader.MultipartReaderState.InHeaders: // First check for the end-of-message string ("--" after separator): if (bufLen >= 2 && Memcmp(_buffer.ToArray(), EOM_BYTES, 2)) { state = MultipartReader.MultipartReaderState.AtEnd; Close(); return; } // Otherwise look for two CRLFs that delimit the end of the headers: var headerEnd = SearchFor(CRLF_CRLF, 0); if (headerEnd.Length > 0) { var headersBytes = new Couchbase.Lite.Util.ArraySegment <Byte>(_buffer.ToArray(), 0, headerEnd.Location); // <-- better? var headersString = Encoding.UTF8.GetString(headersBytes.ToArray()); ParseHeaders(headersString); DeleteUpThrough(headerEnd.Location + headerEnd.Length); _readerDelegate.StartedPart(_headers); nextState = MultipartReader.MultipartReaderState.InBody; } break; default: Log.To.Sync.E(Tag, "Unexpected data after end of MIME body, throwing..."); throw new InvalidOperationException("Unexpected data after end of MIME body"); } if (nextState != MultipartReader.MultipartReaderState.Uninitialized) { state = nextState; } } while (nextState != MultipartReader.MultipartReaderState.Uninitialized && _buffer.Count > 0); }
public void AppendData(IEnumerable<byte> newData) { if (newData == null) { return; } var data = newData.ToArray(); if (_buffer == null || data.Length == 0) { return; } _buffer.AddRange(data); MultipartReader.MultipartReaderState nextState; do { nextState = MultipartReader.MultipartReaderState.Uninitialized; var bufLen = _buffer.Count; switch (state) { case MultipartReader.MultipartReaderState.AtStart: // The entire message might start with a boundary without a leading CRLF. var boundaryWithoutLeadingCRLF = TrimmedBoundary.ToArray(); if (bufLen >= boundaryWithoutLeadingCRLF.Length) { // if (Arrays.equals(buffer.toByteArray(), boundaryWithoutLeadingCRLF)) { if (Memcmp(_buffer.ToArray(), boundaryWithoutLeadingCRLF, boundaryWithoutLeadingCRLF.Length)) { DeleteUpThrough(boundaryWithoutLeadingCRLF.Length); nextState = MultipartReader.MultipartReaderState.InHeaders; } else { nextState = MultipartReader.MultipartReaderState.InPrologue; } } break; case MultipartReader.MultipartReaderState.InPrologue: case MultipartReader.MultipartReaderState.InBody: // Look for the next part boundary in the data we just added and the ending bytes of // the previous data (in case the boundary string is split across calls) if (bufLen < _boundary.Length) { break; } var start = Math.Max(0, bufLen - data.Length - _boundary.Length); var r = SearchFor(_boundary, start); if (r.Length > 0) { if (state == MultipartReader.MultipartReaderState.InBody) { var dataToAppend = new byte[r.Location]; Array.Copy(_buffer.ToArray(), 0, dataToAppend, 0, dataToAppend.Length); _readerDelegate.AppendToPart(dataToAppend); _readerDelegate.FinishedPart(); } DeleteUpThrough(r.Location + r.Length); nextState = MultipartReader.MultipartReaderState.InHeaders; } else { TrimBuffer(); } break; case MultipartReader.MultipartReaderState.InHeaders: // First check for the end-of-message string ("--" after separator): if (bufLen >= 2 && Memcmp(_buffer.ToArray(), EOM_BYTES, 2)) { state = MultipartReader.MultipartReaderState.AtEnd; Close(); return; } // Otherwise look for two CRLFs that delimit the end of the headers: var headerEnd = SearchFor(CRLF_CRLF, 0); if (headerEnd.Length > 0) { var headersBytes = new Couchbase.Lite.Util.ArraySegment<Byte>(_buffer.ToArray(), 0, headerEnd.Location); // <-- better? var headersString = Encoding.UTF8.GetString(headersBytes.ToArray()); ParseHeaders(headersString); DeleteUpThrough(headerEnd.Location + headerEnd.Length); _readerDelegate.StartedPart(_headers); nextState = MultipartReader.MultipartReaderState.InBody; } break; default: Log.To.Sync.E(Tag, "Unexpected data after end of MIME body, throwing..."); throw new InvalidOperationException("Unexpected data after end of MIME body"); } if (nextState != MultipartReader.MultipartReaderState.Uninitialized) { state = nextState; } } while (nextState != MultipartReader.MultipartReaderState.Uninitialized && _buffer.Count > 0); }