int addon_event_process_begin(struct event *evt, void *obj, struct proto_process_stack *stack, unsigned int stack_index) { struct addon_instance_priv *p = obj; // Fetch the instance table lua_State *L = addon_get_instance_and_thread(p); // Stack : self // Fetch the table associated with that event lua_pushlightuserdata(L, evt->reg); // Stack : self, evt_reg lua_gettable(L, -2); // Stack : self, evt_table if (!lua_istable(L, -1)) { pomlog(POMLOG_ERR "Listener not registered for event %s", evt->reg->info->name); return POM_ERR; } // Get the open function lua_getfield(L, -1, "begin"); // Stack : self, evt_table, open_func if (lua_isnil(L, -1)) { lua_pop(L, 3); // Stack : empty return POM_OK; } // Push self lua_pushvalue(L, -3); // Stack : self, evt_table, open_func, self // Push event if (addon_event_push(L, evt) != POM_OK) // Stack : self, evt_table, process_func, self, evt return POM_ERR; int res = addon_pcall(L, 2, 0); // Stack : self, evt_table lua_pop(L, 2); // Stack : empty return res; }
int addon_event_process_end(struct event *evt, void *obj) { struct addon_instance_priv *p = obj; lua_State *L = addon_get_instance_and_thread(p); // Stack : self // Fetch the table associated with that event lua_pushlightuserdata(L, evt->reg); lua_gettable(L, -2); // Stack : self, evt_table if (!lua_istable(L, -1)) { pomlog(POMLOG_ERR "Listener not registered for event %s", evt->reg->info->name); return POM_ERR; } // Get the open function lua_getfield(L, -1, "end"); // Stack : self, evt_table, close_func // Check if there is an end function if (lua_isnil(L, -1)) { lua_pop(L, 3); // Stack : empty return POM_OK; } // Push self lua_pushvalue(L, -3); // Stack : self, evt_table, close_func, self // Push event if (addon_event_push(L, evt) != POM_OK) // Stack : self, evt_table, process_func, self, evt return POM_ERR; int res = addon_pcall(L, 2, 0); // Stack : self, evt_table lua_pop(L, 2); // Stack : empty return res; }
int addon_output_close(void *output_priv) { struct addon_instance_priv *p = output_priv; lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self lua_getfield(p->L, -1, "close"); // Stack : self, close_func lua_pushvalue(p->L, -2); // Stack : self, close_func, self int res = addon_pcall(p->L, 1, 0); // Stack : self lua_pop(p->L, 1); // Stack : empty return res; }
int addon_output_open(void *output_priv) { struct addon_instance_priv *p = output_priv; pom_mutex_lock(&p->lock); lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self lua_getfield(p->L, -1, "open"); // Stack : self, open_func lua_pushvalue(p->L, -2); // Stack : self, open_func, self int res = addon_pcall(p->L, 1, 0); // Stack : self lua_pop(p->L, 1); // Stack : empty pom_mutex_unlock(&p->lock); return res; }
// Called from C to close a pload static int addon_output_pload_close(void *output_priv, void *pload_instance_priv) { struct addon_output_pload_priv *ppriv = pload_instance_priv; struct addon_instance_priv *p = output_priv; int res = POM_OK; pom_mutex_lock(&p->lock); // Process all the plugins attached to this pload struct addon_output_pload_plugin *tmp; for (tmp = ppriv->plugins; tmp; tmp = tmp->next) { if (tmp->is_err) continue; addon_plugin_pload_close(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv); } lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener // Get the pload_priv_table lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, pload_priv lua_gettable(p->L, -2); // Stack : self, __pload_listener, pload_priv_table if (lua_isnil(p->L, -1)) { // There is no pload_priv_table, the payload doesn't need to be processed lua_pop(p->L, 3); goto cleanup; } // Remove the payload_priv_table from __pload_listener lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, pload_priv_table, pload_priv lua_pushnil(p->L); // Stack : self, __pload_listener, pload_priv_table, pload_priv, nil lua_settable(p->L, -4); // Stack : self, __pload_listener, pload_priv_table // Get the close function lua_getfield(p->L, -2, "close"); // Stack : self, __pload_listener, pload_priv_table, close_func if (lua_isnil(p->L, -1)) { // There is no close function lua_pop(p->L, 4); // Stack : empty goto cleanup; } // Setup args lua_pushvalue(p->L, 1); // Stack : self, __pload_listener, pload_priv_table, close_func, self lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, pload_priv_table, close_func, self, pload_priv_table res = addon_pcall(p->L, 2, 0); // Stack : self, __pload_listener, pload_priv_table lua_pop(p->L, 3); // Stack : empty cleanup: pom_mutex_unlock(&p->lock); while (ppriv->plugins) { tmp = ppriv->plugins; ppriv->plugins = tmp->next; free(tmp); } free(ppriv); return res; }
// Called from C to write a pload static int addon_output_pload_write(void *output_priv, void *pload_instance_priv, void *data, size_t len) { struct addon_output_pload_priv *ppriv = pload_instance_priv; struct addon_instance_priv *p = output_priv; pom_mutex_lock(&p->lock); // First process all the plugins attached to this pload struct addon_output_pload_plugin *tmp; for (tmp = ppriv->plugins; tmp; tmp = tmp->next) { if (tmp->is_err) continue; if (addon_plugin_pload_write(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv, data, len) != POM_OK) { addon_plugin_pload_close(tmp->addon_reg, ppriv->plugin_priv, tmp->pload_priv); tmp->is_err = 1; } } lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener // Get the write function lua_getfield(p->L, -1, "write"); // Stack : self, __pload_listener, write_func // Check if there is a write function if (lua_isnil(p->L, -1)) { lua_pop(p->L, 3); // Stack : empty pom_mutex_unlock(&p->lock); return POM_OK; } // Setup args lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, write_func, self lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, write_func, self, pload_priv lua_gettable(p->L, -4); // Stack : self, __pload_listener, write_func, self, pload_priv_table if (lua_isnil(p->L, -1)) { // There is no pload_priv_table, payload doesn't need to be processed lua_pop(p->L, 5); // Stack : empty pom_mutex_unlock(&p->lock); return POM_OK; } lua_getfield(p->L, -1, "__pload_data"); // Stack : self, __pload_listener, write_func, self, pload_priv_table, pload_data // Update the pload_data addon_pload_data_update(p->L, -1, data, len); pom_mutex_unlock(&p->lock); int res = addon_pcall(p->L, 3, 1); // Stack : self, __pload_listener, result int write_res = 0; if (res == POM_OK) { if (!lua_isboolean(p->L, -1)) { pomlog(POMLOG_WARN "LUA coding error: pload write function result must be a boolean"); } else { write_res = lua_toboolean(p->L, -1); } } if (!write_res) { // Remove the pload_priv_table since it failed lua_pushlightuserdata(p->L, pload_instance_priv); // Stack : self, __pload_listener, result, pload_priv lua_pushnil(p->L); // Stack : self, __pload_listener, result, pload_priv, nil lua_settable(p->L, -4); // Stack : self, __pload_listener, result } lua_pop(p->L, 3); // Stack : empty pom_mutex_unlock(&p->lock); return POM_OK; }
// Called from C to open a pload static int addon_output_pload_open(void *obj, void **priv, struct pload *pload) { struct addon_instance_priv *p = obj; // Lock the output pom_mutex_lock(&p->lock); lua_getfield(p->L, LUA_REGISTRYINDEX, ADDON_INSTANCE); // Stack : self struct addon_output_pload_priv *ppriv = malloc(sizeof(struct addon_output_pload_priv)); if (!ppriv) { pom_mutex_unlock(&p->lock); pom_oom(sizeof(struct addon_output_pload_priv)); return POM_ERR; } memset(ppriv, 0, sizeof(struct addon_output_pload_priv)); *priv = ppriv; // Get the __pload_listener table lua_getfield(p->L, -1, "__pload_listener"); // Stack : self, __pload_listener // Get the open function lua_getfield(p->L, -1, "open"); // Stack : self, __pload_listener, open_func // Check if there is an open function if (lua_isnil(p->L, -1)) { pom_mutex_unlock(&p->lock); lua_pop(p->L, 3); // Stack : empty return POM_OK; } // Add self lua_pushvalue(p->L, -3); // Stack : self, __pload_listener, open_func, self // Create a new table for the pload priv and store it into __pload_listener lua_newtable(p->L); // Stack : self, __pload_listener, open_func, self, pload_priv_table // Add output_pload_data to it addon_pload_data_push(p->L); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_data lua_setfield(p->L, -2, "__pload_data"); // Stack : self, __pload_listener, open_func, self, pload_priv_table // Add the new priv to the __pload_listener table lua_pushlightuserdata(p->L, ppriv); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_priv lua_pushvalue(p->L, -2); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload_priv, pload_priv_table lua_settable(p->L, -6); // Stack : self, __pload_listener, open_func, self, pload_priv_table // Add the pload to the args addon_pload_push(p->L, pload, ppriv); // Stack : self, __pload_listener, open_func, self, pload_priv_table, pload // Call the open function addon_pcall(p->L, 3, 1); // Stack : self, __pload_listener, result int res = 0; if (!lua_isboolean(p->L, -1)) { pomlog(POMLOG_WARN "LUA coding error: pload open function result must be a boolean"); } else { res = lua_toboolean(p->L, -1); } if (!res) { // The payload doesn't need to be processed, remove the payload_priv_table and the __pload_data lua_pushlightuserdata(p->L, ppriv); // Stack : self, __pload_listener, result, pload_priv lua_pushnil(p->L); // Stack : self, __pload_listener, result, pload_priv, nil lua_settable(p->L, -4); // Stack : self, __pload_listener, result lua_pushnil(p->L); // Stack : self, __pload_listener, result, nil lua_setfield(p->L, -3, "__pload_data"); // Stack : self, __pload_listener, result } // Remove leftovers lua_pop(p->L, 3); // Stack : empty pom_mutex_unlock(&p->lock); return POM_OK; }