Esempio n. 1
0
        /// <summary>
        /// Sets the payload as a segment of a byte-array
        /// </summary>
        /// <param name="buffer">The byte array where to read the data from.</param>
        /// <param name="offset">The index where to start to read from.</param>
        /// <param name="count">The number of bytes to read.</param>
        /// <returns>The <see cref="MsgIn"/> instance itself, useful for fluent patterns.</returns>
        public MsgIn SetPayload(byte[] buffer, int offset, int count)
        {
            this.PayloadInternal = new byte[count];
            VectorizedCopyExtension.VectorizedCopy(
                buffer,
                offset,
                this.PayloadInternal,
                0,
                count
                );

            return(this);
        }
Esempio n. 2
0
        /// <summary>
        /// Sets the payload of the message as a byte-array.
        /// </summary>
        /// <remarks>
        /// The access of this method is allowed only to the NATS client infrastructure.
        /// </remarks>
        /// <param name="buffer">The byte array with the data as payload</param>
        internal void SetPayload(byte[] buffer)
        {
            this._payloadInternal = new byte[this.PayloadLength];

            //since the local payload byte-array is exposed to the host,
            //here it makes a copy of the given data
            VectorizedCopyExtension.VectorizedCopy(
                buffer,
                0,
                this._payloadInternal,
                0,
                this.PayloadLength
                );
        }
Esempio n. 3
0
        /// <summary>
        /// Copies the payload to a host-provided byte-array.
        /// </summary>
        /// <param name="buffer">The target byte-array, which should be large enough to hold the data.</param>
        /// <param name="offset">The starting position to copy the bytes from.</param>
        /// <returns>The number of bytes copied.</returns>
        public int GetPayloadAsByteArray(byte[] buffer, int offset)
        {
            int count = this._payloadInternal.Length;

            //since the local payload byte-array is exposed to the host,
            //here it makes a copy of the given data
            VectorizedCopyExtension.VectorizedCopy(
                this._payloadInternal,
                0,
                buffer,
                offset,
                count
                );

            return(count);
        }
Esempio n. 4
0
        /// <summary>
        /// Entry-point to feed the parser with data incoming from the NATS server
        /// </summary>
        /// <param name="segment"></param>
        internal void Parse(
            ArraySegment <byte> segment
            )
        {
            byte[] buffer = segment.Array;
            int    bstart = 0;
            int    bcount = 0;

#if DEBUG
            //Print(buffer, 0, segment.Count);
#endif
            for (int i = 0, len = segment.Count; i < len; i++)
            {
                char b = (char)buffer[i];

                switch (_state)
                {
                case OP_START:
                    switch (b)
                    {
                    case 'M':
                    case 'm':
                        _state = OP_M;
                        break;

                    case 'C':
                    case 'c':
                        _state = OP_C;
                        break;

                    case 'P':
                    case 'p':
                        _state = OP_P;
                        break;

                    case '+':
                        _state = OP_PLUS;
                        break;

                    case '-':
                        _state = OP_MINUS;
                        break;

                    case 'i':
                    case 'I':
                        _state = OP_I;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_M:
                    switch (b)
                    {
                    case 'S':
                    case 's':
                        _state = OP_MS;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_MS:
                    switch (b)
                    {
                    case 'G':
                    case 'g':
                        _state = OP_MSG;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_MSG:
                    switch (b)
                    {
                    case ' ':
                    case '\t':
                        _state = OP_MSG_SPC;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_MSG_SPC:
                    switch (b)
                    {
                    case ' ':
                        break;

                    case '\t':
                        break;

                    default:
                        this._xbuflen = 0;
                        bcount        = 0;
                        bstart        = i;
                        _state        = MSG_ARG;
                        i--;
                        break;
                    }
                    break;

                case MSG_ARG:
                    switch (b)
                    {
                    case '\r':
                        break;

                    case '\n':
                        if (bcount != 0)
                        {
                            AddSegment();
                            bcount = 0;
                        }
                        this.ParseHeader();
                        this._xbuflen = 0;
                        _state        = MSG_PAYLOAD;
                        break;

                    default:
                        bcount++;
                        break;
                    }
                    break;

                case MSG_PAYLOAD:
                    int msgSize = this._message.PayloadLength;
                    if (msgSize == 0)
                    {
                        this.NotifyMessage(this._message);
                        this._message = null;
                        _state        = MSG_END;
                    }
                    else
                    {
                        bcount = len - i;
                        if ((this._xbuflen + bcount) > msgSize)
                        {
                            bcount = msgSize - this._xbuflen;
                        }
                        if (bcount != 0)
                        {
                            bstart = i;
                            AddSegment();

                            i     += bcount - 1;
                            bcount = 0;
                        }
                        if (this._xbuflen >= msgSize)
                        {
                            this._message.SetPayload(this._xbuffer);
                            this.NotifyMessage(this._message);
                            this._message = null;

                            this._xbuflen = 0;
                            _state        = MSG_END;
                        }
                    }
                    break;

                case MSG_END:
                    switch (b)
                    {
                    case '\n':
                        _state = OP_START;
                        break;

                    default:
                        continue;
                    }
                    break;

                case OP_PLUS:
                    switch (b)
                    {
                    case 'O':
                    case 'o':
                        _state = OP_PLUS_O;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_PLUS_O:
                    switch (b)
                    {
                    case 'K':
                    case 'k':
                        _state = OP_PLUS_OK;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_PLUS_OK:
                    switch (b)
                    {
                    case '\n':
                        this.NotifyOperation(
                            default(ArraySegment <byte>),
                            this._state
                            );

                        _state = OP_START;
                        break;
                    }
                    break;

                case OP_MINUS:
                    switch (b)
                    {
                    case 'E':
                    case 'e':
                        _state = OP_MINUS_E;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_MINUS_E:
                    switch (b)
                    {
                    case 'R':
                    case 'r':
                        _state = OP_MINUS_ER;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_MINUS_ER:
                    switch (b)
                    {
                    case 'R':
                    case 'r':
                        _state = OP_MINUS_ERR;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_MINUS_ERR:
                    switch (b)
                    {
                    case ' ':
                    case '\t':
                        _state = OP_MINUS_ERR_SPC;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_MINUS_ERR_SPC:
                    switch (b)
                    {
                    case ' ':
                    case '\t':
                        _state = OP_MINUS_ERR_SPC;
                        break;

                    default:
                        this._xbuflen = 0;
                        bcount        = 0;
                        bstart        = i;
                        _state        = MINUS_ERR_ARG;
                        i--;
                        break;
                    }
                    break;

                case MINUS_ERR_ARG:
                    switch (b)
                    {
                    case '\r':
                        break;

                    case '\n':
                        if (bcount != 0)
                        {
                            AddSegment();
                            bcount = 0;
                        }
                        this.NotifyError(
                            new ArraySegment <byte>(this._xbuffer, 0, this._xbuflen)
                            );

                        this._xbuflen = 0;
                        _state        = OP_START;
                        break;

                    default:
                        bcount++;
                        break;
                    }
                    break;

                case OP_P:
                    switch (b)
                    {
                    case 'I':
                    case 'i':
                        _state = OP_PI;
                        break;

                    case 'O':
                    case 'o':
                        _state = OP_PO;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_PO:
                    switch (b)
                    {
                    case 'N':
                    case 'n':
                        _state = OP_PON;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_PON:
                    switch (b)
                    {
                    case 'G':
                    case 'g':
                        _state = OP_PONG;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_PONG:
                    switch (b)
                    {
                    case '\r':
                        break;

                    case '\n':
                        this.NotifyOperation(
                            default(ArraySegment <byte>),
                            this._state
                            );

                        _state = OP_START;
                        break;
                    }
                    break;

                case OP_PI:
                    switch (b)
                    {
                    case 'N':
                    case 'n':
                        _state = OP_PIN;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_PIN:
                    switch (b)
                    {
                    case 'G':
                    case 'g':
                        _state = OP_PING;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_PING:
                    switch (b)
                    {
                    case '\r':
                        break;

                    case '\n':
                        this.NotifyOperation(
                            default(ArraySegment <byte>),
                            this._state
                            );

                        _state = OP_START;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_I:
                    switch (b)
                    {
                    case 'N':
                    case 'n':
                        _state = OP_IN;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_IN:
                    switch (b)
                    {
                    case 'F':
                    case 'f':
                        _state = OP_INF;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_INF:
                    switch (b)
                    {
                    case 'O':
                    case 'o':
                        _state = OP_INFO;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_INFO:
                    switch (b)
                    {
                    case ' ':
                    case '\t':
                        _state = OP_INFO_SPC;
                        break;

                    default:
                        this.ParseError(buffer, i, len);
                        break;
                    }
                    break;

                case OP_INFO_SPC:
                    switch (b)
                    {
                    case ' ':
                    case '\t':
                        break;

                    default:
                        this._xbuflen = 0;
                        bcount        = 0;
                        bstart        = i;
                        this._state   = INFO_ARG;
                        i--;
                        break;
                    }
                    break;

                case INFO_ARG:
                    switch (b)
                    {
                    case '\r':
                        break;

                    case '\n':
                        if (bcount != 0)
                        {
                            AddSegment();
                            bcount = 0;
                        }
                        this.NotifyOperation(
                            new ArraySegment <byte>(this._xbuffer, 0, this._xbuflen),
                            this._state
                            );

                        this._xbuflen = 0;
                        this._state   = OP_START;
                        break;

                    default:
                        bcount++;
                        break;
                    }
                    break;

                default:
                    throw new NATSException("Unable to parse.");
                } // switch(state)
            }     // for

            if (bcount != 0)
            {
                AddSegment();
            }

            //inner data accumulator
            //appends a block of fresh bytes to the local cache
            void AddSegment()
            {
                int newlen = this._xbuflen + bcount;

                if (this._xbuffer.Length < newlen)
                {
                    Array.Resize(
                        ref this._xbuffer,
                        this._xbuffer.Length + Defaults.defaultBufSize
                        );
                }

                VectorizedCopyExtension.VectorizedCopy(
                    buffer,
                    bstart,
                    this._xbuffer,
                    this._xbuflen,
                    bcount
                    );

                this._xbuflen = newlen;
            }
        }