/* * Copyright (c) 2009-2011, Salvatore Sanfilippo * * SPDX-FileCopyrightText: 2024 Hiredict Contributors * SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo * * SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: LGPL-3.0-or-later * */ #ifndef __HIREDICT_REDICTMODULEAPI_H__ #define __HIREDICT_REDICTMODULEAPI_H__ #include "redictmodule.h" #include "../async.h" #include "../hiredict.h" #include typedef struct redictModuleEvents { redictAsyncContext *context; RedictModuleCtx *module_ctx; int fd; int reading, writing; int timer_active; RedictModuleTimerID timer_id; } redictModuleEvents; static inline void redictModuleReadEvent(int fd, void *privdata, int mask) { (void) fd; (void) mask; redictModuleEvents *e = (redictModuleEvents*)privdata; redictAsyncHandleRead(e->context); } static inline void redictModuleWriteEvent(int fd, void *privdata, int mask) { (void) fd; (void) mask; redictModuleEvents *e = (redictModuleEvents*)privdata; redictAsyncHandleWrite(e->context); } static inline void redictModuleAddRead(void *privdata) { redictModuleEvents *e = (redictModuleEvents*)privdata; if (!e->reading) { e->reading = 1; RedictModule_EventLoopAdd(e->fd, REDICTMODULE_EVENTLOOP_READABLE, redictModuleReadEvent, e); } } static inline void redictModuleDelRead(void *privdata) { redictModuleEvents *e = (redictModuleEvents*)privdata; if (e->reading) { e->reading = 0; RedictModule_EventLoopDel(e->fd, REDICTMODULE_EVENTLOOP_READABLE); } } static inline void redictModuleAddWrite(void *privdata) { redictModuleEvents *e = (redictModuleEvents*)privdata; if (!e->writing) { e->writing = 1; RedictModule_EventLoopAdd(e->fd, REDICTMODULE_EVENTLOOP_WRITABLE, redictModuleWriteEvent, e); } } static inline void redictModuleDelWrite(void *privdata) { redictModuleEvents *e = (redictModuleEvents*)privdata; if (e->writing) { e->writing = 0; RedictModule_EventLoopDel(e->fd, REDICTMODULE_EVENTLOOP_WRITABLE); } } static inline void redictModuleStopTimer(void *privdata) { redictModuleEvents *e = (redictModuleEvents*)privdata; if (e->timer_active) { RedictModule_StopTimer(e->module_ctx, e->timer_id, NULL); } e->timer_active = 0; } static inline void redictModuleCleanup(void *privdata) { redictModuleEvents *e = (redictModuleEvents*)privdata; redictModuleDelRead(privdata); redictModuleDelWrite(privdata); redictModuleStopTimer(privdata); hi_free(e); } static inline void redictModuleTimeout(RedictModuleCtx *ctx, void *privdata) { (void) ctx; redictModuleEvents *e = (redictModuleEvents*)privdata; e->timer_active = 0; redictAsyncHandleTimeout(e->context); } static inline void redictModuleSetTimeout(void *privdata, struct timeval tv) { redictModuleEvents* e = (redictModuleEvents*)privdata; redictModuleStopTimer(privdata); mstime_t millis = tv.tv_sec * 1000 + tv.tv_usec / 1000.0; e->timer_id = RedictModule_CreateTimer(e->module_ctx, millis, redictModuleTimeout, e); e->timer_active = 1; } /* Check if Redict is compatible with the adapter. */ static inline int redictModuleCompatibilityCheck(void) { if (!RedictModule_EventLoopAdd || !RedictModule_EventLoopDel || !RedictModule_CreateTimer || !RedictModule_StopTimer) { return REDICT_ERR; } return REDICT_OK; } static inline int redictModuleAttach(redictAsyncContext *ac, RedictModuleCtx *module_ctx) { redictContext *c = &(ac->c); redictModuleEvents *e; /* Nothing should be attached when something is already attached */ if (ac->ev.data != NULL) return REDICT_ERR; /* Create container for context and r/w events */ e = (redictModuleEvents*)hi_malloc(sizeof(*e)); if (e == NULL) return REDICT_ERR; e->context = ac; e->module_ctx = module_ctx; e->fd = c->fd; e->reading = e->writing = 0; e->timer_active = 0; /* Register functions to start/stop listening for events */ ac->ev.addRead = redictModuleAddRead; ac->ev.delRead = redictModuleDelRead; ac->ev.addWrite = redictModuleAddWrite; ac->ev.delWrite = redictModuleDelWrite; ac->ev.cleanup = redictModuleCleanup; ac->ev.scheduleTimer = redictModuleSetTimeout; ac->ev.data = e; return REDICT_OK; } #endif