This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Holger Freyther gerrit-no-reply at lists.osmocom.orgHolger Freyther has submitted this change and it was merged. Change subject: mobile: Add osmo.timeout for lua code to have timeouts ...................................................................... mobile: Add osmo.timeout for lua code to have timeouts Allow to callback into lua code after a user configured timeout. Make it only work on seconds (truncate double to int). Change-Id: I355d2f8d15aeaa13abb1c5e4a8e0c958e5faf7f3 --- M src/host/layer23/src/mobile/script_lua.c 1 file changed, 134 insertions(+), 2 deletions(-) Approvals: Harald Welte: Looks good to me, approved Jenkins Builder: Verified diff --git a/src/host/layer23/src/mobile/script_lua.c b/src/host/layer23/src/mobile/script_lua.c index b3b9c99..cd7e8bc 100644 --- a/src/host/layer23/src/mobile/script_lua.c +++ b/src/host/layer23/src/mobile/script_lua.c @@ -25,7 +25,26 @@ #include <osmocom/bb/common/osmocom_data.h> #include <osmocom/bb/common/logging.h> +#include <osmocom/bb/mobile/primitives.h> + #include <osmocom/vty/misc.h> + +struct timer_userdata { + int cb_ref; +}; + +static char lua_prim_key[] = "osmocom.org-mobile-prim"; + +static struct mobile_prim_intf *get_primitive(lua_State *L) +{ + struct mobile_prim_intf *intf; + + lua_pushlightuserdata(L, lua_prim_key); + lua_gettable(L, LUA_REGISTRYINDEX); + intf = (void *) lua_topointer(L, -1); + lua_pop(L, 1); + return intf; +} static int lua_osmo_do_log(lua_State *L, int loglevel) { @@ -75,6 +94,94 @@ { NULL, NULL }, }; +static void handle_timeout(struct mobile_prim_intf *intf, struct mobile_timer_param *param) +{ + struct timer_userdata *timer = (void *)(intptr_t) param->timer_id; + lua_State *L = intf->ms->lua_state; + int err; + + lua_rawgeti(L, LUA_REGISTRYINDEX, timer->cb_ref); + luaL_unref(L, LUA_REGISTRYINDEX, timer->cb_ref); + + err = lua_pcall(L, 0, 0, 0); + if (err) { + LOGP(DLUA, LOGL_ERROR, "lua error: %s\n", lua_tostring(L, -1)); + lua_pop(L, 1); + } +} + +static int lua_osmo_timeout(lua_State *L) +{ + struct mobile_prim *prim; + struct timer_userdata *timer; + + if(lua_gettop(L) != 2) { + lua_pushliteral(L, "Need two arguments"); + lua_error(L); + return 0; + } + + luaL_argcheck(L, lua_isnumber(L, -2), 1, "Timeout needs to be a number"); + luaL_argcheck(L, lua_isfunction(L, -1), 2, "Callback needs to be a function"); + + /* + * Create a handle to prevent the function to be GCed while we run the + * timer. Add a metatable to the object so itself will be GCed properly. + */ + timer = lua_newuserdata(L, sizeof(*timer)); + luaL_getmetatable(L, "Timer"); + lua_setmetatable(L, -2); + + lua_pushvalue(L, -2); + timer->cb_ref = luaL_ref(L, LUA_REGISTRYINDEX); + + /* Take the address of the user data... */ + prim = mobile_prim_alloc(PRIM_MOB_TIMER, PRIM_OP_REQUEST); + prim->u.timer.timer_id = (intptr_t) timer; + prim->u.timer.seconds = lua_tonumber(L, -3); + mobile_prim_intf_req(get_primitive(L), prim); + + return 1; +} + +static int lua_timer_cancel(lua_State *L) +{ + struct mobile_prim *prim; + struct timer_userdata *timer; + + luaL_argcheck(L, lua_isuserdata(L, -1), 1, "No userdata"); + timer = lua_touserdata(L, -1); + + prim = mobile_prim_alloc(PRIM_MOB_TIMER_CANCEL, PRIM_OP_REQUEST); + prim->u.timer.timer_id = (intptr_t) timer; + mobile_prim_intf_req(get_primitive(L), prim); + return 0; +} + +static const struct luaL_Reg timer_funcs[] = { + { "cancel", lua_timer_cancel }, + { "__gc", lua_timer_cancel }, + { NULL, NULL }, +}; + +static const struct luaL_Reg osmo_funcs[] = { + { "timeout", lua_osmo_timeout }, + { NULL, NULL }, +}; + +static void lua_prim_ind(struct mobile_prim_intf *intf, struct mobile_prim *prim) +{ + switch (OSMO_PRIM_HDR(&prim->hdr)) { + case OSMO_PRIM(PRIM_MOB_TIMER, PRIM_OP_INDICATION): + handle_timeout(intf, (struct mobile_timer_param *) &prim->u.timer); + break; + default: + LOGP(DLUA, LOGL_ERROR, "Unknown primitive: %d\n", OSMO_PRIM_HDR(&prim->hdr)); + }; + + msgb_free(prim->hdr.msg); +} + /* * Add functions to the global lua scope. Technically these are * included in the _G table. The following lua code can be used @@ -89,9 +196,29 @@ lua_pop(L, 1); } -static void add_runtime(lua_State *L, struct osmocom_ms *ms) +static void add_runtime(lua_State *L, struct mobile_prim_intf *intf) { add_globals(L); + + /* Add a osmo module/table. Seems an oldschool module? */ + lua_newtable(L); + luaL_setfuncs(L, osmo_funcs, 0); + lua_setglobal(L, "osmo"); + + /* Create metatables so we can GC objects... */ + luaL_newmetatable(L, "Timer"); + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); + lua_rawset(L, -3); + luaL_setfuncs(L, timer_funcs, 0); + lua_pop(L, 1); + + + /* Remember the primitive pointer... store it in the registry */ + lua_pushlightuserdata(L, lua_prim_key); + lua_pushlightuserdata(L, intf); + lua_settable(L, LUA_REGISTRYINDEX); + } static void *talloc_lua_alloc(void *ctx, void *ptr, size_t osize, size_t nsize) @@ -115,6 +242,7 @@ int script_lua_load(struct vty *vty, struct osmocom_ms *ms, const char *filename) { + struct mobile_prim_intf *intf; int err; if (ms->lua_state) @@ -124,6 +252,11 @@ return -1; luaL_openlibs(ms->lua_state); + + intf = mobile_prim_intf_alloc(ms); + intf->indication = lua_prim_ind; + add_runtime(ms->lua_state, intf); + err = luaL_loadfilex(ms->lua_state, filename, NULL); if (err) { vty_out(vty, "%% LUA load error: %s%s", @@ -132,7 +265,6 @@ return -2; } - add_runtime(ms->lua_state, ms); err = lua_pcall(ms->lua_state, 0, 0, 0); if (err) { -- To view, visit https://gerrit.osmocom.org/4839 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: merged Gerrit-Change-Id: I355d2f8d15aeaa13abb1c5e4a8e0c958e5faf7f3 Gerrit-PatchSet: 7 Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Owner: Holger Freyther <holger at freyther.de> Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org> Gerrit-Reviewer: Holger Freyther <holger at freyther.de> Gerrit-Reviewer: Jenkins Builder