mirror of
https://github.com/joyieldInc/predixy.git
synced 2025-12-24 22:46:41 +08:00
supports inline command protocol for command:PING/ECHO/AUTH/SELECT
This commit is contained in:
parent
1569b57bd7
commit
345ff2c20f
@ -527,7 +527,13 @@ bool Handler::preHandleRequest(Request* req, const String& key)
|
||||
directResponse(req, Response::Pong);
|
||||
} else {
|
||||
ResponsePtr res = ResponseAlloc::create();
|
||||
res->setStr(key.data(), key.length());
|
||||
if (req->isInline()) {
|
||||
SString<Const::MaxKeyLen> k;
|
||||
RequestParser::decodeInlineArg(k, key);
|
||||
res->setStr(k.data(), k.length());
|
||||
} else {
|
||||
res->setStr(key.data(), key.length());
|
||||
}
|
||||
handleResponse(nullptr, req, res);
|
||||
}
|
||||
return true;
|
||||
@ -1400,10 +1406,14 @@ bool Handler::permission(Request* req, const String& key, Response::GenericCode&
|
||||
return true;
|
||||
}
|
||||
if (req->type() == Command::Auth) {
|
||||
SString<Const::MaxKeyLen> pw;
|
||||
if (req->isInline()) {
|
||||
RequestParser::decodeInlineArg(pw, key);
|
||||
}
|
||||
auto m = mProxy->authority();
|
||||
if (!m->hasAuth()) {
|
||||
code = Response::NoPasswordSet;
|
||||
} else if (auto auth = m->get(key)) {
|
||||
} else if (auto auth = m->get(req->isInline() ? pw : key)) {
|
||||
c->setAuth(auth);
|
||||
code = Response::Ok;
|
||||
} else {
|
||||
|
||||
@ -57,6 +57,7 @@ Request::Request():
|
||||
mType(Command::None),
|
||||
mDone(false),
|
||||
mDelivered(false),
|
||||
mInline(false),
|
||||
mFollowers(0),
|
||||
mFollowersDone(0),
|
||||
mRedirectCnt(0),
|
||||
@ -70,6 +71,7 @@ Request::Request(AcceptConnection* c):
|
||||
mType(Command::None),
|
||||
mDone(false),
|
||||
mDelivered(false),
|
||||
mInline(false),
|
||||
mFollowers(0),
|
||||
mFollowersDone(0),
|
||||
mRedirectCnt(0),
|
||||
@ -82,6 +84,7 @@ Request::Request(GenericCode code):
|
||||
mConn(nullptr),
|
||||
mDone(false),
|
||||
mDelivered(false),
|
||||
mInline(false),
|
||||
mFollowers(0),
|
||||
mFollowersDone(0),
|
||||
mRedirectCnt(0),
|
||||
@ -164,6 +167,7 @@ void Request::set(const RequestParser& p, Request* leader)
|
||||
mReq = p.request();
|
||||
}
|
||||
mKey = p.key();
|
||||
mInline = p.isInline();
|
||||
}
|
||||
|
||||
void Request::setAuth(const String& password)
|
||||
|
||||
@ -129,6 +129,10 @@ public:
|
||||
{
|
||||
return mDelivered;
|
||||
}
|
||||
bool isInline() const
|
||||
{
|
||||
return mInline;
|
||||
}
|
||||
void setDelivered()
|
||||
{
|
||||
mDelivered = true;
|
||||
@ -163,6 +167,7 @@ private:
|
||||
ResponsePtr mRes;
|
||||
bool mDone;
|
||||
bool mDelivered;
|
||||
bool mInline;
|
||||
Segment mHead; //for multi key command mget/mset/del...
|
||||
Segment mReq;
|
||||
Segment mKey;
|
||||
|
||||
@ -25,6 +25,8 @@ void RequestParser::reset()
|
||||
mStatus = Normal;
|
||||
mState = Idle;
|
||||
mInline = false;
|
||||
mEscape = false;
|
||||
mQuote = '\0';
|
||||
mArgNum = 0;
|
||||
mArgCnt = 0;
|
||||
mArgLen = 0;
|
||||
@ -92,9 +94,11 @@ RequestParser::Status RequestParser::parse(Buffer* buf, int& pos, bool split)
|
||||
mState = InlineBegin;
|
||||
mInline = true;
|
||||
}
|
||||
/* NO break */
|
||||
case InlineBegin:
|
||||
if (ch == '\r') {
|
||||
error = __LINE__;
|
||||
if (ch == '\n') {
|
||||
mState = Idle;
|
||||
//error = __LINE__;
|
||||
} else if (!isspace(ch)) {
|
||||
mReq.begin().buf = buf;
|
||||
mReq.begin().pos = pos;
|
||||
@ -107,7 +111,13 @@ RequestParser::Status RequestParser::parse(Buffer* buf, int& pos, bool split)
|
||||
if (isspace(ch)) {
|
||||
mCmd[mArgLen < Const::MaxCmdLen ? mArgLen : Const::MaxCmdLen - 1] = '\0';
|
||||
parseCmd();
|
||||
mState = ch == '\r' ? InlineLF : InlineArg;
|
||||
mArgCnt = 1;
|
||||
if (ch == '\n') {
|
||||
mArgNum = 1;
|
||||
mState = Finished;
|
||||
goto Done;
|
||||
}
|
||||
mState = InlineArgBegin;
|
||||
} else {
|
||||
if (mArgLen < Const::MaxCmdLen) {
|
||||
mCmd[mArgLen] = tolower(ch);
|
||||
@ -115,15 +125,64 @@ RequestParser::Status RequestParser::parse(Buffer* buf, int& pos, bool split)
|
||||
++mArgLen;
|
||||
}
|
||||
break;
|
||||
case InlineArg:
|
||||
if (ch == '\r') {
|
||||
mState = InlineLF;
|
||||
}
|
||||
break;
|
||||
case InlineLF:
|
||||
case InlineArgBegin:
|
||||
if (ch == '\n') {
|
||||
mArgNum = mArgCnt;
|
||||
mState = Finished;
|
||||
goto Done;
|
||||
} else if (isspace(ch)) {
|
||||
break;
|
||||
}
|
||||
if (mArgCnt == 1) {
|
||||
mKey.begin().buf = buf;
|
||||
mKey.begin().pos = pos;
|
||||
}
|
||||
mState = InlineArg;
|
||||
/* NO break */
|
||||
case InlineArg:
|
||||
if (mEscape) {
|
||||
mEscape = false;
|
||||
} else if (mQuote) {
|
||||
if (ch == mQuote) {
|
||||
mState = InlineArgEnd;
|
||||
} else if (ch == '\\') {
|
||||
mEscape = true;
|
||||
} else if (ch == '\n') {
|
||||
error = __LINE__;
|
||||
}
|
||||
} else {
|
||||
if (isspace(ch)) {
|
||||
if (mArgCnt == 1) {
|
||||
mKey.end().buf = buf;
|
||||
mKey.end().pos = pos;
|
||||
}
|
||||
++mArgCnt;
|
||||
if (ch == '\n') {
|
||||
mArgNum = mArgCnt;
|
||||
mState = Finished;
|
||||
goto Done;
|
||||
} else {
|
||||
mState = InlineArgBegin;
|
||||
}
|
||||
} else if (ch == '\'' || ch == '"') {
|
||||
mQuote = ch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case InlineArgEnd:
|
||||
if (isspace(ch)) {
|
||||
if (mArgCnt == 1) {
|
||||
mKey.end().buf = buf;
|
||||
mKey.end().pos = pos;
|
||||
}
|
||||
++mArgCnt;
|
||||
if (ch == '\n') {
|
||||
mArgNum = mArgCnt;
|
||||
mState = Finished;
|
||||
goto Done;
|
||||
} else {
|
||||
mState = InlineArgBegin;
|
||||
}
|
||||
} else {
|
||||
error = __LINE__;
|
||||
}
|
||||
@ -405,7 +464,13 @@ void RequestParser::parseCmd()
|
||||
mType = c->type;
|
||||
mCommand = c;
|
||||
if (mInline) {
|
||||
if (mType != Command::Ping) {
|
||||
switch (mType) {
|
||||
case Command::Ping:
|
||||
case Command::Echo:
|
||||
case Command::Auth:
|
||||
case Command::Select:
|
||||
break;
|
||||
default:
|
||||
mStatus = CmdError;
|
||||
logNotice("unsupport command %s in inline command protocol", c->name);
|
||||
return;
|
||||
|
||||
@ -19,8 +19,9 @@ public:
|
||||
Idle, // * or inline command
|
||||
InlineBegin,
|
||||
InlineCmd,
|
||||
InlineLF,
|
||||
InlineArgBegin,
|
||||
InlineArg,
|
||||
InlineArgEnd,
|
||||
ArgNum, // 2
|
||||
ArgNumLF, // \r\n
|
||||
CmdTag,
|
||||
@ -63,6 +64,8 @@ public:
|
||||
~RequestParser();
|
||||
Status parse(Buffer* buf, int& pos, bool split);
|
||||
void reset();
|
||||
template<int Size>
|
||||
static bool decodeInlineArg(SString<Size>& dst, const String& src);
|
||||
bool isIdle() const
|
||||
{
|
||||
return mState == Idle;
|
||||
@ -116,6 +119,8 @@ private:
|
||||
Status mStatus;
|
||||
State mState;
|
||||
bool mInline;
|
||||
bool mEscape;
|
||||
char mQuote;
|
||||
int mArgNum;
|
||||
int mArgCnt;
|
||||
int mArgLen;
|
||||
@ -123,4 +128,48 @@ private:
|
||||
int mByteCnt;
|
||||
};
|
||||
|
||||
template<int Size>
|
||||
bool RequestParser::decodeInlineArg(SString<Size>& dst, const String& src)
|
||||
{
|
||||
bool ret = true;
|
||||
bool escape = false;
|
||||
char quote = '\0';
|
||||
const char* p = src.data();
|
||||
for (int i = 0; i < src.length(); ++i, ++p) {
|
||||
char c = *p;
|
||||
if (escape) {
|
||||
if (quote == '"') {
|
||||
switch (c) {
|
||||
case 'n': c = '\n'; break;
|
||||
case 'r': c = '\r'; break;
|
||||
case 't': c = '\t'; break;
|
||||
case 'b': c = '\b'; break;
|
||||
case 'a': c = '\a'; break;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
if (!dst.append('\\')) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
escape = false;
|
||||
} else if (quote) {
|
||||
if (c == '\\') {
|
||||
escape = true;
|
||||
continue;
|
||||
} else if (c == quote) {
|
||||
quote = '\0';
|
||||
continue;
|
||||
}
|
||||
} else if (c == '"' || c == '\'') {
|
||||
quote = c;
|
||||
continue;
|
||||
}
|
||||
if (!dst.append(c)) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user