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(byte[] data) { if (buffer == null) { return; } if (data.Length == 0) { return; } buffer.AddRange(data); MultipartReader.MultipartReaderState nextState; do { nextState = MultipartReader.MultipartReaderState.kUninitialized; var bufLen = buffer.Count; switch (state) { case MultipartReader.MultipartReaderState.kAtStart: { // Log.d(Database.TAG, "appendData. bufLen: " + bufLen); // The entire message might start with a boundary without a leading CRLF. var boundaryWithoutLeadingCRLF = GetBoundaryWithoutLeadingCRLF(); if (bufLen >= boundaryWithoutLeadingCRLF.Length) { // if (Arrays.equals(buffer.toByteArray(), boundaryWithoutLeadingCRLF)) { if (Memcmp(buffer.ToArray(), boundaryWithoutLeadingCRLF, boundaryWithoutLeadingCRLF.Length)) { DeleteUpThrough(boundaryWithoutLeadingCRLF.Length); nextState = MultipartReader.MultipartReaderState.kInHeaders; } else { nextState = MultipartReader.MultipartReaderState.kInPrologue; } } break; } case MultipartReader.MultipartReaderState.kInPrologue: case MultipartReader.MultipartReaderState.kInBody: { // 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.GetLength() > 0) { if (state == MultipartReader.MultipartReaderState.kInBody) { var dataToAppend = new ArraySegment <Byte>(buffer.ToArray(), 0, r.GetLocation()); readerDelegate.AppendToPart(dataToAppend); readerDelegate.FinishedPart(); } DeleteUpThrough(r.GetLocation() + r.GetLength()); nextState = MultipartReader.MultipartReaderState.kInHeaders; } else { TrimBuffer(); } break; } case MultipartReader.MultipartReaderState.kInHeaders: { // First check for the end-of-message string ("--" after separator): if (bufLen >= 2 && Memcmp(buffer.ToArray(), EOMBytes(), 2)) { state = MultipartReader.MultipartReaderState.kAtEnd; Close(); return; } // Otherwise look for two CRLFs that delimit the end of the headers: var r = SearchFor(kCRLFCRLF, 0); if (r.GetLength() > 0) { var headersBytes = Arrays.CopyTo(buffer.ToArray(), r.GetLocation()); // // var headersBytes = new ArraySegment<Byte>(buffer.ToArray(), 0, r.GetLocation()); // <-- better? var headersString = utf8.GetString(headersBytes); ParseHeaders(headersString); DeleteUpThrough(r.GetLocation() + r.GetLength()); readerDelegate.StartedPart(headers); nextState = MultipartReader.MultipartReaderState.kInBody; } break; } default: { throw new InvalidOperationException("Unexpected data after end of MIME body"); } } if (nextState != MultipartReader.MultipartReaderState.kUninitialized) { state = nextState; } }while (nextState != MultipartReader.MultipartReaderState.kUninitialized && buffer.Count > 0); }