static int l_etable_add(lua_State *L) { struct aura_export_table *tbl; const char *name, *arg, *ret; TRACE(); aura_check_args(L, 4); if (!lua_islightuserdata(L, 1)) aura_typeerror(L, 1, "ludata"); if (!lua_isstring(L, 2)) aura_typeerror(L, 1, "string"); if (!lua_isstring(L, 3)) aura_typeerror(L, 1, "string"); if (!lua_isstring(L, 4)) aura_typeerror(L, 1, "string"); tbl = lua_touserdata(L, 1); name = lua_tostring(L, 2); arg = lua_tostring(L, 3); ret = lua_tostring(L, 4); aura_etable_add(tbl, name, arg, ret); return 0; }
/*** Setup the callback for node status change notifications. @function aura.status_cb @tparam node node The node that we want to get status notifications about @tparam function callback the function to call when status change occurs @param arg user argument to pass to the callback */ static int l_set_status_change_cb(lua_State *L) { struct laura_node *lnode; struct aura_node *node; TRACE(); aura_check_args(L, 3); lnode = lua_fetch_node(L, 1); if (!lnode) return luaL_error(L, "Failed to retrieve node"); node = lnode->node; if (!lua_isfunction(L, 2)) aura_typeerror(L, 2, "function"); if (lnode->refs & REF_STATUS_CB) { luaL_unref(L, LUA_REGISTRYINDEX, lnode->status_changed_arg_ref); luaL_unref(L, LUA_REGISTRYINDEX, lnode->status_changed_ref); } lnode->refs |= REF_STATUS_CB; lnode->status_changed_arg_ref = luaL_ref(L, LUA_REGISTRYINDEX); lnode->status_changed_ref = luaL_ref(L, LUA_REGISTRYINDEX); aura_status_changed_cb(node, status_cb, lnode); return 0; }
static int l_set_node_container(lua_State *L) { struct laura_node *lnode; TRACE(); aura_check_args(L, 2); if (!lua_isuserdata(L, 1)) aura_typeerror(L, 1, "udata"); if (!lua_istable(L, 2)) aura_typeerror(L, 2, "table"); lnode = lua_touserdata(L, 1); lnode->node_container = luaL_ref(L, LUA_REGISTRYINDEX); lnode->refs |= REF_NODE_CONTAINER; aura_unhandled_evt_cb(lnode->node, event_cb, lnode); return 0; }
static int l_etable_create(lua_State *L) { struct aura_node *node; int count = 0; struct aura_export_table *tbl; TRACE(); aura_check_args(L, 2); if (!lua_islightuserdata(L, 1)) aura_typeerror(L, 1, "ludata"); if (!lua_isnumber(L, 2)) aura_typeerror(L, 1, "number"); node = lua_touserdata(L, 1); count = lua_tonumber(L, 2); tbl = aura_etable_create(node, count); if (!tbl) return luaL_error(L, "error creating etable for %d elements", count); lua_pushlightuserdata(L, tbl); return 1; }
static int l_etable_activate(lua_State *L) { struct aura_export_table *tbl; TRACE(); aura_check_args(L, 1); if (!lua_islightuserdata(L, 1)) aura_typeerror(L, 1, "ludata"); tbl = lua_touserdata(L, 1); aura_etable_activate(tbl); return 0; }
/*** Run the event processing loop and dispatch callbacks. @function aura.eventloop_dispatch @param loop [loop] eventloop instance @param flags [number, optional] bitmask of the following flags aura.EVTLOOP_ONCE and aura.EVTLOOP_NONBLOCK */ static int l_eventloop_dispatch(lua_State *L) { struct laura_eventloop *lloop; int flags = 0; TRACE(); aura_check_args(L, 1); if (!lua_isuserdata(L, 1)) aura_typeerror(L, 1, "ludata"); lloop = lua_touserdata(L, 1); if (lua_gettop(L) == 2) flags = lua_tonumber(L, 2); aura_eventloop_dispatch(lloop->loop, flags); return 0; }
static int l_eventloop_add(lua_State *L) { struct laura_node *lnode; struct laura_eventloop *lloop; TRACE(); aura_check_args(L, 2); if (!lua_isuserdata(L, 1)) aura_typeerror(L, 1, "ludata (eventloop)"); lnode = lua_fetch_node(L, 2); lloop = lua_touserdata(L, 1); if (!lloop || !lnode) return luaL_error(L, "Failed to retrive arguments"); aura_eventloop_add(lloop->loop, lnode->node); return 0; }
static int l_eventloop_destroy(lua_State *L) { struct laura_eventloop *lloop; TRACE(); aura_check_args(L, 1); if (!lua_isuserdata(L, 1)) aura_typeerror(L, 2, "ludata (eventloop)"); lloop = lua_touserdata(L, 1); if (!lloop) return luaL_error(L, "Failed to retrive arguments"); if (!lloop->loop) return 0; aura_eventloop_destroy(lloop->loop); lloop->loop = NULL; return 0; }
/*** Terminate the event processing loop (Internal). Do not call this functuion directly. @see eventloop.loopexit The timeout is given in seconds, fractions of seconds are welcome. Zero timeout or omitting the second argument will cause immediate eventloop termination. ProTIP: You can call this function BEFORE aura.eventloop_dispatch() @function aura.eventloop_loopexit @param loop [loop] eventloop instance @param timeout [number, optional] if specified, the eventloop will be terminated after timeout number of seconds. If no timeout given - the eventloop will be stop immediately. */ static int l_eventloop_loopexit(lua_State *L) { TRACE(); struct laura_eventloop *lloop; aura_check_args(L, 1); struct timeval tv; if (!lua_isuserdata(L, 1)) aura_typeerror(L, 1, "ludata"); lloop = lua_touserdata(L, 1); if (lua_isnumber(L,2)) { lua_totimeout(L, 2, &tv); } else { tv.tv_sec = 0; tv.tv_usec = 0; } aura_eventloop_loopexit(lloop->loop, &tv); return 0; }
/*** Terminate the event processing loop (Internal). Do not call this functuion directly. @see eventloop.loopexit The timeout is given in seconds, fractions of seconds are welcome. Zero timeout or omitting the second argument will cause immediate eventloop termination. ProTIP: You can call this function BEFORE aura.eventloop_dispatch() @function aura.eventloop_loopexit @param loop [loop] eventloop instance @param timeout [number, optional] if specified, the eventloop will be terminated after timeout number of seconds. If no timeout given - the eventloop will be stop immediately. */ static int l_eventloop_loopexit(lua_State *L) { TRACE(); struct laura_eventloop *lloop; double timeout; aura_check_args(L, 1); struct timeval tv; if (!lua_isuserdata(L, 1)) aura_typeerror(L, 1, "ludata"); lloop = lua_touserdata(L, 1); if (lua_gettop(L) == 2) { timeout = lua_tonumber(L, 2); tv.tv_sec = floor(timeout); tv.tv_usec = (timeout - tv.tv_sec) * 1000000; } else { tv.tv_sec = 0; tv.tv_usec = 0; } aura_eventloop_loopexit(lloop->loop, &tv); return 0; }
static int laura_do_async_call(lua_State *L) { struct laura_node *lnode = NULL; const char *name; struct aura_buffer *buf; struct aura_object *o; int ret; int callback_ref; TRACE(); /* Sanity */ lnode = lua_fetch_node(L, 1); if (!lnode) { lua_stackdump(L); return aura_typeerror(L, 1, "userdata (node)"); } if (!lua_isstring(L, 2)) { lua_stackdump(L); return aura_typeerror(L, 2, "string (object name)"); } if (!lua_isfunction(L, 3)) { lua_stackdump(L); return aura_typeerror(L, 3, "function (callback)"); } name = lua_tostring(L, 2); o = aura_etable_find(lnode->node->tbl, name); if (!o) return luaL_error(L, "Attempt to call non-existend method"); if (!object_is_method(o)) { lua_stackdump(L); return luaL_error(L, "Attempt to call an event"); } /* Now we're sane! */ buf = lua_to_buffer(L, lnode->node, 5, o); if (!buf) return luaL_error(L, "Serializer failed!"); /* Let's create a table to store our callback and arg */ lua_newtable(L); /* Push the callback function there */ lua_pushnumber(L, 1); lua_pushvalue(L, 3); lua_settable(L, -3); /* And the user argument */ lua_pushnumber(L, 2); lua_pushvalue(L, 4); lua_settable(L, -3); /* And fetch the reference to out table that we'll use in callback */ callback_ref = luaL_ref(L, LUA_REGISTRYINDEX); slog(4, SLOG_DEBUG, "Callback tbl reference: %d", callback_ref); ret = aura_core_start_call(lnode->node, o, calldone_cb, (void *)(long)callback_ref, buf); if (ret != 0) { aura_buffer_release(buf); return luaL_error(L, "Async call for %s failed: %s code (%d)", o->name, strerror(-ret), ret); } return 0; }