Example #1
0
int RedisFrameDecoder::ProcessInlineBuffer(ChannelHandlerContext& ctx,
        Buffer& buffer, RedisCommandFrame* frame)
{
    TRACE_LOG("Enter inline processing.");
    int index = buffer.IndexOf(kCRLF, 2);
    if (-1 == index)
    {
        return 0;
    }
    while (true)
    {
        char ch;
        if (!buffer.ReadByte(ch))
        {
            break;
        }
        if (ch == ' ')
        {
            continue;
        }
        buffer.AdvanceReadIndex(-1);
        int current = buffer.GetReadIndex();
        if (current == index)
        {
            buffer.AdvanceReadIndex(2); //skip "\r\n"
            break;
        }
        int space_index = buffer.IndexOf(" ", 1, current, index - 2);
        if (-1 == space_index)
        {
            break;
        }

        Buffer* arg = frame->GetNextArgument(space_index - current);
        buffer.Read(arg, space_index - current);
        buffer.AdvanceReadIndex(1); //skip space char
    }
    int current = buffer.GetReadIndex();
    if (current < index)
    {
        Buffer* arg = frame->GetNextArgument(index - current);
        buffer.Read(arg, index - current);
        buffer.AdvanceReadIndex(2); //skip "\r\n"
    }
    return 1;
}
Example #2
0
bool RedisCommandDecoder::Decode(Channel* channel, Buffer& buffer, RedisCommandFrame& msg)
{
    while (buffer.Readable() && (buffer.GetRawReadBuffer()[0] == '\r' || buffer.GetRawReadBuffer()[0] == '\n'))
    {
        buffer.AdvanceReadIndex(1);
    }
    size_t mark_read_index = buffer.GetReadIndex();
    char ch;
    if (buffer.ReadByte(ch))
    {
        int ret = -1;
        if (ch == '*')
        {
            //reqtype = REDIS_REQ_MULTIBULK;
            msg.m_is_inline = false;
            ret = ProcessMultibulkBuffer(channel, buffer, msg);
        }
        else
        {
            //reqtype = REDIS_REQ_INLINE;
            msg.m_is_inline = true;
            buffer.AdvanceReadIndex(-1);
            ret = ProcessInlineBuffer(buffer, msg);
        }
        if (ret > 0)
        {
            size_t raw_data_size = buffer.GetReadIndex() - mark_read_index;
            msg.m_raw_msg.WrapReadableContent(buffer.GetRawReadBuffer() - raw_data_size, raw_data_size);
            return true;
        }
        else
        {
            msg.Clear();
            if (0 == ret)
            {
                buffer.SetReadIndex(mark_read_index);
            }
            return false;
        }
    }
    buffer.SetReadIndex(mark_read_index);
    return false;
}
Example #3
0
int RedisCommandDecoder::ProcessInlineBuffer(Buffer& buffer, RedisCommandFrame& frame)
{
    int index = buffer.IndexOf(kCRLF, 2);
    if (-1 == index)
    {
        return 0;
    }
    while (true)
    {
        char ch;
        if (!buffer.ReadByte(ch))
        {
            break;
        }
        if (ch == ' ')
        {
            continue;
        }
        buffer.AdvanceReadIndex(-1);
        int current = buffer.GetReadIndex();
        if (current == index)
        {
            buffer.AdvanceReadIndex(2); //skip "\r\n"
            break;
        }
        int space_index = buffer.IndexOf(" ", 1, current, index);
        if (-1 == space_index)
        {
            break;
        }
        frame.FillNextArgument(buffer, space_index - current);
        buffer.AdvanceReadIndex(1); //skip space char
    }
    int current = buffer.GetReadIndex();
    if (current < index)
    {
        frame.FillNextArgument(buffer, index - current);
        buffer.AdvanceReadIndex(2); //skip "\r\n"
    }
    return 1;
}
Example #4
0
 inline void FillNextArgument(Buffer& buf, size_t len)
 {
     const char* str = buf.GetRawReadBuffer();
     buf.AdvanceReadIndex(len);
     if (m_cmd_seted)
     {
         m_args.push_back(std::string(str, len));
     }
     else
     {
         m_cmd.append(str, len);
         m_cmd_seted = true;
     }
 }
Example #5
0
int RedisCommandFrame::EncodeRawProtocol(Buffer& buf)
{
    if (m_is_inline)
    {
        ArgumentArray::iterator it = m_args.begin();
        while (it != m_args.end())
        {
            Buffer* arg = *it;
            uint32 datalen = arg->ReadableBytes();
            buf.Write(arg, datalen);
            arg->AdvanceReadIndex(0-datalen);
            it++;
            if (it != m_args.end())
            {
                buf.Printf(" ");
            }
        }
        buf.Write("\r\n", 2);
        return 0;
    }
    else
    {
        buf.Printf("*%d\r\n", m_args.size());
        ArgumentArray::iterator it = m_args.begin();
        while (it != m_args.end())
        {
            Buffer* arg = *it;
            uint32 datalen = arg->ReadableBytes();
            buf.Printf("$%d\r\n", datalen);
            buf.Write(arg, datalen);
            buf.Write("\r\n", 2);
            arg->AdvanceReadIndex(0-datalen);
            it++;
        }
        return 0;
    }
}
Example #6
0
bool RedisCommandDecoder::Decode(ChannelHandlerContext& ctx, Channel* channel, Buffer& buffer, RedisCommandFrame& msg)
{
    bool have_empty = false;
    while (buffer.Readable() && (buffer.GetRawReadBuffer()[0] == '\r' || buffer.GetRawReadBuffer()[0] == '\n'))
    {
        buffer.AdvanceReadIndex(1);
        have_empty = true;
    }
    if(!m_ignore_empty && have_empty)
    {
        msg.Clear();
        return true;
    }
    return Decode(channel, buffer, msg);
}
Example #7
0
static inline int readBulkLen(Buffer& buffer, int& len)
{
    char *eptr = NULL;
    const char* raw = buffer.GetRawReadBuffer();
    int tmp = strtol(raw, &eptr, 10);
    if ((eptr - raw) > (buffer.ReadableBytes() - 2))
    {
        return 0;
    }
    if (*eptr != '\r' || *(eptr + 1) != '\n')
    {
        return -1;
    }
    len = tmp;
    buffer.AdvanceReadIndex(eptr - raw + 2);
    return 1;
}
Example #8
0
int RedisCommandFrame::EncodeToBuffer(Buffer& buf)
{
    char ch = m_is_inline ? 1 : 0;
    buf.WriteByte(ch);
    size_t size = m_args.size();
    BufferHelper::WriteFixUInt32(buf, size);
    ArgumentArray::iterator it = m_args.begin();
    while (it != m_args.end())
    {
        Buffer* item = *it;
        size_t datalen = item->ReadableBytes();
        BufferHelper::WriteFixUInt32(buf, datalen);
        buf.Write(item, datalen);
        item->AdvanceReadIndex(0 - datalen);
        it++;
    }
    return 0;
}
Example #9
0
FrameDecodeResult<RedisCommandFrame> RedisFrameDecoder::Decode(
    ChannelHandlerContext& ctx, Channel* channel, Buffer& buffer)
{
    int reqtype = -1;
    size_t mark_read_index = buffer.GetReadIndex();
    char ch;
    if (buffer.ReadByte(ch))
    {
        RedisCommandFrame* frame = NULL;
        NEW(frame, RedisCommandFrame);
        int ret = -1;
        if (ch == '*')
        {
            reqtype = REDIS_REQ_MULTIBULK;
            frame->m_is_inline = false;
            ret = ProcessMultibulkBuffer(ctx, buffer, frame);
        }
        else
        {
            reqtype = REDIS_REQ_INLINE;
            frame->m_is_inline = true;
            buffer.AdvanceReadIndex(-1);
            ret = ProcessInlineBuffer(ctx, buffer, frame);
        }
        if (ret > 0)
        {
            return FrameDecodeResult<RedisCommandFrame> (frame,
                    StandardDestructor<RedisCommandFrame> );
        }
        else
        {
            DELETE(frame);
            if (0 == ret)
            {
                buffer.SetReadIndex(mark_read_index);
            }
            return FrameDecodeResult<RedisCommandFrame> ();
        }

    }
    return FrameDecodeResult<RedisCommandFrame> ();
}
Example #10
0
int FastRedisCommandDecoder::ProcessMultibulkBuffer(Buffer& buffer, std::string& err)
{
    const char *newline = NULL;
    int pos = 0, ok;
    int64_t ll;
    //const char* querybuf = buffer.GetRawReadBuffer();
    if (m_multibulklen == 0)
    {
        m_cmd.Clear();
        m_argc = 0;
        /* Multi bulk length cannot be read without a \r\n */
        newline = strchr(buffer.GetRawReadBuffer(), '\r');
        if (newline == NULL)
        {
            if (buffer.ReadableBytes() > REDIS_INLINE_MAX_SIZE)
            {
                err = "Protocol error: too big mbulk count string";
                return -1;
            }
            return 0;
        }
        /* Buffer should also contain \n */
        if (newline - buffer.GetRawReadBuffer() > (buffer.ReadableBytes() - 2))
            return 0;

        /* We know for sure there is a whole line since newline != NULL,
         * so go ahead and find out the multi bulk length. */

        ok = string2ll(buffer.GetRawReadBuffer() + 1, newline - (buffer.GetRawReadBuffer() + 1), &ll);
        if (!ok || ll > 1024 * 1024)
        {
            err = "Protocol error: invalid multibulk length";
            return -1;
        }

        pos = (newline - buffer.GetRawReadBuffer()) + 2;
        if (ll <= 0)
        {
            buffer.AdvanceReadIndex(pos);
            return 1;
        }
        m_multibulklen = ll;
        m_cmd.ReserveArgs(ll);
    }

    while (m_multibulklen)
    {
        /* Read bulk length if unknown */
        if (m_bulklen == -1)
        {
            newline = strchr(buffer.GetRawReadBuffer() + pos, '\r');
            if (newline == NULL)
            {
                if (buffer.ReadableBytes() > REDIS_INLINE_MAX_SIZE)
                {
                    err = "Protocol error: too big bulk count string";
                    return -1;
                }
                break;
            }

            /* Buffer should also contain \n */
            if (newline - buffer.GetRawReadBuffer() > (buffer.ReadableBytes() - 2))
                break;

            if (buffer.GetRawReadBuffer()[pos] != '$')
            {
                err = "Protocol error: expected '$', got '%c'";
                //err = "Protocol error: expected '$', got '%c'", c->querybuf[pos];
                return -1;
            }

            ok = string2ll(buffer.GetRawReadBuffer() + pos + 1, newline - (buffer.GetRawReadBuffer() + pos + 1), &ll);
            if (!ok || ll < 0 || ll > 512 * 1024 * 1024)
            {
                err = "Protocol error: invalid bulk length";
                return -1;
            }

            pos += newline - (buffer.GetRawReadBuffer() + pos) + 2;
            m_bulklen = ll;
        }

        /* Read bulk argument */
        if (buffer.ReadableBytes() - pos < (unsigned) (m_bulklen + 2))
        {
            /* Not enough data (+2 == trailing \r\n) */
            break;
        }
        else
        {
            /* Optimization: if the buffer contains JUST our bulk element
             * instead of creating a new object by *copying* the sds we
             * just use the current sds string. */
            std::string* arg = m_cmd.GetMutableArgument(m_argc++);
            arg->assign(buffer.GetRawReadBuffer() + pos, m_bulklen);
            pos += m_bulklen + 2;
            m_bulklen = -1;
            m_multibulklen--;
        }
    }
    /* Trim to pos */
    if (pos)
    {
        buffer.AdvanceReadIndex(pos);
    }

    /* We're done when c->multibulk == 0 */
    if (m_multibulklen == 0)
    {
        m_cmd.Adapt();
        m_argc = 0;

        return 1;
    }
    return 0;

}
Example #11
0
int RedisCommandDecoder::ProcessMultibulkBuffer(Channel* channel, Buffer& buffer, RedisCommandFrame& frame)
{
    if (buffer.ReadableBytes() < 3)  //at least  '0\r\n'
    {
        return 0;
    }
    int multibulklen = 0;
    int read_len_ret = readBulkLen(buffer, multibulklen);
    if (read_len_ret == 0)
    {
        return 0;
    }
    else if (read_len_ret < 0)
    {
        THROW_DECODE_EX("Protocol error: expected CRLF at bulk length end");
        return -1;
    }
    if (multibulklen > 512 * 1024 * 1024)
    {
        THROW_DECODE_EX("Protocol error: invalid multibulk length");
        return -1;
    }
    int parsed_args = 0;
    while (parsed_args < multibulklen)
    {
        if (buffer.ReadableBytes() < 4)  //at least '$0\r\n'
        {
            return 0;
        }
        char expected = 0;
        buffer.ReadByte(expected);
        if (expected != '$')
        {
            if (NULL != channel)
            {
                char temp[100];
                sprintf(temp, "Protocol error: expected '$', , got '%c'", buffer.GetRawReadBuffer()[0]);
                THROW_DECODE_EX(temp);
            }
            return -1;
        }
        int arglen = 0;
        read_len_ret = readBulkLen(buffer, arglen);
        if (read_len_ret == 0)
        {
            return 0;
        }
        else if (read_len_ret < 0)
        {
            THROW_DECODE_EX("Protocol error: expected CRLF at bulk length end");
            return -1;
        }
        if (arglen > 512 * 1024 * 1024)
        {
            THROW_DECODE_EX("Protocol error: invalid bulk length");
            return -1;
        }
        if (buffer.ReadableBytes() < (arglen + 2))
        {
            return 0;
        }
        if (buffer.GetRawReadBuffer()[arglen] != '\r' || buffer.GetRawReadBuffer()[arglen + 1] != '\n')
        {
            THROW_DECODE_EX("Protocol error: expected CRLF at bulk end.");
            return -1;
        }
        frame.FillNextArgument(buffer, arglen);
        buffer.AdvanceReadIndex(2);
        parsed_args++;
    }
    return 1;
}