add Lua bindings for ubus events
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.remy@gmail.com>
This commit is contained in:
parent
a9ee3ef0cf
commit
8ea9667036
3 changed files with 109 additions and 1 deletions
12
lua/test.lua
12
lua/test.lua
|
@ -39,4 +39,16 @@ local my_method = {
|
|||
}
|
||||
|
||||
conn:add(my_method)
|
||||
|
||||
local my_event = {
|
||||
test = function(msg)
|
||||
print("Call to test event")
|
||||
for k, v in pairs(msg) do
|
||||
print("key=" .. k .. " value=" .. tostring(v))
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
conn:listen(my_event)
|
||||
|
||||
uloop.run()
|
||||
|
|
|
@ -36,4 +36,6 @@ for a = 1, #status do
|
|||
end
|
||||
end
|
||||
|
||||
conn:send("test", { foo = "bar"})
|
||||
|
||||
uloop.run()
|
||||
|
|
96
lua/ubus.c
96
lua/ubus.c
|
@ -17,7 +17,7 @@
|
|||
#include <libubox/blobmsg.h>
|
||||
#include <libubox/blobmsg_json.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include <lua.h>
|
||||
|
||||
#define MODNAME "ubus"
|
||||
#define METANAME MODNAME ".meta"
|
||||
|
@ -35,6 +35,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);
|
||||
|
||||
|
@ -557,6 +562,89 @@ ubus_lua_call(lua_State *L)
|
|||
return lua_gettop(L) - top;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
struct ubus_lua_connection *c = luaL_checkudata(L, 1, METANAME);
|
||||
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 int
|
||||
ubus_lua__gc(lua_State *L)
|
||||
|
@ -580,6 +668,8 @@ static const luaL_Reg ubus[] = {
|
|||
{ "signatures", ubus_lua_signatures },
|
||||
{ "call", ubus_lua_call },
|
||||
{ "close", ubus_lua__gc },
|
||||
{ "listen", ubus_lua_listen },
|
||||
{ "send", ubus_lua_send },
|
||||
{ "__gc", ubus_lua__gc },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
@ -629,5 +719,9 @@ luaopen_ubus(lua_State *L)
|
|||
lua_createtable(L, 1, 0);
|
||||
lua_setglobal(L, "__ubus_cb");
|
||||
|
||||
/* create the event table */
|
||||
lua_createtable(L, 1, 0);
|
||||
lua_setglobal(L, "__ubus_cb_event");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue