diff --git a/src/networking.c b/src/networking.c index ff2d29a8..60f1b798 100644 --- a/src/networking.c +++ b/src/networking.c @@ -160,6 +160,9 @@ int prepareClientToWrite(client *c) { * handler since there is no socket at all. */ if (c->flags & CLIENT_LUA) return C_OK; + /* CLIENT REPLY OFF / SKIP handling: don't send replies. */ + if (c->flags & (CLIENT_REPLY_OFF|CLIENT_REPLY_SKIP)) return C_ERR; + /* Masters don't receive replies, unless CLIENT_MASTER_FORCE_REPLY flag * is set. */ if ((c->flags & CLIENT_MASTER) && @@ -945,10 +948,20 @@ void resetClient(client *c) { c->reqtype = 0; c->multibulklen = 0; c->bulklen = -1; + /* We clear the ASKING flag as well if we are not inside a MULTI, and * if what we just executed is not the ASKING command itself. */ if (!(c->flags & CLIENT_MULTI) && prevcmd != askingCommand) - c->flags &= (~CLIENT_ASKING); + c->flags &= ~CLIENT_ASKING; + + /* Remove the CLIENT_REPLY_SKIP flag if any so that the reply + * to the next command will be sent, but set the flag if the command + * we just processed was "CLIENT REPLY SKIP". */ + c->flags &= ~CLIENT_REPLY_SKIP; + if (c->flags & CLIENT_REPLY_SKIP_NEXT) { + c->flags |= CLIENT_REPLY_SKIP; + c->flags &= ~CLIENT_REPLY_SKIP_NEXT; + } } int processInlineBuffer(client *c) { @@ -1396,6 +1409,20 @@ void clientCommand(client *c) { sds o = getAllClientsInfoString(); addReplyBulkCBuffer(c,o,sdslen(o)); sdsfree(o); + } else if (!strcasecmp(c->argv[1]->ptr,"reply") && c->argc == 3) { + /* CLIENT REPLY ON|OFF|SKIP */ + if (!strcasecmp(c->argv[2]->ptr,"on")) { + c->flags &= ~(CLIENT_REPLY_SKIP|CLIENT_REPLY_OFF); + addReply(c,shared.ok); + } else if (!strcasecmp(c->argv[2]->ptr,"off")) { + c->flags |= CLIENT_REPLY_OFF; + } else if (!strcasecmp(c->argv[2]->ptr,"skip")) { + if (!(c->flags & CLIENT_REPLY_OFF)) + c->flags |= CLIENT_REPLY_SKIP_NEXT; + } else { + addReply(c,shared.syntaxerr); + return; + } } else if (!strcasecmp(c->argv[1]->ptr,"kill")) { /* CLIENT KILL * CLIENT KILL