This patch add Lua bindings for ubus events (I don't know why they were not added, can be quite convenient). It mostly mimick the style of the existing code.
With it and the ubox Lua bindings, you can now send ubus events through Lua or listen for events (you can register for multiple events at the same time). Signed-off-by: Jeff Remy <jeff.r...@gmail.com> --- lua/ubus.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/lua/ubus.c b/lua/ubus.c index 77624d7..16dc348 100644 --- a/lua/ubus.c +++ b/lua/ubus.c @@ -17,6 +17,7 @@ #include <libubox/blobmsg.h> #include <libubox/blobmsg_json.h> #include <lauxlib.h> +#include <lua.h> #define MODNAME "ubus" @@ -35,6 +36,11 @@ struct ubus_lua_object { int r; }; +struct ubus_lua_event { + struct ubus_event_handler e; + int r; +}; + static int ubus_lua_parse_blob(lua_State *L, struct blob_attr *attr, bool table); @@ -443,6 +449,7 @@ static struct ubus_object* ubus_lua_load_object(lua_State *L) return &obj->o; } + static int ubus_lua_add(lua_State *L) { struct ubus_lua_connection *c = luaL_checkudata(L, 1, METANAME); @@ -572,6 +579,95 @@ ubus_lua__gc(lua_State *L) return 0; } +static void +ubus_event_handler(struct ubus_context *ctx, struct ubus_event_handler *ev, + const char *type, struct blob_attr *msg) +{ + struct ubus_lua_event *listener = container_of(ev, struct ubus_lua_event, e); + + lua_getglobal(state, "__ubus_cb_event"); + lua_rawgeti(state, -1, listener->r); + + if (lua_isfunction(state, -1)) { + ubus_lua_parse_blob_array(state, blob_data(msg), blob_len(msg), true); + lua_call(state, 1, 0); + } + return; +} + +static struct ubus_event_handler* +ubus_lua_load_event(lua_State *L) { + struct ubus_lua_event* event = NULL; + + event = malloc(sizeof(struct ubus_lua_event)); + memset(event, 0, sizeof(struct ubus_lua_event)); + event->e.cb = ubus_event_handler; + + /* update the he callback lookup table */ + lua_getglobal(L, "__ubus_cb_event"); + lua_pushvalue(L, -2); + event->r = luaL_ref(L, -2); + lua_setfield(L, -1, lua_tostring(L, -3)); + + return &event->e; +} + +static int +ubus_lua_listen(lua_State *L) { + // Registers event listener(s). + // Expected format is conn:listen(eventMap:table) + // Event map is an associative table where the key name is the event (* possible for everything) and the value is the cb function + + // Self is the connection itself + struct ubus_lua_connection *c = luaL_checkudata(L, 1, METANAME); + + /* verify top level object */ + luaL_checktype(L, 2, LUA_TTABLE); + + /* scan each object */ + lua_pushnil(L); + while (lua_next(L, -2) != 0) { + struct ubus_event_handler *listener; + + /* check if the key is a string and the value is a method */ + if ((lua_type(L, -2) == LUA_TSTRING) && (lua_type(L, -1) == LUA_TFUNCTION)) { + listener = ubus_lua_load_event(L); + if(listener != NULL) { + ubus_register_event_handler(c->ctx, listener, lua_tostring(L, -2)); + } + } + lua_pop(L, 1); + } + return 0; +} + +static int +ubus_lua_send(lua_State *L) { + // Send an event conn:send(eventName:string, event:table) + // Self is the connection itself + struct ubus_lua_connection *c = luaL_checkudata(L, 1, METANAME); + // Event name + const char *event = luaL_checkstring(L, 2); + if(*event == 0) { + return luaL_argerror(L, 2, "no event name"); + } + // Event content convert to ubus form + luaL_checktype(L, 3, LUA_TTABLE); + blob_buf_init(&c->buf, 0); + + if (!ubus_lua_format_blob_array(L, &c->buf, true)) + { + lua_pushnil(L); + lua_pushinteger(L, UBUS_STATUS_INVALID_ARGUMENT); + return 2; + } + + // Send the event + ubus_send_event(c->ctx, event, c->buf.head); + + return 0; +} + static const luaL_Reg ubus[] = { { "connect", ubus_lua_connect }, { "objects", ubus_lua_objects }, @@ -581,6 +677,8 @@ static const luaL_Reg ubus[] = { { "call", ubus_lua_call }, { "close", ubus_lua__gc }, { "__gc", ubus_lua__gc }, + { "listen", ubus_lua_listen }, + { "send", ubus_lua_send }, { NULL, NULL }, }; @@ -628,6 +726,9 @@ luaopen_ubus(lua_State *L) /* create the callback table */ lua_createtable(L, 1, 0); lua_setglobal(L, "__ubus_cb"); + /* create the callback table */ + lua_createtable(L, 1, 0); + lua_setglobal(L, "__ubus_cb_event"); return 0; } -- 1.8.1.2 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel