From 16ed3a79e372f9ec8615e5b23488a331325b2258 Mon Sep 17 00:00:00 2001 From: Amin Ben Romdhane Date: Mon, 18 Aug 2025 08:07:08 +0000 Subject: [PATCH] Support multiple DM paths for the same UBUS event --- libbbfdm-ubus/bbfdm-ubus.h | 7 -- libbbfdm-ubus/events.c | 204 ++++++++++++++++++++++--------------- 2 files changed, 124 insertions(+), 87 deletions(-) diff --git a/libbbfdm-ubus/bbfdm-ubus.h b/libbbfdm-ubus/bbfdm-ubus.h index f3742267..fcd5d38c 100644 --- a/libbbfdm-ubus/bbfdm-ubus.h +++ b/libbbfdm-ubus/bbfdm-ubus.h @@ -29,13 +29,6 @@ struct bbfdm_context { struct list_head event_handlers; }; -struct ev_handler_node { - char *dm_path; - char *ev_name; - struct ubus_event_handler *ev_handler; - struct list_head list; -}; - typedef struct bbfdm_data { struct ubus_context *ctx; struct ubus_request_data *req; diff --git a/libbbfdm-ubus/events.c b/libbbfdm-ubus/events.c index 9163bcda..f7b1838c 100644 --- a/libbbfdm-ubus/events.c +++ b/libbbfdm-ubus/events.c @@ -19,16 +19,28 @@ struct event_args { char method_name[256]; }; -static char *get_events_dm_path(struct list_head *ev_list, const char *event) +struct dm_path_node { + char *dm_path; + struct list_head list; +}; + +struct ev_handler_node { + char *ev_name; + struct ubus_event_handler *ev_handler; + struct list_head dm_paths_list; // For dm path list + struct list_head list; // For event list +}; + +static struct ev_handler_node *get_event_node(struct list_head *ev_list, const char *event_name) { struct ev_handler_node *iter = NULL; - if (ev_list == NULL || event == NULL) + if (!ev_list || !event_name) return NULL; list_for_each_entry(iter, ev_list, list) { - if (iter->ev_name && strcmp(iter->ev_name, event) == 0) - return iter->dm_path; + if (iter->ev_name && strcmp(iter->ev_name, event_name) == 0) + return iter; } return NULL; @@ -60,7 +72,9 @@ static void bbfdm_event_handler(struct ubus_context *ctx, struct ubus_event_hand const char *type, struct blob_attr *msg) { (void)ev; - struct bbfdm_context *u; + struct ev_handler_node *ev_node = NULL; + struct dm_path_node *dp_iter = NULL; + struct bbfdm_context *u = NULL; u = container_of(ctx, struct bbfdm_context, ubus_ctx); if (u == NULL) { @@ -71,83 +85,120 @@ static void bbfdm_event_handler(struct ubus_context *ctx, struct ubus_event_hand if (!msg || !type) return; - char *event_dm_path = get_events_dm_path(&u->event_handlers, type); - if (event_dm_path == NULL) + ev_node = get_event_node(&u->event_handlers, type); + if (!ev_node) return; - char dm_path[MAX_DM_PATH]; + list_for_each_entry(dp_iter, &ev_node->dm_paths_list, list) { + char dm_path[MAX_DM_PATH]; - replace_str(event_dm_path, ".{i}.", ".*.", dm_path, sizeof(dm_path)); - if (strlen(dm_path) == 0) - return; + replace_str(dp_iter->dm_path, ".{i}.", ".*.", dm_path, sizeof(dm_path)); + if (strlen(dm_path) == 0) + return; - char *str = blobmsg_format_json(msg, true); + char *str = blobmsg_format_json(msg, true); - struct dmctx bbf_ctx = { - .in_param = dm_path, - .in_value = str, - .nextlevel = false, - .iscommand = false, - .isevent = true, - .isinfo = false, - .dm_type = BBFDM_USP - }; + struct dmctx bbf_ctx = { + .in_param = dm_path, + .in_value = str, + .nextlevel = false, + .iscommand = false, + .isevent = true, + .isinfo = false, + .dm_type = BBFDM_USP + }; - bbf_init(&bbf_ctx); + bbf_init(&bbf_ctx); - int ret = bbfdm_cmd_exec(&bbf_ctx, BBF_EVENT); - if (ret) - goto end; - - size_t blob_data_len = blob_raw_len(bbf_ctx.bb.head); - - if (blob_data_len) { - struct event_args *e_args = (struct event_args *)calloc(1, sizeof(struct event_args)); - if (!e_args) + int ret = bbfdm_cmd_exec(&bbf_ctx, BBF_EVENT); + if (ret) goto end; - snprintf(e_args->method_name, sizeof(e_args->method_name), "%s.event", BBFDM_DEFAULT_UBUS_OBJ); + size_t blob_data_len = blob_raw_len(bbf_ctx.bb.head); - e_args->blob_data = (struct blob_attr *)calloc(1, blob_data_len); + if (blob_data_len) { + struct event_args *e_args = (struct event_args *)calloc(1, sizeof(struct event_args)); + if (!e_args) + goto end; - memcpy(e_args->blob_data, bbf_ctx.bb.head, blob_data_len); + snprintf(e_args->method_name, sizeof(e_args->method_name), "%s.event", BBFDM_DEFAULT_UBUS_OBJ); - bbfdm_task_schedule(event_callback, NULL, e_args, 6); + e_args->blob_data = (struct blob_attr *)calloc(1, blob_data_len); + + memcpy(e_args->blob_data, bbf_ctx.bb.head, blob_data_len); + + bbfdm_task_schedule(event_callback, NULL, e_args, 6); + } + + end: + bbf_cleanup(&bbf_ctx); + FREE(str); } - -end: - bbf_cleanup(&bbf_ctx); - FREE(str); } -static void add_ubus_event_handler(struct ubus_event_handler *ev, const char *ev_name, const char *dm_path, struct list_head *ev_list) +static void add_dm_path(struct ev_handler_node *node, const char *dm_path) { - if (ev == NULL || ev_list == NULL) + struct dm_path_node *dp_iter = NULL; + + if (!node || !dm_path) return; - struct ev_handler_node *node = NULL; + // Prevent duplicate dm_paths + list_for_each_entry(dp_iter, &node->dm_paths_list, list) { + if (strcmp(dp_iter->dm_path, dm_path) == 0) + return; + } - node = (struct ev_handler_node *)calloc(1, sizeof(struct ev_handler_node)); - if (!node) { - BBF_ERR("Out of memory!"); + struct dm_path_node *dp_node = (struct dm_path_node *)calloc(1, sizeof(struct dm_path_node)); + if (!dp_node) { + BBF_ERR("Out of memory adding DM path!"); return; } - INIT_LIST_HEAD(&node->list); - list_add_tail(&node->list, ev_list); + INIT_LIST_HEAD(&dp_node->list); - node->ev_handler = ev; - node->ev_name = ev_name ? strdup(ev_name) : NULL; - node->dm_path = dm_path ? strdup(dm_path) : NULL; + dp_node->dm_path = strdup(dm_path); + + list_add_tail(&dp_node->list, &node->dm_paths_list); +} + +static void add_ubus_event_handler(struct ubus_context *ctx, const char *ev_name, const char *dm_path, struct list_head *ev_list) +{ + struct ev_handler_node *node; + + if (!ctx || !ev_name || !dm_path || !ev_list) + return; + + node = get_event_node(ev_list, ev_name); + + if (!node) { + // Create a new event node + node = (struct ev_handler_node *)calloc(1, sizeof(struct ev_handler_node)); + if (!node) { + BBF_ERR("Out of memory!"); + return; + } + + INIT_LIST_HEAD(&node->list); + INIT_LIST_HEAD(&node->dm_paths_list); + + list_add_tail(&node->list, ev_list); + + node->ev_name = strdup(ev_name); + node->ev_handler = (struct ubus_event_handler *)calloc(1, sizeof(struct ubus_event_handler)); + if (node->ev_handler) { + node->ev_handler->cb = bbfdm_event_handler; + if (ubus_register_event_handler(ctx, node->ev_handler, ev_name) != 0) { + BBF_ERR("Failed to register: %s", ev_name); + } + } + } + + add_dm_path(node, dm_path); } int register_events_to_ubus(struct ubus_context *ctx, struct list_head *ev_list) { - int err = 0; - - if (ctx == NULL || ev_list == NULL) - return -1; - struct dmctx bbf_ctx = { .in_param = ROOT_NODE, .nextlevel = false, @@ -157,6 +208,9 @@ int register_events_to_ubus(struct ubus_context *ctx, struct list_head *ev_list) .dm_type = BBFDM_USP }; + if (ctx == NULL || ev_list == NULL) + return -1; + bbf_init(&bbf_ctx); if (0 == bbfdm_cmd_exec(&bbf_ctx, BBF_SCHEMA)) { @@ -178,50 +232,40 @@ int register_events_to_ubus(struct ubus_context *ctx, struct list_head *ev_list) if (!param_name || !event_name || !strlen(event_name)) continue; - struct ubus_event_handler *ev = (struct ubus_event_handler *)calloc(1, sizeof(struct ubus_event_handler)); - if (!ev) { - BBF_ERR("Out of memory!"); - err = -1; - goto end; - } - - ev->cb = bbfdm_event_handler; - - if (0 != ubus_register_event_handler(ctx, ev, event_name)) { - BBF_ERR("Failed to register: %s", event_name); - err = -1; - goto end; - } - - add_ubus_event_handler(ev, event_name, param_name, ev_list); + add_ubus_event_handler(ctx, event_name, param_name, ev_list); } } -end: bbf_cleanup(&bbf_ctx); - return err; + return 0; } void free_ubus_event_handler(struct ubus_context *ctx, struct list_head *ev_list) -{ - struct ev_handler_node *iter = NULL, *node = NULL; + { + struct ev_handler_node *iter = NULL, *tmp = NULL; + struct dm_path_node *dp_iter = NULL, *dp_tmp = NULL; - if (ctx == NULL || ev_list == NULL) + if (!ctx || !ev_list) return; - list_for_each_entry_safe(iter, node, ev_list, list) { + list_for_each_entry_safe(iter, tmp, ev_list, list) { if (iter->ev_handler != NULL) { ubus_unregister_event_handler(ctx, iter->ev_handler); free(iter->ev_handler); } - if (iter->dm_path) - free(iter->dm_path); - if (iter->ev_name) free(iter->ev_name); + list_for_each_entry_safe(dp_iter, dp_tmp, &iter->dm_paths_list, list) { + if (dp_iter->dm_path) + free(dp_iter->dm_path); + + list_del(&dp_iter->list); + free(dp_iter); + } + list_del(&iter->list); free(iter); }