3 Star 9 Fork 4

赵建辉/lua-eco

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
ubus.c 23.16 KB
一键复制 编辑 原始数据 按行查看 历史
赵建辉 提交于 2025-02-27 19:19 +08:00 . fix(ubus): fix lua_ubus_subscribe
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
/* SPDX-License-Identifier: MIT */
/*
* Author: Jianhui Zhao <[email protected]>
*/
#include <libubus.h>
#include <fcntl.h>
#include <math.h>
#include "eco.h"
struct eco_ubus_context {
struct eco_context *eco;
struct ubus_context ctx;
struct ev_timer tmr;
struct ev_io io;
struct {
struct ubus_request req;
struct ev_timer tmr;
lua_State *L;
bool has_data;
double timeout;
} req;
char *path;
char path_data[0];
};
struct eco_ubus_object {
struct ubus_object object;
struct ubus_object_type type;
struct ubus_method methods[0];
};
#define ECO_UBUS_CTX_MT "eco{ubus-ctx}"
static const char *obj_registry = "eco.ubus{obj}";
/* ctx_env[ptr] = userdata */
static int lua_save_obj_to_ubus_ctx(lua_State *L, void *obj)
{
lua_getuservalue(L, 1);
lua_pushlightuserdata(L, obj);
lua_pushvalue(L, -3);
lua_rawset(L, -3);
lua_settop(L, -2);
return 1;
}
static void lua_get_obj_env_from_ubus_ctx(lua_State *L, struct eco_ubus_context *ctx, void *obj)
{
lua_rawgetp(L, LUA_REGISTRYINDEX, &obj_registry);
lua_rawgetp(L, -1, ctx);
lua_getuservalue(L, -1); /* ..., reg, ctx, ctx env */
lua_pushlightuserdata(L, obj); /* ..., reg, ctx, ctx env, ptr */
lua_rawget(L, -2); /* ..., reg, ctx, ctx env, handler */
lua_getuservalue(L, -1); /* ..., reg, ctx, ctx env, handler, handler env */
lua_replace(L, -5); /* ..., handler env, ctx, ctx env, handler */
lua_pop(L, 3);
}
static void lua_get_obj_cb_from_ubus_ctx_by_idx(lua_State *L, struct eco_ubus_context *ctx,
void *obj, int idx)
{
lua_pushnil(L);
lua_get_obj_env_from_ubus_ctx(L, ctx, obj); /* ..., nil, handler env */
lua_rawgeti(L, -1, idx); /* ..., nil, handler env, func */
lua_replace(L, -3); /* ..., func, handler env */
lua_pop(L, 1); /* ..., func */
}
static void lua_get_obj_cb_from_ubus_ctx_by_str(lua_State *L, struct eco_ubus_context *ctx,
void *obj, const char *name)
{
lua_pushnil(L);
lua_get_obj_env_from_ubus_ctx(L, ctx, obj); /* ..., nil, handler env */
lua_getfield(L, -1, name); /* ..., nil, handler env, func */
lua_replace(L, -3); /* ..., func, handler env */
lua_pop(L, 1); /* ..., func */
}
static void lua_table_to_blob(lua_State *L, int index, struct blob_buf *b, bool is_array)
{
void *c;
if (!lua_istable(L, index))
return;
for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 2)) {
const char *key;
int type;
lua_pushvalue(L, -2);
lua_insert(L, -2);
key = is_array ? NULL : lua_tostring(L, -2);
type = lua_type(L, -1);
switch (type) {
case LUA_TBOOLEAN:
blobmsg_add_u8(b, key, (uint8_t)lua_toboolean(L, -1));
break;
case LUA_TNUMBER: {
if (lua_isinteger(L, -1)) {
int64_t v = lua_tointeger(L, -1);
if (v > INT32_MAX)
blobmsg_add_u64(b, key, v);
else
blobmsg_add_u32(b, key, v);
} else {
blobmsg_add_double(b, key, lua_tonumber(L, -1));
}
break;
}
case LUA_TSTRING:
case LUA_TUSERDATA:
case LUA_TLIGHTUSERDATA:
if (type == LUA_TSTRING) {
blobmsg_add_string(b, key, lua_tostring(L, -1));
} else {
const char *val = lua_tostring(L, -1);
if (val)
blobmsg_add_string(b, key, val);
}
break;
case LUA_TTABLE:
if (lua_table_is_array(L, -1)) {
c = blobmsg_open_array(b, key);
lua_table_to_blob(L, lua_gettop(L), b, true);
blobmsg_close_array(b, c);
} else {
c = blobmsg_open_table(b, key);
lua_table_to_blob(L, lua_gettop(L), b, false);
blobmsg_close_table(b, c);
}
break;
}
}
}
static void blob_to_lua_table(lua_State *L, struct blob_attr *attr, size_t len, bool is_array);
static int __blob_to_lua_table(lua_State *L, struct blob_attr *attr, bool is_array)
{
void *data;
int off = 0;
int len;
if (!blobmsg_check_attr(attr, false))
return 0;
if (!is_array && blobmsg_name(attr)[0]) {
lua_pushstring(L, blobmsg_name(attr));
off++;
}
data = blobmsg_data(attr);
len = blobmsg_data_len(attr);
switch (blob_id(attr)) {
case BLOBMSG_TYPE_BOOL:
lua_pushboolean(L, *(uint8_t *)data);
break;
case BLOBMSG_TYPE_INT16:
lua_pushinteger(L, (int16_t)be16_to_cpu(*(uint16_t *)data));
break;
case BLOBMSG_TYPE_INT32:
lua_pushinteger(L, (int32_t)be32_to_cpu(*(uint32_t *)data));
break;
case BLOBMSG_TYPE_INT64:
lua_pushinteger(L, (int64_t)be64_to_cpu(*(uint64_t *)data));
break;
case BLOBMSG_TYPE_DOUBLE: {
union {
double d;
uint64_t u64;
} v;
v.u64 = be64_to_cpu(*(uint64_t *)data);
lua_pushnumber(L, v.d);
}
break;
case BLOBMSG_TYPE_STRING:
lua_pushstring(L, data);
break;
case BLOBMSG_TYPE_ARRAY:
blob_to_lua_table(L, data, len, true);
break;
case BLOBMSG_TYPE_TABLE:
blob_to_lua_table(L, data, len, false);
break;
default:
lua_pushnil(L);
break;
}
return off + 1;
}
static void blob_to_lua_table(lua_State *L, struct blob_attr *attr, size_t len, bool is_array)
{
struct blob_attr *pos;
size_t rem = len;
int idx = 1;
int rv;
lua_newtable(L);
__blob_for_each_attr(pos, attr, rem) {
rv = __blob_to_lua_table(L, pos, is_array);
if (rv > 1)
lua_rawset(L, -3);
else if (rv > 0)
lua_rawseti(L, -2, idx++);
}
}
static int lua_ubus_close(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
if (ctx->ctx.sock.eof)
return 0;
ev_io_stop(ctx->eco->loop, &ctx->io);
ev_timer_stop(ctx->eco->loop, &ctx->req.tmr);
ubus_shutdown(&ctx->ctx);
ctx->ctx.sock.eof = true;
lua_rawgetp(L, LUA_REGISTRYINDEX, &obj_registry);
lua_pushlightuserdata(L, ctx);
lua_pushnil(L);
lua_rawset(L, -3);
lua_pop(L, 1);
return 0;
}
static void ev_io_cb(struct ev_loop *loop, ev_io *w, int revents)
{
struct eco_ubus_context *ctx = container_of(w, struct eco_ubus_context, io);
ubus_handle_event(&ctx->ctx);
}
static void req_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
struct eco_ubus_context *ctx = container_of(w, struct eco_ubus_context, req.tmr);
lua_State *L = ctx->req.L;
if (!L)
return;
ctx->req.L = NULL;
ubus_abort_request(&ctx->ctx, &ctx->req.req);
lua_pushnil(L);
lua_pushliteral(L, "timeout");
eco_resume(ctx->eco->L, L, 2);
}
static int lua_ubus_settimeout(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
double timeout = luaL_checknumber(L, 2);
ctx->req.timeout = timeout;
return 0;
}
static void reconnect_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
struct eco_ubus_context *ctx = container_of(w, struct eco_ubus_context, tmr);
if (ubus_reconnect(&ctx->ctx, ctx->path)) {
ev_timer_set(w, 1.0, 0);
ev_timer_start(loop, w);
return;
}
ev_io_init(&ctx->io, ev_io_cb, ctx->ctx.sock.fd, EV_READ);
ev_io_start(loop, &ctx->io);
}
static void ubus_connection_lost(struct ubus_context *ctx)
{
struct eco_ubus_context *c = container_of(ctx, struct eco_ubus_context, ctx);
struct ev_loop *loop = c->eco->loop;
ev_io_stop(loop, &c->io);
ev_timer_start(loop, &c->tmr);
}
static int lua_ubus_auto_reconnect(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
ctx->ctx.connection_lost = ubus_connection_lost;
return 1;
}
static void lua_ubus_call_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
struct eco_ubus_context *ctx = container_of(req, struct eco_ubus_context, req.req);
/* I don't support multiple messages */
if (ctx->req.has_data)
return;
blob_to_lua_table(ctx->req.L, blob_data(msg), blob_len(msg), false);
ctx->req.has_data = true;
}
static void lua_ubus_call_complete_cb(struct ubus_request *req, int ret)
{
struct eco_ubus_context *ctx = container_of(req, struct eco_ubus_context, req.req);
lua_State *L = ctx->req.L;
int nret = 1;
if (!L)
return;
ctx->req.L = NULL;
ev_timer_stop(ctx->eco->loop, &ctx->req.tmr);
if (ret) {
lua_pushnil(L);
lua_pushstring(L, ubus_strerror(ret));
nret++;
} else if (!ctx->req.has_data) {
lua_newtable(L);
}
eco_resume(ctx->eco->L, L, nret);
}
static int lua_ubus_call(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
const char *path = luaL_checkstring(L, 2);
const char *func = luaL_checkstring(L, 3);
struct blob_buf buf = {};
uint32_t id;
int ret;
if (ctx->req.L) {
lua_pushnil(L);
lua_pushliteral(L, "busy");
return 2;
}
if (ubus_lookup_id(&ctx->ctx, path, &id)) {
lua_pushnil(L);
lua_pushliteral(L, "not found");
return 2;
}
blob_buf_init(&buf, 0);
lua_table_to_blob(L, 4, &buf, false);
ctx->req.has_data = false;
ret = ubus_invoke_async(&ctx->ctx, id, func, buf.head, &ctx->req.req);
if (ret) {
blob_buf_free(&buf);
lua_pushnil(L);
lua_pushstring(L, ubus_strerror(ret));
return 2;
}
ctx->req.req.data_cb = lua_ubus_call_data_cb;
ctx->req.req.complete_cb = lua_ubus_call_complete_cb;
ubus_complete_request_async(&ctx->ctx, &ctx->req.req);
blob_buf_free(&buf);
ctx->req.L = L;
if (ctx->req.timeout > 0) {
ev_timer_set(&ctx->req.tmr, ctx->req.timeout, 0);
ev_timer_start(ctx->eco->loop, &ctx->req.tmr);
}
return lua_yield(L, 0);
}
static int lua_ubus_send(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
const char *event = luaL_checkstring(L, 2);
struct blob_buf buf = {};
luaL_checktype(L, 3, LUA_TTABLE);
blob_buf_init(&buf, 0);
lua_table_to_blob(L, 3, &buf, false);
ubus_send_event(&ctx->ctx, event, buf.head);
blob_buf_free(&buf);
return 0;
}
static void lua_ubus_event_handler(struct ubus_context *ctx, struct ubus_event_handler *ev,
const char *type, struct blob_attr *msg)
{
struct eco_ubus_context *c = container_of(ctx, struct eco_ubus_context, ctx);
lua_State *L = c->eco->L;
lua_get_obj_cb_from_ubus_ctx_by_idx(L, c, ev, 1);
lua_pushstring(L, type);
blob_to_lua_table(L, blob_data(msg), blob_len(msg), false);
lua_call(L, 2, 0);
}
static int lua_ubus_listen(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
const char *event = luaL_checkstring(L, 2);
struct ubus_event_handler *e;
int ret;
luaL_checktype(L, 3, LUA_TFUNCTION);
e = lua_newuserdata(L, sizeof(struct ubus_event_handler));
lua_newtable(L);
lua_pushvalue(L, 3);
lua_rawseti(L, -2, 1); /* env[1] = func */
lua_setuservalue(L, -2);
memset(e, 0, sizeof(struct ubus_event_handler));
e->cb = lua_ubus_event_handler;
ret = ubus_register_event_handler(&ctx->ctx, e, event);
if (ret) {
lua_pushnil(L);
lua_pushstring(L, ubus_strerror(ret));
return 2;
}
lua_save_obj_to_ubus_ctx(L, e);
return 1;
}
static int ubus_method_handler(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
struct eco_ubus_context *c = container_of(ctx, struct eco_ubus_context, ctx);
struct eco_ubus_object *o = container_of(obj, struct eco_ubus_object, object);
struct ubus_request_data *dreq;
lua_State *L = c->eco->L;
int rv = 0;
dreq = malloc(sizeof(struct ubus_request_data));
if (!dreq)
luaL_error(L, "no mem");
lua_settop(L, 0);
lua_get_obj_cb_from_ubus_ctx_by_str(L, c, o, method);
ubus_defer_request(ctx, req, dreq);
lua_pushlightuserdata(L, dreq);
blob_to_lua_table(L, blob_data(msg), blob_len(msg), false);
lua_call(L, 2, 1);
if (lua_isnumber(L, -1))
rv = lua_tonumber(L, -1);
lua_pop(L, 1);
return rv;
}
static int lua_ubus_load_methods(lua_State *L, struct ubus_method *m)
{
const char *name = lua_tostring(L, -2);
struct blobmsg_policy *p;
int pidx = 0, plen;
/* store function to uservalue */
lua_rawgeti(L, -1, 1);
if ((lua_type(L, -1) != LUA_TFUNCTION)) {
lua_pop(L, 1);
return 1;
}
lua_setfield(L, 5, name);
m->handler = ubus_method_handler;
m->name = name;
/* get the policy table */
lua_rawgeti(L, -1, 2);
if ((lua_type(L, -1) != LUA_TTABLE) || lua_rawlen(L, -1)) {
lua_pop(L, 1);
return 0;
}
plen = lua_gettablelen(L, -1);
/* exit if policy table is empty */
if (!plen) {
lua_pop(L, 1);
return 0;
}
/* setup the policy pointers */
p = calloc(plen, sizeof(struct blobmsg_policy));
if (!p)
return 1;
m->policy = p;
lua_pushnil(L);
while (lua_next(L, -2) != 0) {
int val = lua_tointeger(L, -1);
/* check if the policy is valid */
if ((lua_type(L, -2) != LUA_TSTRING) ||
(lua_type(L, -1) != LUA_TNUMBER) ||
(val < 0) ||
(val > BLOBMSG_TYPE_LAST)) {
lua_pop(L, 1);
continue;
}
p[pidx].name = lua_tostring(L, -2);
p[pidx].type = val;
lua_pop(L, 1);
pidx++;
}
m->n_policy = pidx;
lua_pop(L, 1);
return 0;
}
static void lua_ubus_load_object(lua_State *L, struct eco_ubus_object *o)
{
struct ubus_object *obj = &o->object;
struct ubus_object_type *type = &o->type;
struct ubus_method *methods = o->methods;
const char *name = lua_tostring(L, 2);
int midx = 0;
obj->name = name;
obj->methods = methods;
type->name = name;
type->methods = methods;
obj->type = type;
lua_pushnil(L);
while (lua_next(L, 3)) {
if ((lua_type(L, -2) != LUA_TSTRING) ||
(lua_type(L, -1) != LUA_TTABLE) ||
!lua_rawlen(L, -1)) {
lua_pop(L, 1);
continue;
}
if (!lua_ubus_load_methods(L, methods + midx))
midx++;
lua_pop(L, 1);
}
type->n_methods = obj->n_methods = midx;
}
static int lua_ubus_add(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
struct eco_ubus_object *o;
int ret, mlen;
luaL_checkstring(L, 2);
luaL_checktype(L, 3, LUA_TTABLE);
mlen = lua_gettablelen(L, 3);
o = lua_newuserdata(L, sizeof(struct eco_ubus_object) + mlen * sizeof(struct ubus_method));
memset(o, 0, sizeof(struct eco_ubus_object) + mlen * sizeof(struct ubus_method));
lua_newtable(L);
lua_ubus_load_object(L, o);
lua_setuservalue(L, -2);
ret = ubus_add_object(&ctx->ctx, &o->object);
if (ret) {
lua_pushnil(L);
lua_pushstring(L, ubus_strerror(ret));
return 2;
}
return lua_save_obj_to_ubus_ctx(L, o);
}
static int lua_ubus_reply(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
struct ubus_request_data *req = lua_touserdata(L, 2);
struct blob_buf buf = {};
luaL_checktype(L, 3, LUA_TTABLE);
blob_buf_init(&buf, 0);
lua_table_to_blob(L, 3, &buf, false);
ubus_send_reply(&ctx->ctx, req, buf.head);
blob_buf_free(&buf);
return 0;
}
static int lua_ubus_complete_deferred_request(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
struct ubus_request_data *req = lua_touserdata(L, 2);
int ret = luaL_checkinteger(L, 3);
ubus_complete_deferred_request(&ctx->ctx, req, ret);
free(req);
return 0;
}
static int ubus_subscriber_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req,const char *method, struct blob_attr *msg)
{
struct eco_ubus_context *c = container_of(ctx, struct eco_ubus_context, ctx);
struct ubus_subscriber *s = container_of(obj, struct ubus_subscriber, obj);
lua_State *L = c->eco->L;
lua_get_obj_cb_from_ubus_ctx_by_idx(L, c, s, 1);
lua_pushstring(L, method);
blob_to_lua_table(L, blob_data(msg), blob_len(msg), false);
lua_call(L, 2, 0);
return 0;
}
static int lua_ubus_subscribe(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
const char *path = luaL_checkstring(L, 2);
struct ubus_subscriber *sub;
uint32_t id;
int ret;
if (ubus_lookup_id(&ctx->ctx, path, &id)) {
lua_pushnil(L);
lua_pushliteral(L, "not found");
return 2;
}
sub = lua_newuserdata(L, sizeof(struct ubus_subscriber));
lua_newtable(L);
lua_pushvalue(L, 3);
lua_rawseti(L, -2, 1);
lua_setuservalue(L, -2);
memset(sub, 0, sizeof(struct ubus_subscriber));
sub->cb = ubus_subscriber_cb;
ret = ubus_register_subscriber(&ctx->ctx, sub);
if (ret) {
lua_pushnil(L);
lua_pushstring(L, ubus_strerror(ret));
return 2;
}
ret = ubus_subscribe(&ctx->ctx, sub, id);
if (ret) {
lua_pushnil(L);
lua_pushstring(L, ubus_strerror(ret));
return 2;
}
return lua_save_obj_to_ubus_ctx(L, sub);
}
static int lua_ubus_notify(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
struct blob_buf buf = {};
struct eco_ubus_object *obj;
const char *method;
if(!lua_isuserdata(L, 2))
return luaL_error(L, "Invald 2nd parameter, expected ubus obj ref");
obj = lua_touserdata(L, 2);
method = luaL_checkstring(L, 3);
luaL_checktype(L, 4, LUA_TTABLE);
blob_buf_init(&buf, 0);
lua_table_to_blob(L, 4, &buf, false);
ubus_notify(&ctx->ctx, &obj->object, method, buf.head, -1);
blob_buf_free(&buf);
return 0;
}
static int lua_ubus_connect(lua_State *L)
{
const char *path = luaL_optstring(L, 1, NULL);
size_t size = sizeof(struct eco_ubus_context);
struct eco_ubus_context *ctx;
if (getuid() > 0) {
lua_pushnil(L);
lua_pushliteral(L, "Operation not permitted, must be run as root");
return 2;
}
if (path)
size += strlen(path) + 1;
ctx = lua_newuserdata(L, size);
memset(ctx, 0, sizeof(struct eco_ubus_context));
if (ubus_connect_ctx(&ctx->ctx, path)) {
uloop_done();
lua_pushnil(L);
lua_pushliteral(L, "Failed to connect to ubus");
return 2;
}
uloop_done();
if (path) {
strcpy(ctx->path_data, path);
ctx->path = ctx->path_data;
}
lua_pushvalue(L, lua_upvalueindex(1));
lua_setmetatable(L, -2);
lua_newtable(L);
lua_setuservalue(L, -2);
lua_rawgetp(L, LUA_REGISTRYINDEX, &obj_registry);
lua_pushlightuserdata(L, ctx);
lua_pushvalue(L, -3);
lua_rawset(L, -3);
lua_pop(L, 1);
ctx->eco = eco_get_context(L);
ev_io_init(&ctx->io, ev_io_cb, ctx->ctx.sock.fd, EV_READ);
ev_io_start(ctx->eco->loop, &ctx->io);
ev_timer_init(&ctx->tmr, reconnect_cb, 1.0, 0);
ev_timer_init(&ctx->req.tmr, req_timeout_cb, 30.0, 0);
return 1;
}
static void lua_ubus_objects_cb(struct ubus_context *c, struct ubus_object_data *o, void *p)
{
lua_State *L = (lua_State *)p;
lua_pushinteger(L, o->id);
lua_pushstring(L, o->path);
lua_settable(L, -3);
}
static int lua_ubus_objects(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
int ret;
lua_newtable(L);
ret = ubus_lookup(&ctx->ctx, NULL, lua_ubus_objects_cb, L);
if (ret != UBUS_STATUS_OK) {
lua_pop(L, 1);
lua_pushnil(L);
lua_pushstring(L, ubus_strerror(ret));
return 2;
}
return 1;
}
static void lua_ubus_signatures_cb(struct ubus_context *c, struct ubus_object_data *o, void *p)
{
lua_State *L = (lua_State *)p;
if (!o->signature)
return;
blob_to_lua_table(L, blob_data(o->signature), blob_len(o->signature), false);
}
static int lua_ubus_signatures(lua_State *L)
{
struct eco_ubus_context *ctx = luaL_checkudata(L, 1, ECO_UBUS_CTX_MT);
const char *path = luaL_checkstring(L, 2);
int ret;
lua_newtable(L);
ret = ubus_lookup(&ctx->ctx, path, lua_ubus_signatures_cb, L);
if (ret != UBUS_STATUS_OK) {
lua_pop(L, 1);
lua_pushnil(L);
lua_pushstring(L, ubus_strerror(ret));
return 2;
}
return 1;
}
static const struct luaL_Reg ubus_methods[] = {
{"settimeout", lua_ubus_settimeout},
{"auto_reconnect", lua_ubus_auto_reconnect},
{"call", lua_ubus_call},
{"send", lua_ubus_send},
{"listen", lua_ubus_listen},
{"add", lua_ubus_add},
{"reply", lua_ubus_reply},
{"complete_deferred_request", lua_ubus_complete_deferred_request},
{"subscribe", lua_ubus_subscribe},
{"notify", lua_ubus_notify},
{"objects", lua_ubus_objects},
{"signatures", lua_ubus_signatures},
{"close", lua_ubus_close},
{"__gc", lua_ubus_close},
{NULL, NULL}
};
static int lua_ubus_strerror(lua_State *L)
{
int ret = luaL_checkinteger(L, 1);
lua_pushstring(L, ubus_strerror(ret));
return 1;
}
int luaopen_eco_core_ubus(lua_State *L)
{
lua_newtable(L);
lua_createtable(L, 0, 1);
lua_pushliteral(L, "v");
lua_setfield(L, -2, "__mode");
lua_setmetatable(L, -2);
lua_rawsetp(L, LUA_REGISTRYINDEX, &obj_registry);
lua_newtable(L);
lua_add_constant(L, "STATUS_OK", UBUS_STATUS_OK);
lua_add_constant(L, "STATUS_INVALID_COMMAND", UBUS_STATUS_INVALID_COMMAND);
lua_add_constant(L, "STATUS_INVALID_ARGUMENT", UBUS_STATUS_INVALID_ARGUMENT);
lua_add_constant(L, "STATUS_METHOD_NOT_FOUND", UBUS_STATUS_METHOD_NOT_FOUND);
lua_add_constant(L, "STATUS_NOT_FOUND", UBUS_STATUS_NOT_FOUND);
lua_add_constant(L, "STATUS_NO_DATA", UBUS_STATUS_NO_DATA);
lua_add_constant(L, "STATUS_PERMISSION_DENIED", UBUS_STATUS_PERMISSION_DENIED);
lua_add_constant(L, "STATUS_TIMEOUT", UBUS_STATUS_TIMEOUT);
lua_add_constant(L, "STATUS_NOT_SUPPORTED", UBUS_STATUS_NOT_SUPPORTED);
lua_add_constant(L, "STATUS_UNKNOWN_ERROR", UBUS_STATUS_UNKNOWN_ERROR);
lua_add_constant(L, "STATUS_CONNECTION_FAILED", UBUS_STATUS_CONNECTION_FAILED);
lua_add_constant(L, "ARRAY", BLOBMSG_TYPE_ARRAY);
lua_add_constant(L, "TABLE", BLOBMSG_TYPE_TABLE);
lua_add_constant(L, "STRING", BLOBMSG_TYPE_STRING);
lua_add_constant(L, "INT64", BLOBMSG_TYPE_INT64);
lua_add_constant(L, "INT32", BLOBMSG_TYPE_INT32);
lua_add_constant(L, "INT16", BLOBMSG_TYPE_INT16);
lua_add_constant(L, "INT8", BLOBMSG_TYPE_INT8);
lua_add_constant(L, "DOUBLE", BLOBMSG_TYPE_DOUBLE);
lua_add_constant(L, "BOOLEAN", BLOBMSG_TYPE_BOOL);
eco_new_metatable(L, ECO_UBUS_CTX_MT, ubus_methods);
lua_pushcclosure(L, lua_ubus_connect, 1);
lua_setfield(L, -2, "connect");
lua_pushcfunction(L, lua_ubus_strerror);
lua_setfield(L, -2, "strerror");
return 1;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Lua
1
https://gitee.com/zhaojh329/lua-eco.git
[email protected]:zhaojh329/lua-eco.git
zhaojh329
lua-eco
lua-eco
master

搜索帮助