void luaCommand(redisClient *c) { //printf("LUA: %s\n", c->argv[1]->ptr); LuaFlag = PIPE_NONE_FLAG; LuaClient = c; /* used in func redisLua */ int s = luaL_dostring(Lua, c->argv[1]->ptr); if (s) { const char *x = lua_tostring(Lua, -1); lua_pop(Lua, 1); addReplySds(c, sdscatprintf(sdsempty(), "-ERR Lua error: %s \r\n", x)); return; } int lret = lua_gettop(Lua); //printf("LuaFlag: %d lret: %d\n", LuaFlag, lret); if (lua_istable(Lua, -1)) { const int len = lua_objlen(Lua, -1 ); addReplySds(c, sdscatprintf(sdsempty(), "*%d\r\n", len)); for (int i = 1; i <= len; ++i ) { lua_pushinteger(Lua, i); lua_gettable(Lua, -2); char *x = (char *)lua_tostring(Lua, -1); robj *r = _createStringObject(x); addReplyBulk(c, r); decrRefCount(r); lua_pop(Lua, 1); } lua_pop(Lua, 1); } else if (LuaFlag == PIPE_EMPTY_SET_FLAG) { addReply(c, shared.emptymultibulk); lua_pop(Lua, 1); /* pop because Pipe adds "-1" for Multi-NonRelIndxs */ } else if (!lret) { addReply(c, shared.nullbulk); } else { char *x = (char *)lua_tostring(Lua, -1); if (!x) { addReply(c, shared.nullbulk); } else { /* NOTE: if "client() is called in a lua func and the lua func then returns "+OK" it will 'correctly' returned */ if (LuaFlag == PIPE_ONE_LINER_FLAG && (*x == '-' || *x == '+' || *x == ':')) { addReplySds(c, sdscatprintf(sdsempty(), "%s\r\n", x)); } else { robj *r = _createStringObject(x); addReplyBulk(c, r); decrRefCount(r); } } lua_pop(Lua, 1); } lua_gc(Lua, LUA_GCCOLLECT, 0); }
static void sendStaticFileReply(cli *c) { robj *o; if ((o = lookupKeyRead(c->db, c->http.file)) == NULL) SEND_404 else if (o->type != REDIS_STRING) SEND_404 else { //NOTE: STATIC expire in 10 years (HARDCODED) listNode *ln; bool dfl = 0; listIter *li = listGetIterator(c->http.req_hdr, AL_START_HEAD); while((ln = listNext(li))) { // check for "deflate" two_sds *ss = ln->value; if (!strncasecmp(ss->a, "Accept-Encoding", 15)) { if (DXDB_strcasestr(ss->b, "deflate")) { dfl = 1; break; } } } listReleaseIterator(li); if (dfl) { robj *dfile = _createStringObject("DEFLATE/"); dfile->ptr = sdscatlen(dfile->ptr, c->http.file->ptr, sdslen(c->http.file->ptr)); robj *od; if ((od = lookupKeyRead(c->db, dfile)) && od->type == REDIS_STRING){ o = od; addHttpResponseHeader(sdsnew("Content-Encoding"), sdsnew("deflate")); } } addHttpResponseHeader(sdsnew("Expires"), sdsnew("Wed, 09 Jun 2021 10:18:14 GMT;")); SEND_REPLY_FROM_STRING(send_http200_reponse_header(c, sdslen(o->ptr))); addReply(c, o); } }
/* This gets called when the function "client)" gets called in Lua */ int luaCall_client(lua_State *L) { LuaFlag = PIPE_NONE_FLAG; int argc = lua_gettop(L); const char *arg1 = lua_tostring(L, 1); if (!arg1) { return redisLuaArityErr(L, NULL); } redisCommand *cmd = lookupCommand((char *)arg1); if (!cmd) { char buf[64]; snprintf(buf, 63, "-ERR Unknown command '%s'\r\n", arg1); buf[63] = '\0'; lua_pushstring(L, buf); LuaFlag = PIPE_ONE_LINER_FLAG; return 1; } else if ((cmd->arity > 0 && cmd->arity != argc) || (argc < -cmd->arity)) { return redisLuaArityErr(L, cmd->name); } if (server.maxmemory && (cmd->flags & REDIS_CMD_DENYOOM) && (zmalloc_used_memory() > server.maxmemory)) { LuaFlag = PIPE_ONE_LINER_FLAG; lua_pushstring(L, "-ERR command not allowed when used memory > 'maxmemory'\r\n"); return 1; } if (server.vm_enabled && server.vm_max_threads > 0 && blockClientOnSwappedKeys(LuaClient, cmd)) return 1; long ok = 0; /* must come before first GOTO */ redisClient *rfc = rsql_createFakeClient(); robj **rargv = zmalloc(sizeof(robj *) * argc); for (int i = 0; i < argc; i++) { char *arg = (char *)lua_tostring(L, i + 1); if (!arg) { char *lbuf = "args must be strings"; luaL_argerror (L, i, lbuf); LuaFlag = PIPE_ONE_LINER_FLAG; ok = 1; goto redis_lua_end; } rargv[i] = _createStringObject(arg); } rfc->argv = rargv; rfc->argc = argc; ok = fakeClientPipe(LuaClient, rfc, L, 0, &LuaFlag, luaLine, emptyNoop); redis_lua_end: for (int i = 0; i < argc; i++) decrRefCount(rargv[i]); zfree(rargv); rsql_freeFakeClient(rfc); return (ok > 0) ? 1 : 0; }
bool replyIfNestedErr(redisClient *c, redisClient *rfc, char *msg) { if (!respNotErr(rfc)) { listNode *ln = listFirst(rfc->reply); robj *emsg = ln->value; robj *repl = _createStringObject(msg); repl->ptr = sdscatlen(repl->ptr, emsg->ptr, sdslen(emsg->ptr)); addReply(c, repl); decrRefCount(repl); return 0; } return 1; }
static bool nonRelIndRespHandler(redisClient *c, void *x, robj *key, long *card, int b, /* variable ignored */ int n) { /* variable ignored */ x = 0; b = 0; n = 0; /* compiler warnings */ if (NriFlag == PIPE_ONE_LINER_FLAG) { char *s = key->ptr; robj *r = _createStringObject(s + 1); /* +1 skips '+','-',':' */ decrRefCount(key); key = r; } addReplyBulk(c, key); decrRefCount(key); *card = *card + 1; CurrCard++; return 1; }
static void sendLuaFuncReply(cli *c, sds file) { //printf("sendLuaFuncReply\n"); int argc; robj **rargv = NULL; if (!sdslen(file) || !strcmp(file, "/")) { argc = 2; //NOTE: rargv[0] is ignored rargv = zmalloc(sizeof(robj *) * argc); rargv[1] = _createStringObject(server.alc.WebServerIndexFunc); } else if (c->http.post && c->http.req_clen) { int urgc; sds *urgv = sdssplitlen(file, sdslen(file), "/", 1, &urgc); sds pb = c->http.post_body; sds *argv = sdssplitlen(pb, sdslen(pb), "&", 1, &argc); rargv = zmalloc(sizeof(robj *) * (argc + urgc + 1)); for (int i = 0; i < urgc; i++) { rargv[i + 1] = createStringObject(urgv[i], sdslen(urgv[i])); } for (int i = 0; i < argc; i++) { char *x = strchr(argv[i], '='); if (!x) continue; x++; rargv[i + urgc + 1] = createStringObject(x, strlen(x)); } for (int i = 0; i < urgc; i++) sdsfree(urgv[i]); zfree(urgv); zfree(argv); argc += (urgc + 1); //NOTE: rargv[0] is ignored } else { sds *argv = sdssplitlen(file, sdslen(file), "/", 1, &argc); rargv = zmalloc(sizeof(robj *) * (argc + 1)); for (int i = 0; i < argc; i++) { rargv[i + 1] = createStringObject(argv[i], sdslen(argv[i])); } for (int i = 0; i < argc; i++) sdsfree(argv[i]); zfree(argv); argc++; //NOTE: rargv[0] is ignored } if (!luafunc_call(c, argc, rargv)) { robj *resp = luaReplyToHTTPReply(server.lua); SEND_REPLY_FROM_STRING(send_http_reponse_header(c, sdslen(resp->ptr))); if (c->http.get || c->http.post) addReply(c, resp); decrRefCount(resp); } for (int i = 1; i < argc; i++) decrRefCount(rargv[i]); zfree(rargv); CLEAR_LUA_STACK }