Пример #1
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);
        }
        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);
        }