示例#1
0
        public void Init()
        {
            this.RawData = this.ReadBinaries();

            this.IpRanges  = this.GetEmptyRangesIps(this.RawData.IpRangesCount);
            this.Locations = this.GetEmptyLocations(this.RawData.LocationsCount);

            var ipRanges  = this.IpRanges;
            var locations = this.Locations;

            BinaryReaderHelper.RawDeserializerList <IpRange>(
                this.RawData.IpRangesBytes,
                this.RawData.IpRangesCount,
                Marshal.SizeOf <IpRange>(),
                ref ipRanges);

            BinaryReaderHelper.RawDeserializerList <Location>(
                this.RawData.LocationsBytes,
                this.RawData.LocationsCount,
                Marshal.SizeOf <Location>(),
                ref locations);

            IpRanges  = ipRanges;
            Locations = locations;

            InitIndexes();

            OnIndexesCreated?.Invoke();
        }
示例#2
0
 public ArraySegment <byte> ReadValue(int length)
 {
     Trace.Assert(length <= Int32.MaxValue - 2);
     m_buffer.EnsureCapacity(length + 2);
     BinaryReaderHelper.ReadTo(m_reader, m_buffer.Array, 0, length + 2);
     return(new ArraySegment <byte>(m_buffer.Array, 0, length));
 }
示例#3
0
        private int ReadLine()
        {
            var position = BinaryReaderHelper.ReadToken(m_reader, m_buffer.Array, 0, m_buffer.Capacity,
                                                        token => token == 0x0A);

            if (position == -1)
            {
                throw new InvalidOperationException("End of line not found");
            }

            return(--position);
        }
示例#4
0
        private int ReadToken()
        {
            var position = BinaryReaderHelper.ReadToken(m_reader, m_buffer.Array, 0, m_buffer.Capacity,
                                                        token => token == 0x20 || token == 0x0A);

            if (position == -1)
            {
                throw new InvalidOperationException("Token not found");
            }

            if (m_buffer.Array[position] == 0x0A)
            {
                position--;
            }

            return(position);
        }
示例#5
0
        public ResponseStatus ReadStatus()
        {
            var buffer = m_buffer.Array;

            BinaryReaderHelper.ReadTo(m_reader, buffer, 0, Offset.EndOfHeader);

            var totalLength = BigEndianConverter.GetInt32(buffer, Offset.TotalBodyLength);

            m_buffer.EnsureCapacity(Offset.EndOfHeader + totalLength);
            BinaryReaderHelper.ReadTo(m_reader, buffer, Offset.EndOfHeader, totalLength);

            var status = (ResponseStatus)m_buffer.Array[Offset.Status];

            if (status == ResponseStatus.NoError)
            {
                if (buffer[Offset.OperationCode] == 0x00)
                {
                    status = ResponseStatus.Value;
                }
            }

            return(status);
        }
示例#6
0
        /// <summary>
        /// BinaryReader.BaseStream position is preserved in cases other than Continue
        /// </summary>
        /// <param name="br">
        /// A <see cref="BinaryReader"/>
        /// </param>
        /// <returns>
        /// A <see cref="ProcessStatus"/>
        /// ProcessStatus.Error if any errors are detected, the stream position
        ///         is restored to the starting position
        /// ProcessStatus.NeedMoreData if we run into a situation where there isn't
        ///         enough data to continue processing. Stream position is at the position
        ///         where the internal state machine is waiting to resume when additional
        ///         data arrives
        /// </returns>
        public ProcessStatus Process(BinaryReader br)
        {
            if (IsDebugEnabled)
            {
                Log.Debug("");
            }

            string line;

            HttpMessage.ProcessStatus processStatus;

            while (true)
            {
                // the request response and header phases work in terms of lines,
                // terminated by /r/n, this is different from the body phase that
                // is a blob of bytes if "Content-Length" was set in the headers, or
                // chunked mode if "Transfer-Encoding" was set in the headers
                if ((Phase == Phases.RequestResponse) ||
                    (Phase == Phases.Headers) ||
                    (Phase == Phases.BodyChunkedLength) ||
                    (Phase == Phases.BodyChunkSeparator))
                {
                    if (IsDebugEnabled)
                    {
                        Log.Debug("Line reading phase");
                    }

                    // save the starting position so we can restore if we don't have
                    // enough bytes
                    long startingPosition = br.BaseStream.Position;

                    // read the next line from the binary reader
                    var readNextLine
                        = BinaryReaderHelper.ReadNextLineFromBinaryReader(br, out line);

                    if (IsDebugEnabled)
                    {
                        Log.Debug("readNextLine {0}, line of '{1}'",
                                  readNextLine, line);
                    }

                    // NOTE: Because we ensure that we have a string that was properly terminated by
                    //       crlf we can consider 'Needs`MoreData' cases inside of this if() to be
                    //       errors
                    if (readNextLine == BinaryReaderHelper.ReadNextLineResponses.StringTerminatedByCrLf)
                    {
                        if (Phase == Phases.RequestResponse)
                        {
                            if (IsDebugEnabled)
                            {
                                Log.Debug("Phase == Phases.RequestResponse");
                            }

                            processStatus = ProcessRequestResponseFirstLineHandler(line);

                            if (processStatus == ProcessStatus.Error)
                            {
                                Log.Debug("ProcessStatus.Error() from ProcessRequestResponseFirstLineHandler()");

                                // rewind to the starting position
                                br.BaseStream.Position = startingPosition;

                                return(ProcessStatus.Error);
                            }
                            else if (processStatus == ProcessStatus.Complete)
                            {
                                Log.Debug("status == ProcessStatus.Compete, moving to Phases.Headers");

                                // done with the request/response first line handler
                                // move to the next phase
                                phase = Phases.Headers;
                            }
                            else
                            {
                                // make sure to catch any unexpected status return values
                                throw new System.InvalidOperationException("Unexpected processStatus of " + processStatus + " returned by ProcessRequestResponseFirstLineHandler()");
                            }
                        }
                        else if (Phase == Phases.Headers)
                        {
                            if (IsDebugEnabled)
                            {
                                Log.Debug("Phase == Phases.Headers");
                            }

                            processStatus = ProcessHeaders(line);

                            if (processStatus == ProcessStatus.Error)
                            {
                                Log.Debug("ProcessStatus.Error from ProcessHeaders(), moving back to startingPosition and returning ProcessStatus.Error");

                                // rewind to the starting position
                                br.BaseStream.Position = startingPosition;

                                return(ProcessStatus.Error);
                            }
                            else if (processStatus == ProcessStatus.Complete)
                            {
                                if (IsDebugEnabled)
                                {
                                    Log.Debug("Done with headers");
                                }

                                // done with headers
                                // if we have a content length then move to Phases.Body
                                // otherwise we are done with the request
                                if (ContentLength != -1)
                                {
                                    if (IsDebugEnabled)
                                    {
                                        Log.Debug("ContentLength is {0}, moving to Body phase",
                                                  ContentLength);
                                    }

                                    phase = Phases.Body;
                                }
                                else if (TransferEncoding == "chunked")
                                {
                                    if (IsDebugEnabled)
                                    {
                                        Log.Debug("TransferEncoding chunked, moving to Phases.BodyChunkedLength");
                                    }
                                    phase = Phases.BodyChunkedLength;
                                }
                                else
                                {
                                    // we are all done, no data follows the headers
                                    if (IsDebugEnabled)
                                    {
                                        Log.Debug("returning ProcessStatus.Complete");
                                    }
                                    return(ProcessStatus.Complete);
                                }
                            }
                            else if (processStatus == ProcessStatus.Continue)
                            {
                                if (IsDebugEnabled)
                                {
                                    Log.Debug("ProcessHeaders() returned 'Continue'");
                                }
                            }
                            else
                            {
                                // make sure to catch any unexpected status return values
                                throw new System.InvalidOperationException("Unexpected processStatus of " + processStatus + " returned by ProcessHeaders()");
                            }
                        }
                        else if (Phase == Phases.BodyChunkedLength)
                        {
                            if (IsDebugEnabled)
                            {
                                Log.Debug("Phase == Phases.BodyChunkedLength");
                            }

                            processStatus = PhaseBodyChunkLength(line);
                            if (processStatus != ProcessStatus.Continue)
                            {
                                return(processStatus);
                            }
                        }
                        else if (Phase == Phases.BodyChunkSeparator)
                        {
                            if (IsDebugEnabled)
                            {
                                Log.Debug("Phase == Phases.BodyChunkSeparator");
                            }

                            // we expect the line to be empty
                            if (line != String.Empty)
                            {
                                Log.Error("Expected a line that was String.Empty in the BodyChunkSeparator state but instead got '"
                                          + line + "'");
                                return(ProcessStatus.Error);
                            }

                            // if the ChunkLength is 0 then we are all done with the chunked data
                            if (ChunkLength == 0)
                            {
                                Log.Debug("Found ChunkLength of zero, decoding content and returning ProcessStatus.Complete");

                                // we have the entire body, decode the content
                                DecodeContent();

                                return(ProcessStatus.Complete);
                            }
                            else   // we have more chunks pending
                            {
                                // go back to the BodyChunkedLength phase
                                if (IsDebugEnabled)
                                {
                                    Log.Debug("Going back to Phases.BodyChunkedLength");
                                }
                                phase = Phases.BodyChunkedLength;
                            }
                        }
                    }
                    else if (readNextLine == BinaryReaderHelper.ReadNextLineResponses.NonAsciiCharacterFound)
                    {
                        if (IsDebugEnabled)
                        {
                            Log.Debug("found a non-ascii character, this appears to be a binary stream, returning an error code");
                        }

                        return(ProcessStatus.Error);
                    }
                    else if ((readNextLine == BinaryReaderHelper.ReadNextLineResponses.StringAtEndOfStream) ||
                             (readNextLine == BinaryReaderHelper.ReadNextLineResponses.NeedMoreBytes))
                    {
                        if (IsDebugEnabled)
                        {
                            Log.Debug("restoring the starting position and returning ProcessStatus.NeedMoreData",
                                      readNextLine);
                        }

                        // restore the starting position
                        br.BaseStream.Position = startingPosition;

                        // if we don't have enough data or if we have data but no crlf
                        // then report this
                        return(ProcessStatus.NeedMoreData);
                    }
                    else
                    {
                        // Treat errors more seriously in DEBUG mode
#if DEBUG
                        throw new System.InvalidOperationException("unknown readNextLine value of " + readNextLine + ", returning an error");
#else
                        Log.Error("unknown readNextLine value of " + readNextLine + ", returning an error");
                        return(ProcessStatus.Error);
#endif
                    }
                }
                else if (Phase == Phases.Body)
                {
                    if (IsDebugEnabled)
                    {
                        Log.Debug("Phase == Phases.Body");
                    }

                    processStatus = PhaseBody(br);
                    if (processStatus != ProcessStatus.Continue)
                    {
                        return(processStatus);
                    }
                }
                else if (Phase == Phases.BodyChunkData)
                {
                    if (IsDebugEnabled)
                    {
                        Log.Debug("Phase == Phases.BodyChunkData");
                    }

                    processStatus = PhaseBodyChunkData(br);
                    if (processStatus != ProcessStatus.Continue)
                    {
                        return(processStatus);
                    }
                }
                else
                {
                    throw new System.InvalidCastException("Unknown phase of " + Phase);
                }
            } // while(true)
        }
示例#7
0
        public ResponseStatus ReadStatus()
        {
            var status = ResponseStatus.Unknown;

            var buffer = m_statusBuffer;

            BinaryReaderHelper.ReadTo(m_reader, buffer, 0, 5);

            var remains = 0;
            var code    = buffer[3] | (buffer[4] << 8);

            switch (code)
            {
            case End:
                status = ResponseStatus.NoError;
                break;

            case Value:
                status  = ResponseStatus.Value;
                remains = 1;
                break;

            case Stored:
                status  = ResponseStatus.NoError;
                remains = 3;
                break;

            case Deleted:
                status  = ResponseStatus.NoError;
                remains = 4;
                break;

            case NotFound:
                status  = ResponseStatus.KeyNotFound;
                remains = 6;
                break;

            case Exists:
                status  = ResponseStatus.KeyExists;
                remains = 3;
                break;

            case NotStored:
                status  = ResponseStatus.ItemNotStored;
                remains = 7;
                break;

            case ServerError:
            case ClientError:
                Read(8);
                throw new InvalidOperationException(ReadError());

            case Error:
                Read(2);
                throw new InvalidOperationException();

            default:
                throw new NotImplementedException();
            }

            if (remains > 0)
            {
                BinaryReaderHelper.ReadTo(m_reader, buffer, 0, remains);
            }

            return(status);
        }
示例#8
0
 private void Read(int count)
 {
     BinaryReaderHelper.ReadTo(m_reader, m_buffer.Array, 0, count);
 }