From 9d93c075af3419a863c155d9d6782c8ec68868af Mon Sep 17 00:00:00 2001 From: Vivek Kumar Dutta Date: Fri, 20 Oct 2023 16:13:44 +0530 Subject: [PATCH] Signal handler for microservice --- bbfdmd/ubus/bbfdmd.c | 351 +++++++++++++++++++++++++++++-------------- bbfdmd/ubus/bbfdmd.h | 21 +++ bbfdmd/ubus/cli.c | 63 +++----- bbfdmd/ubus/cli.h | 2 +- bbfdmd/ubus/common.h | 5 +- bbfdmd/ubus/events.c | 11 +- bbfdmd/ubus/plugin.c | 12 +- 7 files changed, 297 insertions(+), 168 deletions(-) diff --git a/bbfdmd/ubus/bbfdmd.c b/bbfdmd/ubus/bbfdmd.c index ae7247e8..d255d350 100644 --- a/bbfdmd/ubus/bbfdmd.c +++ b/bbfdmd/ubus/bbfdmd.c @@ -30,6 +30,12 @@ #include "plugin.h" #include "cli.h" +#ifndef DAEMON_JSON_INPUT +#define BBFDM_JSON_INPUT "/etc/bbfdm/input.json" +#else +#define BBFDM_JSON_INPUT TO_STR(DAEMON_JSON_INPUT) +#endif + extern struct list_head loaded_json_files; extern struct list_head json_list; extern struct list_head json_memhead; @@ -44,17 +50,8 @@ static void cancel_periodic_timers(struct ubus_context *ctx); static void run_schema_updater(struct bbfdm_context *u); // Global variables -static unsigned int g_refresh_time = BBF_INSTANCES_UPDATE_TIMEOUT; -static int g_subprocess_level = BBF_SUBPROCESS_DEPTH; - static void *deamon_lib_handle = NULL; -char UBUS_MAIN_METHOD_NAME[32] = "bbfdm"; -char CONFIG_PLUGIN_PATH[256] = {0}; -char UBUS_METHOD_NAME[32] = "bbfdm"; -char PARENT_DM[512] = {0}; -char MICRO_SERVICE_OBJ_NAME[64] = {0}; - static void sig_handler(int sig) { if (sig == SIGSEGV) { @@ -64,12 +61,26 @@ static void sig_handler(int sig) } } +static void service_sig_handler(int sig) +{ + WARNING("# PID[%ld] received %d signal ...", getpid(), sig); + if (sig == SIGSEGV) { + ERR("# Exception in PID[%ld] ...", getpid()); + } + exit(-1); +} + static void signal_init(void) { signal(SIGSEGV, sig_handler); signal(SIGUSR1, sig_handler); } +static void service_signal_init(void) +{ + signal(SIGSEGV, service_sig_handler); +} + static void usage(char *prog) { fprintf(stderr, "Usage: %s [options]\n", prog); @@ -105,14 +116,14 @@ static bool is_sync_operate_cmd(bbfdm_data_t *data __attribute__((unused))) return false; } -static bool is_subprocess_required(const char *path) +static bool is_subprocess_required(int subprocess_level, const char *path) { bool ret = false; size_t len = DM_STRLEN(path); if (len == 0) return ret; - if (count_delim(path) < g_subprocess_level) { + if (count_delim(path) < subprocess_level) { if (path[len - 1] == '.') ret = true; } @@ -317,6 +328,13 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ bbfdm_data_t data; uint8_t maxdepth = 0; bool is_subprocess_needed = false; + struct bbfdm_context *u; + + u = container_of(ctx, struct bbfdm_context, ubus_ctx); + if (u == NULL) { + ERR("Failed to get the bbfdm context"); + return UBUS_STATUS_UNKNOWN_ERROR; + } memset(&data, 0, sizeof(bbfdm_data_t)); @@ -331,7 +349,7 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ if (tb[DM_GET_PATH]) { char *path = blobmsg_get_string(tb[DM_GET_PATH]); add_path_list(path, &paths_list); - is_subprocess_needed = is_subprocess_required(path); + is_subprocess_needed = is_subprocess_required(u->config.subprocess_level, path); } if (tb[DM_GET_PATHS]) { @@ -344,7 +362,7 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ add_path_list(path_str, &paths_list); if (!is_subprocess_needed) - is_subprocess_needed = is_subprocess_required(path_str); + is_subprocess_needed = is_subprocess_required(u->config.subprocess_level, path_str); } } @@ -1032,6 +1050,13 @@ static int bbfdm_notify_event(struct ubus_context *ctx, struct ubus_object *obj, { struct blob_attr *tb[__BBF_NOTIFY_MAX] = {NULL}; char method_name[40] = {0}; + struct bbfdm_context *u; + + u = container_of(ctx, struct bbfdm_context, ubus_ctx); + if (u == NULL) { + ERR("failed to get the bbfdm context"); + return UBUS_STATUS_UNKNOWN_ERROR; + } if (blobmsg_parse(dm_notify_event_policy, __BBF_NOTIFY_MAX, tb, blob_data(msg), blob_len(msg))) { ERR("Failed to parse blob"); @@ -1042,7 +1067,7 @@ static int bbfdm_notify_event(struct ubus_context *ctx, struct ubus_object *obj, return UBUS_STATUS_INVALID_ARGUMENT; INFO("ubus method|%s|, name|%s|", method, obj->name); - snprintf(method_name, sizeof(method_name), "%s.%s", UBUS_METHOD_NAME, BBF_EVENT); + snprintf(method_name, sizeof(method_name), "%s.%s", u->config.out_name, BBF_EVENT); ubus_send_event(ctx, method_name, msg); return 0; @@ -1061,10 +1086,10 @@ static struct ubus_method bbf_methods[] = { UBUS_METHOD("notify_event", bbfdm_notify_event, dm_notify_event_policy), }; -static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE(UBUS_METHOD_NAME, bbf_methods); +static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE("", bbf_methods); static struct ubus_object bbf_object = { - .name = UBUS_METHOD_NAME, + .name = "", .type = &bbf_type, .methods = bbf_methods, .n_methods = ARRAY_SIZE(bbf_methods) @@ -1081,14 +1106,14 @@ static void run_schema_updater(struct bbfdm_context *u) memset(&bb, 0, sizeof(struct blob_buf)); INFO("Schema update available"); - snprintf(method_name, sizeof(method_name), "%s.%s", UBUS_METHOD_NAME, BBF_UPDATE_SCHEMA_EVENT); + snprintf(method_name, sizeof(method_name), "%s.%s", u->config.out_name, BBF_UPDATE_SCHEMA_EVENT); blob_buf_init(&bb, 0); ubus_send_event(&u->ubus_ctx, method_name, bb.head); blob_buf_free(&bb); } } -static void broadcast_add_del_event(struct list_head *inst, bool is_add) +static void broadcast_add_del_event(const char *method, struct list_head *inst, bool is_add) { struct ubus_context ctx; struct blob_buf bb; @@ -1117,7 +1142,7 @@ static void broadcast_add_del_event(struct list_head *inst, bool is_add) } blobmsg_close_array(&bb, a); - snprintf(method_name, sizeof(method_name), "%s.%s", UBUS_MAIN_METHOD_NAME, is_add ? BBF_ADD_EVENT : BBF_DEL_EVENT); + snprintf(method_name, sizeof(method_name), "%s.%s", method, is_add ? BBF_ADD_EVENT : BBF_DEL_EVENT); if (is_add) ubus_send_event(&ctx, method_name, bb.head); @@ -1162,9 +1187,9 @@ static void instance_fork_done(struct uloop_process *p, int ret) INFO("Instance updater(%d) completed, starting a new instance timer", r->process.pid); struct bbfdm_context *u = (struct bbfdm_context *)r->result; - if (g_refresh_time != 0) { + if (u->config.refresh_time != 0) { u->instance_timer.cb = periodic_instance_updater; - uloop_timeout_set(&u->instance_timer, g_refresh_time); + uloop_timeout_set(&u->instance_timer, u->config.refresh_time); } free_path_list(&u->old_instances); async_req_free(r); @@ -1174,17 +1199,23 @@ static void instance_fork_done(struct uloop_process *p, int ret) } } -static void instance_compare_publish(struct list_head *new_inst, struct list_head *old_inst) +static void instance_compare_publish(struct bbfdm_context *daemon_ctx) { struct pathNode *ptr; LIST_HEAD(inst_list); + struct list_head *new_inst, *old_inst; + const char *method; + new_inst = &daemon_ctx->instances; + old_inst = &daemon_ctx->old_instances; + + method = DM_STRLEN(daemon_ctx->config.out_root_obj) ? daemon_ctx->config.out_root_obj : daemon_ctx->config.out_name; list_for_each_entry(ptr, old_inst, list) { if (!present_in_path_list(new_inst, ptr->path)) { add_path_list(ptr->path, &inst_list); } } - broadcast_add_del_event(&inst_list, false); + broadcast_add_del_event(method, &inst_list, false); free_path_list(&inst_list); list_for_each_entry(ptr, new_inst, list) { @@ -1192,7 +1223,7 @@ static void instance_compare_publish(struct list_head *new_inst, struct list_hea add_path_list(ptr->path, &inst_list); } } - broadcast_add_del_event(&inst_list, true); + broadcast_add_del_event(method, &inst_list, true); free_path_list(&inst_list); } @@ -1204,9 +1235,9 @@ static int fork_instance_checker(struct bbfdm_context *u) r = async_req_new(); if (r == NULL) { ERR("Error allocating instance req"); - if (g_refresh_time != 0) { + if (u->config.refresh_time != 0) { u->instance_timer.cb = periodic_instance_updater; - uloop_timeout_set(&u->instance_timer, g_refresh_time); + uloop_timeout_set(&u->instance_timer, u->config.refresh_time); } free_path_list(&u->old_instances); goto err_out; @@ -1225,7 +1256,7 @@ static int fork_instance_checker(struct bbfdm_context *u) fclose(stderr); DEBUG("subprocess instances checker"); - instance_compare_publish(&u->instances, &u->old_instances); + instance_compare_publish(u); bbfdm_cleanup(u); closelog(); /* write result and exit */ @@ -1251,16 +1282,16 @@ static void periodic_instance_updater(struct uloop_timeout *t) { struct bbfdm_context *u; - if (g_refresh_time == 0) { - return; // periodic refresh disabled - } - u = container_of(t, struct bbfdm_context, instance_timer); if (u == NULL) { ERR("Failed to get the bbfdm context"); return; } + if (u->config.refresh_time == 0) { + return; // periodic refresh disabled + } + if (is_transaction_running()) { DEBUG("Transaction ongoing, schedule refresh timer after 1s"); u->instance_timer.cb = periodic_instance_updater; @@ -1272,7 +1303,7 @@ static void periodic_instance_updater(struct uloop_timeout *t) update_instances_list(&u->instances); DEBUG("Creating timer for instance update checker, init instances"); u->instance_timer.cb = periodic_instance_updater; - uloop_timeout_set(&u->instance_timer, g_refresh_time); + uloop_timeout_set(&u->instance_timer, u->config.refresh_time); return; } @@ -1288,9 +1319,15 @@ static bool register_service(struct ubus_context *ctx) { struct blob_buf bb; uint32_t ubus_id; + struct bbfdm_context *u; + u = container_of(ctx, struct bbfdm_context, ubus_ctx); + if (u == NULL) { + ERR("failed to get the bbfdm context"); + return false; + } // check if object already present - int ret = ubus_lookup_id(ctx, UBUS_MAIN_METHOD_NAME, &ubus_id); + int ret = ubus_lookup_id(ctx, u->config.out_root_obj, &ubus_id); if (ret != 0) return false; @@ -1298,9 +1335,9 @@ static bool register_service(struct ubus_context *ctx) blob_buf_init(&bb, 0); blobmsg_add_string(&bb, "cmd", "register"); - blobmsg_add_string(&bb, "name", UBUS_METHOD_NAME); - blobmsg_add_string(&bb, "parent_dm", PARENT_DM); - blobmsg_add_string(&bb, "object", MICRO_SERVICE_OBJ_NAME); + blobmsg_add_string(&bb, "name", u->config.out_name); + blobmsg_add_string(&bb, "parent_dm", u->config.out_parent_dm); + blobmsg_add_string(&bb, "object", u->config.out_object); ubus_invoke(ctx, ubus_id, "service", bb.head, NULL, NULL, 5000); blob_buf_free(&bb); @@ -1308,9 +1345,8 @@ static bool register_service(struct ubus_context *ctx) return true; } -static int bbfdm_load_deamon_config(const char *input) +static int bbfdm_load_deamon_config(bbfdm_config_t *config, const char *json_path) { - const char *json_path = input ? input : BBF_JSON_INPUT; char *opt_val = NULL; int err = 0; @@ -1328,80 +1364,92 @@ static int bbfdm_load_deamon_config(const char *input) } opt_val = dmjson_get_value(deamon_obj, 2, "config", "loglevel"); - if (opt_val && strlen(opt_val)) { - uint8_t log_level = (uint8_t) strtoul(opt_val, NULL, 10); - set_debug_level(log_level); + if (DM_STRLEN(opt_val)) { + config->log_level = (uint8_t) strtoul(opt_val, NULL, 10); + set_debug_level(config->log_level); } opt_val = dmjson_get_value(deamon_obj, 2, "config", "refresh_time"); - if (opt_val && strlen(opt_val)) { - unsigned int refresh_time = (unsigned int) strtoul(opt_val, NULL, 10); - g_refresh_time = refresh_time * 1000; + if (DM_STRLEN(opt_val)) { + config->refresh_time = (unsigned int) strtoul(opt_val, NULL, 10) * 1000; + } else { + config->refresh_time = BBF_INSTANCES_UPDATE_TIMEOUT; } opt_val = dmjson_get_value(deamon_obj, 2, "config", "transaction_timeout"); - if (opt_val && strlen(opt_val)) { - int trans_timeout = (int) strtol(opt_val, NULL, 10); - configure_transaction_timeout(trans_timeout); + if (DM_STRLEN(opt_val)) { + config->transaction_timeout = (int) strtol(opt_val, NULL, 10); + configure_transaction_timeout(config->transaction_timeout); } opt_val = dmjson_get_value(deamon_obj, 2, "config", "subprocess_level"); - if (opt_val && strlen(opt_val)) { - g_subprocess_level = (unsigned int) strtoul(opt_val, NULL, 10); + if (DM_STRLEN(opt_val)) { + config->subprocess_level = (unsigned int) strtoul(opt_val, NULL, 10); + } else { + config->subprocess_level = BBF_SUBPROCESS_DEPTH; } opt_val = dmjson_get_value(deamon_obj, 2, "output", "name"); - if (opt_val && strlen(opt_val)) { - strncpyt(UBUS_METHOD_NAME, opt_val, sizeof(UBUS_METHOD_NAME)); - } else { - err = -1; - goto exit; + if (DM_STRLEN(opt_val)) { + strncpyt(config->out_name, opt_val, sizeof(config->out_name)); } - if (input) { - opt_val = dmjson_get_value(deamon_obj, 2, "output", "parent_dm"); - if (opt_val && strlen(opt_val)) { - strncpyt(PARENT_DM, opt_val, sizeof(PARENT_DM)); - } else { - err = -1; - goto exit; - } + opt_val = dmjson_get_value(deamon_obj, 2, "output", "parent_dm"); + if (DM_STRLEN(opt_val)) { + strncpyt(config->out_parent_dm, opt_val, sizeof(config->out_parent_dm)); + } - opt_val = dmjson_get_value(deamon_obj, 2, "output", "object"); - if (opt_val && strlen(opt_val)) { - strncpyt(MICRO_SERVICE_OBJ_NAME, opt_val, sizeof(MICRO_SERVICE_OBJ_NAME)); - } else { - err = -1; - goto exit; - } + opt_val = dmjson_get_value(deamon_obj, 2, "output", "object"); + if (DM_STRLEN(opt_val)) { + strncpyt(config->out_object, opt_val, sizeof(config->out_object)); + } - opt_val = dmjson_get_value(deamon_obj, 2, "output", "root_obj"); - if (opt_val && strlen(opt_val)) { - strncpyt(UBUS_MAIN_METHOD_NAME, opt_val, sizeof(UBUS_MAIN_METHOD_NAME)); - } + opt_val = dmjson_get_value(deamon_obj, 2, "output", "root_obj"); + if (DM_STRLEN(opt_val)) { + strncpyt(config->out_root_obj, opt_val, sizeof(config->out_root_obj)); } opt_val = dmjson_get_value(deamon_obj, 2, "input", "plugin_dir"); - if (opt_val && strlen(opt_val)) { - strncpyt(CONFIG_PLUGIN_PATH, opt_val, sizeof(CONFIG_PLUGIN_PATH)); + if (DM_STRLEN(opt_val)) { + strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); } opt_val = dmjson_get_value(deamon_obj, 2, "input", "type"); - if (opt_val && strlen(opt_val)) { - char *file_path = dmjson_get_value(deamon_obj, 2, "input", "name"); + if (DM_STRLEN(opt_val)) { + strncpyt(config->in_type, opt_val, sizeof(config->in_type)); + } + opt_val = dmjson_get_value(deamon_obj, 2, "input", "name"); + if (DM_STRLEN(opt_val)) { + strncpyt(config->in_name, opt_val, sizeof(config->in_name)); + } - if (strcasecmp(opt_val, "JSON") == 0) - err = load_json_plugin(&loaded_json_files, &json_list, &json_memhead, file_path, - &DEAMON_DM_ROOT_OBJ); - else if (strcasecmp(opt_val, "DotSo") == 0) - err = load_dotso_plugin(&deamon_lib_handle, file_path, - &DEAMON_DM_ROOT_OBJ, - DEAMON_DM_VENDOR_EXTENSION, - &DEAMON_DM_VENDOR_EXTENSION_EXCLUDE); - else - err = -1; + opt_val = dmjson_get_value(json_obj, 3, "cli", "config", "proto"); + if (DM_STRLEN(opt_val)) { + config->proto = get_proto_type(opt_val); } else { - err = -1; + config->proto = BBFDM_BOTH; + } + + opt_val = dmjson_get_value(json_obj, 3, "cli", "config", "instance_mode"); + if (DM_STRLEN(opt_val)) { + config->instance_mode = get_instance_mode((int) strtol(opt_val, NULL, 10)); + } else { + config->instance_mode = INSTANCE_MODE_NUMBER; + } + + opt_val = dmjson_get_value(json_obj, 3, "cli", "input", "type"); + if (DM_STRLEN(opt_val)) { + snprintf(config->cli_in_type, sizeof(config->cli_in_type), "%s", opt_val); + } + + opt_val = dmjson_get_value(json_obj, 3, "cli", "input", "name"); + if (DM_STRLEN(opt_val)) { + snprintf(config->cli_in_name, sizeof(config->cli_in_name), "%s", opt_val); + } + + opt_val = dmjson_get_value(json_obj, 3, "cli", "output", "type"); + if (DM_STRLEN(opt_val)) { + snprintf(config->cli_out_type, sizeof(config->cli_out_type), "%s", opt_val); } exit: @@ -1413,7 +1461,16 @@ exit: static int bbfdm_regiter_ubus(struct ubus_context *ctx) { int ret; + struct bbfdm_context *u; + u = container_of(ctx, struct bbfdm_context, ubus_ctx); + if (u == NULL) { + ERR("failed to get the bbfdm context"); + return -1; + } + + bbf_object.name = u->config.out_name; + bbf_object.type->name = u->config.out_name; if (is_micro_service) { bbf_object.n_methods = bbf_object.n_methods - 2; bbf_object.type->n_methods = bbf_object.n_methods; @@ -1433,6 +1490,13 @@ static void lookup_event_cb(struct ubus_context *ctx, }; struct blob_attr *attr; const char *path; + struct bbfdm_context *u; + + u = container_of(ctx, struct bbfdm_context, ubus_ctx); + if (u == NULL) { + ERR("failed to get the bbfdm context"); + return; + } if (type && strcmp(type, "ubus.object.add") != 0) return; @@ -1443,7 +1507,7 @@ static void lookup_event_cb(struct ubus_context *ctx, return; path = blobmsg_data(attr); - if (path && strcmp(path, UBUS_MAIN_METHOD_NAME) == 0) { + if (path && strcmp(path, u->config.out_root_obj) == 0) { // register micro-service register_service(ctx); } @@ -1460,7 +1524,7 @@ static void cancel_periodic_timers(struct ubus_context *ctx) } DEBUG("Cancelling Instance_timer"); - if (g_refresh_time != 0) { + if (u->config.refresh_time != 0) { uloop_timeout_cancel(&u->instance_timer); } } @@ -1475,10 +1539,10 @@ static void register_periodic_timers(struct ubus_context *ctx) return; } - DEBUG("Register instance_timer %d", g_refresh_time); - if (g_refresh_time != 0) { + DEBUG("Register instance_timer %d", u->config.refresh_time); + if (u->config.refresh_time != 0) { u->instance_timer.cb = periodic_instance_updater; - uloop_timeout_set(&u->instance_timer, g_refresh_time); + uloop_timeout_set(&u->instance_timer, u->config.refresh_time); } } @@ -1491,11 +1555,61 @@ void bbfdm_ctx_init(struct bbfdm_context *bbfdm_ctx) INIT_LIST_HEAD(&bbfdm_ctx->event_handlers); } +int daemon_load_datamodel(struct bbfdm_context *daemon_ctx) +{ + int err = -1; + char *tmp = daemon_ctx->config.in_type; + char *file_path = daemon_ctx->config.in_name; + + if (DM_STRLEN(tmp) == 0 || DM_STRLEN(file_path) == 0) { + ERR("Input type/name not supported or defined"); + return -1; + } + + if (DM_STRLEN(daemon_ctx->config.out_name) == 0) { + ERR("output name not defined"); + return -1; + } + + if (is_micro_service) { + if (DM_STRLEN(daemon_ctx->config.out_parent_dm) == 0) { + ERR("output parent dm not defined"); + return -1; + } + if (DM_STRLEN(daemon_ctx->config.out_object) == 0) { + ERR("output object not defined"); + return -1; + } + if (DM_STRLEN(daemon_ctx->config.out_root_obj) == 0) { + ERR("output root obj not defined"); + return -1; + } + } + + if (strcasecmp(tmp, "JSON") == 0) { + err = load_json_plugin(&loaded_json_files, &json_list, &json_memhead, file_path, &DEAMON_DM_ROOT_OBJ); + } else if (strcasecmp(tmp, "DotSo") == 0) { + err = load_dotso_plugin(&deamon_lib_handle, file_path, &DEAMON_DM_ROOT_OBJ, DEAMON_DM_VENDOR_EXTENSION, &DEAMON_DM_VENDOR_EXTENSION_EXCLUDE); + } else { + ERR("Input type %s not supported", tmp); + } + + if (!err) { + bbf_global_init(DEAMON_DM_ROOT_OBJ, DEAMON_DM_VENDOR_EXTENSION, DEAMON_DM_VENDOR_EXTENSION_EXCLUDE, daemon_ctx->config.in_plugin_dir); + } else { + ERR("Failed loading %s", file_path); + } + + return err; +} + int main(int argc, char **argv) { struct bbfdm_context bbfdm_ctx; - const char *ubus_socket = NULL, *input_file = NULL; - int err = 0, ch; + const char *ubus_socket = NULL, *input_file = BBFDM_JSON_INPUT; + char *cli_argv[4] = {0}; + int err = 0, ch, cli_argc = 0, i; + bool ubus_init_done = false; while ((ch = getopt(argc, argv, "hs:m:c:")) != -1) { switch (ch) { @@ -1507,8 +1621,11 @@ int main(int argc, char **argv) is_micro_service = input_file ? true : false; break; case 'c': - err = bbfdm_cli_exec_command(input_file, argc-optind+1, &argv[optind-1]); - exit(err); + cli_argc = argc-optind+1; + for (i = 0; i < cli_argc; i++) { + cli_argv[i] = argv[optind - 1 + i]; + } + break; case 'h': usage(argv[0]); exit(0); @@ -1517,18 +1634,30 @@ int main(int argc, char **argv) } } - - if (is_micro_service == false) // It's not a micro-service instance + bbfdm_ctx_init(&bbfdm_ctx); + if (is_micro_service == false) { // It's not a micro-service instance signal_init(); - - err = bbfdm_load_deamon_config(input_file); - if (err != UBUS_STATUS_OK) { - fprintf(stderr, "Failed to load %s config from json file (%s)\n", UBUS_METHOD_NAME, input_file ? input_file : BBF_JSON_INPUT); - return -1; + } else { + service_signal_init(); } - openlog(UBUS_METHOD_NAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); - bbfdm_ctx_init(&bbfdm_ctx); + err = bbfdm_load_deamon_config(&bbfdm_ctx.config, input_file); + if (err) { + fprintf(stderr, "Failed to load %s config from json file (%s)\n", bbfdm_ctx.config.out_name, input_file); + goto exit; + } + + openlog(bbfdm_ctx.config.out_name, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); + if (cli_argc) { + err = bbfdm_cli_exec_command(&bbfdm_ctx.config , cli_argc, cli_argv); + goto exit; + } + + err = daemon_load_datamodel(&bbfdm_ctx); + if (err) { + ERR("Failed to load datamodel"); + goto exit; + } err = ubus_connect_ctx(&bbfdm_ctx.ubus_ctx, ubus_socket); if (err != UBUS_STATUS_OK) { @@ -1538,13 +1667,13 @@ int main(int argc, char **argv) uloop_init(); ubus_add_uloop(&bbfdm_ctx.ubus_ctx); - periodic_instance_updater(&bbfdm_ctx.instance_timer); + ubus_init_done = true; + periodic_instance_updater(&bbfdm_ctx.instance_timer); err = bbfdm_regiter_ubus(&bbfdm_ctx.ubus_ctx); if (err != UBUS_STATUS_OK) goto exit; - bbf_global_init(DEAMON_DM_ROOT_OBJ, DEAMON_DM_VENDOR_EXTENSION, DEAMON_DM_VENDOR_EXTENSION_EXCLUDE, CONFIG_PLUGIN_PATH); run_schema_updater(&bbfdm_ctx); if (is_micro_service == false) { // It's not a micro-service instance err = register_events_to_ubus(&bbfdm_ctx.ubus_ctx, &bbfdm_ctx.event_handlers); @@ -1569,8 +1698,10 @@ exit: if (is_micro_service == false) // It's not a micro-service instance free_ubus_event_handler(&bbfdm_ctx.ubus_ctx, &bbfdm_ctx.event_handlers); - ubus_shutdown(&bbfdm_ctx.ubus_ctx); - uloop_done(); + if (ubus_init_done) { + uloop_done(); + ubus_shutdown(&bbfdm_ctx.ubus_ctx); + } bbfdm_cleanup(&bbfdm_ctx); closelog(); diff --git a/bbfdmd/ubus/bbfdmd.h b/bbfdmd/ubus/bbfdmd.h index 57f1d4bb..4cfc8b80 100644 --- a/bbfdmd/ubus/bbfdmd.h +++ b/bbfdmd/ubus/bbfdmd.h @@ -14,7 +14,28 @@ struct bbfdm_async_req { void *result; }; +typedef struct bbfdm_config { + int proto; + int instance_mode; + int transaction_timeout; + int subprocess_level; + uint8_t log_level; + uint32_t refresh_time; + char in_type[32]; + char in_name[128]; + char in_plugin_dir[128]; + char out_type[32]; + char out_name[32]; + char out_parent_dm[32]; + char out_object[32]; + char out_root_obj[32]; + char cli_in_type[32]; + char cli_in_name[128]; + char cli_out_type[32]; +} bbfdm_config_t; + struct bbfdm_context { + bbfdm_config_t config; struct ubus_context ubus_ctx; struct blob_buf dm_schema; struct uloop_timeout instance_timer; diff --git a/bbfdmd/ubus/cli.c b/bbfdmd/ubus/cli.c index ac7fc9a4..8003fcb2 100644 --- a/bbfdmd/ubus/cli.c +++ b/bbfdmd/ubus/cli.c @@ -26,15 +26,14 @@ static DM_MAP_VENDOR *CLI_DM_VENDOR_EXTENSION[2] = {0}; static DM_MAP_VENDOR_EXCLUDE *CLI_DM_VENDOR_EXTENSION_EXCLUDE = NULL; static void *cli_lib_handle = NULL; -static json_object *cli_json_obj = NULL; typedef struct { struct dmctx bbf_ctx; unsigned int instance_mode; unsigned int proto; char in_name[128]; - char in_type[8]; - char out_type[8]; + char in_type[32]; + char out_type[32]; char *cmd; bool ubus_status; } cli_data_t; @@ -257,37 +256,14 @@ static int in_ubus_out_cli_exec_cmd(cli_data_t *cli_data, const char *path, cons return err; } -static int bbfdm_load_cli_config(const char *json_path, cli_data_t *cli_data) +static int bbfdm_load_cli_config(bbfdm_config_t *bbf_config, cli_data_t *cli_data) { char *opt_val = NULL; - if (!json_path || !strlen(json_path)) { - printf("ERROR: json file not specified\n"); - return -1; - } + cli_data->proto = bbf_config->proto; + cli_data->instance_mode = bbf_config->instance_mode; - cli_json_obj = json_object_from_file(json_path); - if (!cli_json_obj) { - printf("ERROR: not possible to load json file (%s)\n", json_path); - return -1; - } - - opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "config", "proto"); - if (opt_val && strlen(opt_val)) { - cli_data->proto = get_proto_type(opt_val); - } else { - cli_data->proto = BBFDM_BOTH; - } - - opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "config", "instance_mode"); - if (opt_val && strlen(opt_val)) { - int inst_mode = (int) strtol(opt_val, NULL, 10); - cli_data->instance_mode = get_instance_mode(inst_mode); - } else { - cli_data->instance_mode = INSTANCE_MODE_NUMBER; - } - - opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "input", "type"); + opt_val = bbf_config->cli_in_type; if (opt_val && strlen(opt_val)) { snprintf(cli_data->in_type, sizeof(cli_data->in_type), "%s", opt_val); } else { @@ -295,7 +271,7 @@ static int bbfdm_load_cli_config(const char *json_path, cli_data_t *cli_data) return -1; } - opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "input", "name"); + opt_val = bbf_config->cli_in_name; if (opt_val && strlen(opt_val)) { snprintf(cli_data->in_name, sizeof(cli_data->in_name), "%s", opt_val); } else { @@ -303,7 +279,7 @@ static int bbfdm_load_cli_config(const char *json_path, cli_data_t *cli_data) return -1; } - opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "output", "type"); + opt_val = bbf_config->cli_out_type; if (opt_val && strlen(opt_val)) { snprintf(cli_data->out_type, sizeof(cli_data->out_type), "%s", opt_val); } else { @@ -640,7 +616,7 @@ static int cli_exec_command(cli_data_t *cli_data, int argc, char *argv[]) goto end; } - bbf_global_init(CLI_DM_ROOT_OBJ, CLI_DM_VENDOR_EXTENSION, CLI_DM_VENDOR_EXTENSION_EXCLUDE, CONFIG_PLUGIN_PATH); + bbf_global_init(CLI_DM_ROOT_OBJ, CLI_DM_VENDOR_EXTENSION, CLI_DM_VENDOR_EXTENSION_EXCLUDE, NULL); bbf_ctx_init(&cli_data->bbf_ctx, CLI_DM_ROOT_OBJ, CLI_DM_VENDOR_EXTENSION, CLI_DM_VENDOR_EXTENSION_EXCLUDE); @@ -692,17 +668,10 @@ end: return err; } -int bbfdm_cli_exec_command(const char *input, int argc, char *argv[]) +int bbfdm_cli_exec_command(bbfdm_config_t *bbf_config, int argc, char *argv[]) { cli_data_t cli_data = {0}; int err = EXIT_SUCCESS; - const char *json_input = (input) ? input : BBF_JSON_INPUT; - - memset(&cli_data, 0, sizeof(cli_data_t)); - - err = bbfdm_load_cli_config(json_input, &cli_data); - if (err) - return EXIT_FAILURE; // Exit if no command specified if (argc < 1) { @@ -710,11 +679,13 @@ int bbfdm_cli_exec_command(const char *input, int argc, char *argv[]) return EXIT_FAILURE; } - err = cli_exec_command(&cli_data, argc, argv); - - if (cli_json_obj) { - json_object_put(cli_json_obj); - cli_json_obj = NULL; + memset(&cli_data, 0, sizeof(cli_data_t)); + err = bbfdm_load_cli_config(bbf_config, &cli_data); + if (err) { + printf("ERROR: required cli config missing\n"); + return EXIT_FAILURE; } + + err = cli_exec_command(&cli_data, argc, argv); return err; } diff --git a/bbfdmd/ubus/cli.h b/bbfdmd/ubus/cli.h index 1a02f604..cd2d53ad 100644 --- a/bbfdmd/ubus/cli.h +++ b/bbfdmd/ubus/cli.h @@ -8,4 +8,4 @@ * See LICENSE file for license related information. */ -int bbfdm_cli_exec_command(const char *input, int argc, char *argv[]); +int bbfdm_cli_exec_command(bbfdm_config_t *bbf_config, int argc, char *argv[]); diff --git a/bbfdmd/ubus/common.h b/bbfdmd/ubus/common.h index e06bf856..cc36320d 100644 --- a/bbfdmd/ubus/common.h +++ b/bbfdmd/ubus/common.h @@ -18,14 +18,15 @@ #include "bbfdmd.h" +#define STRINGIFY(x) #x +#define TO_STR(x) STRINGIFY(x) + #define ROOT_NODE "Device." #define BBF_ADD_EVENT "AddObj" #define BBF_DEL_EVENT "DelObj" #define BBF_EVENT "event" #define BBF_UPDATE_SCHEMA_EVENT "UpdateSchema" -#define BBF_JSON_INPUT "/etc/bbfdm/input.json" - #define MAX_DM_KEY_LEN 256 #define MAX_DM_PATH 1024 #define MAX_DM_VALUE 4096 diff --git a/bbfdmd/ubus/events.c b/bbfdmd/ubus/events.c index 1f8395a4..5203dc43 100644 --- a/bbfdmd/ubus/events.c +++ b/bbfdmd/ubus/events.c @@ -14,8 +14,6 @@ #include "get_helper.h" #include -extern char UBUS_METHOD_NAME[32]; - static struct event_map_list ev_map_list[] = { /* { event name, DM Path, .arguments[] = { event_args, dm_args } } */ { "wifi.dataelements.Associated", "Device.WiFi.DataElements.AssociationEvent.Associated!", @@ -148,6 +146,13 @@ 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; + + u = container_of(ctx, struct bbfdm_context, ubus_ctx); + if (u == NULL) { + ERR("Failed to get the bbfdm context"); + return; + } if (!msg || !type) return; @@ -169,7 +174,7 @@ static void bbfdm_event_handler(struct ubus_context *ctx, struct ubus_event_hand blob_buf_init(&b, 0); blob_buf_init(&bb, 0); - snprintf(method_name, sizeof(method_name), "%s.%s", UBUS_METHOD_NAME, BBF_EVENT); + snprintf(method_name, sizeof(method_name), "%s.%s", u->config.out_name, BBF_EVENT); blobmsg_add_string(&b, "name", dm_path); generate_blob_input(&bb, type, &pv_list); diff --git a/bbfdmd/ubus/plugin.c b/bbfdmd/ubus/plugin.c index 8f4e031f..767efbcc 100644 --- a/bbfdmd/ubus/plugin.c +++ b/bbfdmd/ubus/plugin.c @@ -28,7 +28,7 @@ int load_dotso_plugin(void **lib_handle, const char *file_path, void *handle = dlopen(file_path, RTLD_NOW|RTLD_LOCAL); if (!handle) { - fprintf(stderr, "ERROR: Plugin failed [%s]\n", dlerror()); + ERR("Plugin failed [%s]\n", dlerror()); return -1; } @@ -42,13 +42,13 @@ int load_dotso_plugin(void **lib_handle, const char *file_path, unsigned int len = strlen(node_obj); if (strncmp(node_obj, ROOT_NODE, strlen(ROOT_NODE)) != 0 || node_obj[len-1] != '.') { - fprintf(stderr, "ERROR: Object (%s) not valid\n", node_obj); + ERR("Object (%s) not valid\n", node_obj); return -1; } DMOBJ *dm_entryobj = (DMOBJ *)dm_dynamic_calloc(&global_memhead, 2, sizeof(DMOBJ)); if (dm_entryobj == NULL) { - fprintf(stderr, "ERROR: No Memory exists\n"); + ERR("No Memory exists\n"); return -1; } @@ -62,7 +62,7 @@ int load_dotso_plugin(void **lib_handle, const char *file_path, *main_entry = dm_entryobj; } else { - fprintf(stderr, "ERROR: Main entry not available"); + ERR("Main entry not available"); return -1; } @@ -119,7 +119,7 @@ int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, unsigned int len = strlen(node_obj); if (strncmp(node_obj, ROOT_NODE, strlen(ROOT_NODE)) != 0 || node_obj[len-1] != '.') { - fprintf(stderr, "ERROR: Object (%s) not valid\n", node_obj); + ERR("ERROR: Object (%s) not valid\n", node_obj); return -1; } @@ -129,7 +129,7 @@ int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, DMOBJ *dm_entryobj = (DMOBJ *)dm_dynamic_calloc(json_memhead, 2, sizeof(DMOBJ)); if (dm_entryobj == NULL) { - fprintf(stderr, "ERROR: No Memory exists\n"); + ERR("ERROR: No Memory exists\n"); return -1; }