Modules: expose real client on conn events.

When REDISMODULE_EVENT_CLIENT_CHANGE events are delivered, modules may
want to mutate the client state (e.g. perform authentication).

This change links the module context with the real client rather than a
fake client for these events.
This commit is contained in:
Yossi Gottlieb 2020-08-18 17:16:08 +03:00
parent cfccfbd6f4
commit 67b43f75e2

View File

@ -7264,6 +7264,7 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) {
* cheap if there are no registered modules. */ * cheap if there are no registered modules. */
if (listLength(RedisModule_EventListeners) == 0) return; if (listLength(RedisModule_EventListeners) == 0) return;
int real_client_used = 0;
listIter li; listIter li;
listNode *ln; listNode *ln;
listRewind(RedisModule_EventListeners,&li); listRewind(RedisModule_EventListeners,&li);
@ -7273,7 +7274,15 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) {
RedisModuleCtx ctx = REDISMODULE_CTX_INIT; RedisModuleCtx ctx = REDISMODULE_CTX_INIT;
ctx.module = el->module; ctx.module = el->module;
if (ModulesInHooks == 0) { if (eid == REDISMODULE_EVENT_CLIENT_CHANGE) {
/* In the case of client changes, we're pushing the real client
* so the event handler can mutate it if needed. For example,
* to change its authentication state in a way that does not
* depend on specific commands executed later.
*/
ctx.client = (client *) data;
real_client_used = 1;
} else if (ModulesInHooks == 0) {
ctx.client = moduleFreeContextReusedClient; ctx.client = moduleFreeContextReusedClient;
} else { } else {
ctx.client = createClient(NULL); ctx.client = createClient(NULL);
@ -7326,7 +7335,7 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) {
el->module->in_hook--; el->module->in_hook--;
ModulesInHooks--; ModulesInHooks--;
if (ModulesInHooks != 0) freeClient(ctx.client); if (ModulesInHooks != 0 && !real_client_used) freeClient(ctx.client);
moduleFreeContext(&ctx); moduleFreeContext(&ctx);
} }
} }