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; }
int RedisCommandDecoder::ProcessMultibulkBuffer(Channel* channel, Buffer& buffer, RedisCommandFrame& frame) { int index = buffer.IndexOf(kCRLF, 2); if (-1 == index) { return 0; } char *eptr = NULL; const char* raw = buffer.GetRawReadBuffer(); int32 multibulklen = strtol(raw, &eptr, 10); if (multibulklen <= 0) { buffer.SetReadIndex(index + 2); return 1; } else if (multibulklen > 512 * 1024 * 1024) { if(NULL != channel) { APIException ex("Protocol error: invalid multibulk length"); fire_exception_caught(channel, ex); } return -1; } buffer.SetReadIndex(index + 2); while (multibulklen > 0) { int newline_index = buffer.IndexOf(kCRLF, 2); if (-1 == newline_index) { return 0; } char ch; if (!buffer.ReadByte(ch)) { return 0; } if (ch != '$') { if(NULL != channel) { char temp[100]; sprintf(temp, "Protocol error: expected '$', , got '%c'", ch); APIException ex(temp); fire_exception_caught(channel, ex); } return -1; } if (!buffer.Readable()) { return 0; } const char* raw = buffer.GetRawReadBuffer(); int32 arglen = (uint32) strtol(raw, &eptr, 10); if (eptr[0] != '\r' || arglen < 0 || arglen > 512 * 1024 * 1024) { if(NULL != channel) { APIException ex("Protocol error: invalid bulk length"); fire_exception_caught(channel, ex); } return -1; } buffer.SetReadIndex(newline_index + 2); if (!buffer.Readable()) { return 0; } if (buffer.ReadableBytes() < (uint32) (arglen + 2)) { return 0; } frame.FillNextArgument(buffer, arglen); //Buffer* arg = frame.GetNextArgument(arglen); //buffer.Read(arg, arglen); char tempchs[2]; buffer.Read(tempchs, 2); if (tempchs[0] != '\r' || tempchs[1] != '\n') { if(NULL != channel) { APIException ex("CRLF expected after argument."); fire_exception_caught(channel, ex); } return -1; } //buffer.AdvanceReadIndex(arglen + 2); multibulklen--; } return 1; }
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; }