55 #include <amxc/amxc_string_split.h>
60 struct ubus_request_data
req;
67 enum blobmsg_type converter[AMXC_VAR_ID_CUSTOM_BASE] = {
87 if(type <= AMXC_VAR_ID_ANY) {
88 return converter[type];
90 return BLOBMSG_TYPE_UNSPEC;
96 return (c ==
'.') ? 1 : 0;
100 int status[amxd_status_last] = {
102 UBUS_STATUS_UNKNOWN_ERROR,
103 UBUS_STATUS_NOT_FOUND,
104 UBUS_STATUS_METHOD_NOT_FOUND,
105 UBUS_STATUS_NOT_FOUND,
106 UBUS_STATUS_NOT_SUPPORTED,
107 UBUS_STATUS_INVALID_COMMAND,
108 UBUS_STATUS_INVALID_ARGUMENT,
109 UBUS_STATUS_INVALID_ARGUMENT,
110 UBUS_STATUS_INVALID_ARGUMENT,
111 UBUS_STATUS_INVALID_ARGUMENT,
112 UBUS_STATUS_NOT_SUPPORTED,
113 UBUS_STATUS_INVALID_ARGUMENT,
114 UBUS_STATUS_UNKNOWN_ERROR,
115 UBUS_STATUS_UNKNOWN_ERROR,
116 UBUS_STATUS_NOT_SUPPORTED,
117 UBUS_STATUS_INVALID_ARGUMENT,
118 UBUS_STATUS_UNKNOWN_ERROR,
119 UBUS_STATUS_INVALID_ARGUMENT,
120 UBUS_STATUS_UNKNOWN_ERROR,
121 UBUS_STATUS_UNKNOWN_ERROR,
122 UBUS_STATUS_NOT_FOUND,
123 UBUS_STATUS_UNKNOWN_ERROR,
126 if(rv <
sizeof(status) /
sizeof(
int)) {
129 return UBUS_STATUS_UNKNOWN_ERROR;
135 switch(amxc_var_type_of(ret)) {
136 case AMXC_VAR_ID_HTABLE:
140 case AMXC_VAR_ID_LIST: {
141 void* c = blobmsg_open_array(&amxb_ubus_ctx->
b,
"retval");
144 blobmsg_close_array(&amxb_ubus_ctx->
b, c);
156 amxc_var_t* status) {
166 amxc_var_set_type(args, AMXC_VAR_ID_HTABLE);
167 }
else if(amxc_var_type_of(args) != AMXC_VAR_ID_HTABLE) {
168 amxc_var_set_type(args, AMXC_VAR_ID_HTABLE);
183 amxc_var_take_it(args);
184 amxc_var_delete(&args);
191 amxc_var_t* ret = GET_ARG(data,
"retval");
192 amxc_var_t* args = GET_ARG(data,
"args");
193 amxc_var_t* status = GET_ARG(data,
"status");
199 amxc_llist_it_take(&fcall->
it);
206 const char* method = GET_CHAR(data,
"method");
207 const char* path = GET_CHAR(data,
"path");
208 amxc_var_t* args = GET_ARG(data,
"args");
210 amxd_status_t retval = amxd_status_ok;
213 amxd_object_t* root_obj = amxd_dm_get_root(amxb_ubus_ctx->
dm);
214 amxd_object_t* dm_obj = amxd_object_findf(root_obj,
"%s", path);
218 amxc_var_init(&status);
219 retval = amxd_object_invoke_function(dm_obj, method, args, &ret);
220 amxc_var_set(uint32_t, &status, retval);
229 amxd_function_deferred_remove(fcall->
call_id);
230 amxc_llist_it_take(&fcall->
it);
233 case amxd_status_deferred: {
234 uint64_t call_id = amxc_var_constcast(uint64_t, &ret);
235 amxd_function_deferred_remove(fcall->
call_id);
244 amxc_var_clean(&status);
245 amxc_var_clean(&ret);
262 struct ubus_object* obj,
263 struct ubus_request_data* req,
265 struct blob_attr* msg) {
266 int status = UBUS_STATUS_OK;
270 amxd_object_t* root_obj = amxd_dm_get_root(amxb_ubus_ctx->
dm);
271 amxd_object_t* dm_obj = amxd_object_findf(root_obj,
"%s", amxb_ubus_obj->
ubus_path);
272 amxd_function_t* func = amxd_object_get_function(dm_obj, method);
276 amxc_var_t* args = NULL;
277 amxc_var_init(&data);
280 when_null_status(dm_obj, exit, status = UBUS_STATUS_NOT_FOUND);
281 when_null_status(func, exit, status = UBUS_STATUS_METHOD_NOT_FOUND);
283 amxc_var_set_type(&data, AMXC_VAR_ID_HTABLE);
285 amxc_var_add_key(cstring_t, &data,
"method", method);
286 amxc_var_add_key(cstring_t, &data,
"path", amxb_ubus_obj->
ubus_path);
287 args = amxc_var_add_key(amxc_htable_t, &data,
"args", NULL);
291 amxd_function_defer(func, &fcall->
call_id, &ret, NULL, NULL);
295 ubus_defer_request(ctx, req, &fcall->
req);
300 amxc_var_clean(&data);
301 amxc_var_clean(&ret);
307 struct ubus_method* ubus_method) {
308 amxd_function_t* func = amxd_object_get_function(
object, name);
311 struct blobmsg_policy* args = NULL;
313 when_null(func, exit);
314 when_null(ubus_method, exit);
316 ubus_method->name = func->name;
319 n_args = amxc_llist_size(&func->args);
320 args = (
struct blobmsg_policy*) calloc(n_args,
sizeof(
struct blobmsg_policy));
321 when_null(args, exit);
323 amxc_llist_for_each(it, (&func->args)) {
324 amxd_func_arg_t* amxd_arg = amxc_llist_it_get_data(it, amxd_func_arg_t, it);
325 args[index].name = amxd_arg->name;
330 ubus_method->policy = args;
331 ubus_method->n_policy = n_args;
338 AMXB_UNUSED int32_t depth,
339 AMXB_UNUSED
void* priv) {
341 amxd_object_t* parent = NULL;
342 when_true(amxd_object_get_type(
object) == amxd_object_root, exit);
344 if(amxd_object_is_attr_set(
object, amxd_oattr_private)) {
349 parent = amxd_object_get_parent(
object);
350 if(amxd_object_get_type(
object) != amxd_object_instance) {
351 if(amxd_object_get_type(parent) == amxd_object_template) {
362 const amxc_var_t*
const data,
367 blob_buf_init(&amxb_ubus_ctx->
b, 0);
370 ubus_notify(amxb_ubus_ctx->
ubus_ctx,
372 sig_name, amxb_ubus_ctx->
b.head,
377 struct ubus_object* obj) {
382 amxd_object_t* root_obj = amxd_dm_get_root(amxb_ubus_ctx->
dm);
383 amxd_object_t* dm_obj = amxd_object_findf(root_obj,
"%s",
385 when_null(dm_obj, exit);
387 if(amxb_ubus_obj->
ubus_obj.has_subscribers) {
388 amxc_string_t expression;
389 char* path = amxd_object_get_path(dm_obj, AMXD_OBJECT_INDEXED);
391 amxc_string_init(&expression, 0);
392 amxc_string_appendf(&expression,
"path starts with \"%s.\"", path);
393 amxp_slot_connect_filtered(&amxb_ubus_ctx->
dm->sigmngr,
395 amxc_string_get(&expression, 0),
398 amxc_string_clean(&expression);
401 amxp_slot_disconnect_with_priv(&amxb_ubus_ctx->
dm->sigmngr,
412 amxd_object_t*
const object) {
413 struct ubus_method* methods = NULL;
414 const amxc_llist_t* lfuncs = NULL;
417 amxc_var_init(&funcs);
421 obj->
ubus_path = amxd_object_get_path(
object, AMXD_OBJECT_INDEXED);
423 amxd_object_list_functions(
object, &funcs, amxd_dm_access_protected);
424 lfuncs = amxc_var_constcast(amxc_llist_t, &funcs);
427 obj->
ubus_obj.n_methods = amxc_llist_size(lfuncs);
429 methods = (
struct ubus_method*) calloc(obj->
ubus_obj.n_methods,
sizeof(
struct ubus_method));
437 amxc_llist_for_each(it, lfuncs) {
438 const char* func_name = amxc_var_constcast(cstring_t, amxc_var_from_llist_it(it));
445 amxc_var_clean(&funcs);
449 AMXB_UNUSED int32_t depth,
454 when_true(object->type == amxd_object_root, exit);
457 when_null(obj, exit);
458 obj->
ubus_obj.type = (
struct ubus_object_type*) calloc(1,
sizeof(
struct ubus_object_type));
465 if(ubus_add_object(amxb_ubus_ctx->
ubus_ctx, &obj->
ubus_obj) != UBUS_STATUS_OK) {
477 const amxc_var_t*
const data,
480 amxd_object_t*
object = amxd_dm_signal_get_object(amxb_ubus_ctx->
dm, data);
482 if(strcmp(sig_name,
"dm:instance-added") == 0) {
483 uint32_t index = amxc_var_constcast(uint32_t,
484 amxc_var_get_key(data,
"index", 0));
485 object = amxd_object_get_instance(
object, NULL, index);
494 const amxc_var_t*
const data,
497 amxd_object_t*
object = amxd_dm_signal_get_object(amxb_ubus_ctx->
dm, data);
501 amxd_object_hierarchy_walk(
object,
511 const amxc_var_t*
const data,
514 amxd_dm_t*
dm = amxb_ubus_ctx->
dm;
515 const char* object_path = GET_CHAR(data,
"path");
516 amxc_string_t full_path;
518 amxc_string_init(&full_path, 0);
519 if(strcmp(sig_name,
"dm:instance-removed") == 0) {
520 uint32_t index = amxc_var_constcast(uint32_t,
521 amxc_var_get_key(data,
"index", 0));
522 amxc_string_setf(&full_path,
"%s%d", object_path, index);
524 amxc_string_setf(&full_path,
"%s", object_path);
525 amxc_string_trimr(&full_path,
isdot);
532 if(strcmp(obj->
ubus_obj.name, amxc_string_get(&full_path, 0)) == 0) {
540 amxc_string_clean(&full_path);
544 UNUSED
const amxc_var_t*
const data,
547 amxd_dm_t*
dm = amxb_ubus_ctx->
dm;
549 amxd_object_hierarchy_walk(amxd_dm_get_root(
dm),
558 amxp_slot_connect(&
dm->sigmngr,
564 amxp_slot_connect(&
dm->sigmngr,
570 amxp_slot_connect(&
dm->sigmngr,
575 amxp_slot_connect(&
dm->sigmngr,
580 amxp_slot_connect(&
dm->sigmngr,
585 amxp_slot_connect(&
dm->sigmngr,
586 "dm:instance-removed",
597 blob_buf_init(&amxb_ubus_ctx->
b, 0);
599 ubus_send_reply(amxb_ubus_ctx->
ubus_ctx, &fcall->
req, amxb_ubus_ctx->
b.head);
601 ubus_complete_deferred_request(amxb_ubus_ctx->
ubus_ctx,
603 UBUS_STATUS_UNKNOWN_ERROR);
605 amxd_function_set_deferred_cb(fcall->
call_id, NULL, NULL);
606 amxd_function_deferred_remove(fcall->
call_id);
607 amxc_llist_it_take(it);
611 amxc_var_clean(&ret);
618 struct ubus_method* methods = (
struct ubus_method*) obj->
ubus_obj.methods;
620 amxc_llist_it_take(it);
621 for(
int i = 0; i < obj->
ubus_obj.n_methods; i++) {
622 struct blobmsg_policy* policy =
623 (
struct blobmsg_policy*) methods[i].policy;
625 methods[i].policy = NULL;
640 amxd_dm_t*
const dm) {
641 int status = UBUS_STATUS_UNKNOWN_ERROR;
645 when_not_null(amxb_ubus_ctx->
dm, exit);
646 amxb_ubus_ctx->
dm =
dm;
648 if(amxc_var_dyncast(
bool, cfg_ros)) {
649 amxp_slot_connect(&
dm->sigmngr,
658 status = UBUS_STATUS_OK;
int PRIVATE amxb_ubus_format_blob_array(const amxc_llist_t *list, struct blob_buf *b)
int PRIVATE amxb_ubus_format_blob_table(const amxc_htable_t *table, struct blob_buf *b)
const amxc_var_t * amxb_ubus_get_config_option(const char *name)
int PRIVATE amxb_ubus_format_blob(amxc_var_t *data, const char *key, struct blob_buf *b)
int PRIVATE amxb_ubus_parse_blob_table(amxc_var_t *var, struct blob_attr *attr, int len)
void PRIVATE amxb_ubus_obj_it_free(amxc_llist_it_t *it)
static void amxb_ubus_register_object(amxd_object_t *const object, AMXB_UNUSED int32_t depth, void *priv)
static void amxb_ubus_register_dm(UNUSED const char *const sig_name, UNUSED const amxc_var_t *const data, void *const priv)
static void amxb_ubus_call_func(const amxc_var_t *const data, void *const priv)
static void amxb_ubus_exec_done(const amxc_var_t *const data, void *const priv)
static int amxb_ubus_amxd_to_ubus_status(amxd_status_t rv)
static void amxb_ubus_build_obj(amxb_ubus_t *amxb_ubus_ctx, amxb_ubus_object_t *obj, amxd_object_t *const object)
struct _amxb_ubus_fcall amxb_ubus_fcall_t
static bool amxb_ubus_filter_object(amxd_object_t *const object, AMXB_UNUSED int32_t depth, AMXB_UNUSED void *priv)
static void amxb_ubus_register_remove(const char *const sig_name, const amxc_var_t *const data, void *const priv)
static enum blobmsg_type amxb_ubus_var_type_to_ubus_type(int type)
static void amxb_ubus_send_notification(const char *const sig_name, const amxc_var_t *const data, void *const priv)
static void amxb_ubus_subcribe(AMXB_UNUSED struct ubus_context *ctx, struct ubus_object *obj)
static void amxb_ubus_func_return(amxb_ubus_t *amxb_ubus_ctx, amxc_var_t *ret)
static void amxb_ubus_register_add(const char *const sig_name, const amxc_var_t *const data, void *const priv)
int PRIVATE amxb_ubus_register(void *const ctx, amxd_dm_t *const dm)
static void amxb_ubus_build_messages(amxb_ubus_fcall_t *fcall, amxc_var_t *ret, amxc_var_t *args, amxc_var_t *status)
static void amxb_register_add_function(amxd_object_t *const object, const char *name, struct ubus_method *ubus_method)
static int amxb_ubus_func_handler(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg)
static void amxb_ubus_register_tree(AMXB_UNUSED const char *const sig_name, const amxc_var_t *const data, void *const priv)
void PRIVATE amxb_ubus_cancel_requests(amxb_ubus_t *amxb_ubus_ctx)
struct ubus_request_data req
amxb_ubus_t * amxb_ubus_ctx
struct ubus_object ubus_obj
amxb_ubus_t * amxb_ubus_ctx
amxc_llist_t pending_reqs
amxc_llist_t registered_objs
struct ubus_context * ubus_ctx