diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b8026ab..52060448 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,11 +2,6 @@ cmake_minimum_required(VERSION 3.0) PROJECT(bbf C) -OPTION(BBFDMD_ENABLED "build bbfdmd daemon with their dependencies" OFF) - add_subdirectory(libbbfdm-api) add_subdirectory(libbbfdm) - -IF(BBFDMD_ENABLED) - add_subdirectory(bbfdmd/src) -ENDIF(BBFDMD_ENABLED) +add_subdirectory(bbfdmd/src) diff --git a/bbfdmd/README.md b/bbfdmd/README.md index 53301999..5e22caac 100644 --- a/bbfdmd/README.md +++ b/bbfdmd/README.md @@ -68,7 +68,7 @@ Below is an example of json file: ```json { - "client": { + "cli": { "config": { "proto": "usp", // usp, cwmp "instance_mode": 0 // 0:number, 1:alias diff --git a/bbfdmd/src/bbfdmd.c b/bbfdmd/src/bbfdmd.c index c985e20b..3c293659 100644 --- a/bbfdmd/src/bbfdmd.c +++ b/bbfdmd/src/bbfdmd.c @@ -52,17 +52,19 @@ extern struct list_head json_memhead; #define BBF_SCHEMA_UPDATE_TIMEOUT (60 * 1000) #define BBF_INSTANCES_UPDATE_TIMEOUT (25 * 1000) -#define DEFAULT_JSON_INPUT "/etc/bbfdm/input.json" +LIST_HEAD(head_registered_service); // 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; -static json_object *deamon_json_obj = NULL; +char UBUS_MAIN_METHOD_NAME[32] = "bbfdm"; char UBUS_METHOD_NAME[32] = "bbfdm"; -bool enable_plugins = true; +char PARENT_DM[512] = {0}; +char MICRO_SERVICE_OBJ_NAME[64] = {0}; +char *input_json = NULL; static void sig_handler(int sig) { @@ -85,7 +87,7 @@ static void usage(char *prog) fprintf(stderr, "\n"); fprintf(stderr, "options:\n"); fprintf(stderr, " -s ubus socket\n"); - fprintf(stderr, " -I json input configuration\n"); + fprintf(stderr, " -m json input configuration for micro services\n"); fprintf(stderr, " -c Run cli command\n"); fprintf(stderr, " -h Displays this help\n"); fprintf(stderr, "\n"); @@ -93,21 +95,19 @@ static void usage(char *prog) static void bbfdm_cleanup(struct bbfdm_context *u) { - free_path_list(&u->instances); - free_path_list(&u->old_instances); bbf_global_clean(DEAMON_DM_ROOT_OBJ); + if (!input_json) { // It's not a micro-service instance + free_path_list(&u->instances); + free_path_list(&u->old_instances); + free_services_from_list(&head_registered_service); + } + /* DotSo Plugin */ free_dotso_plugin(deamon_lib_handle); /* JSON Plugin */ free_json_plugin(); - - /* Input JSON File */ - if (deamon_json_obj) { - json_object_put(deamon_json_obj); - deamon_json_obj = NULL; - } } static bool is_sync_operate_cmd(bbfdm_data_t *data __attribute__((unused))) @@ -157,7 +157,7 @@ static void fill_optional_data(bbfdm_data_t *data, struct blob_attr *msg) data->is_raw = is_str_eq(blobmsg_get_string(attr), "raw") ? true : false; } - data->bbf_ctx.enable_plugins = enable_plugins; + data->bbf_ctx.enable_plugins = input_json ? false : true; DEBUG("Proto:|%s|, Inst Mode:|%s|, Tran-id:|%d|, Format:|%s|", (data->bbf_ctx.dm_type == BBFDM_BOTH) ? "both" : (data->bbf_ctx.dm_type == BBFDM_CWMP) ? "cwmp" : "usp", @@ -915,6 +915,100 @@ static int bbfdm_transaction_handler(struct ubus_context *ctx, struct ubus_objec return 0; } +enum { + BBF_SERVICE_CMD, + BBF_SERVICE_NAME, + BBF_SERVICE_PARENT_DM, + BBF_SERVICE_OBJECT, + __BBF_SERVICE_MAX, +}; + +static const struct blobmsg_policy service_policy[] = { + [BBF_SERVICE_CMD] = { .name = "cmd", .type = BLOBMSG_TYPE_STRING }, + [BBF_SERVICE_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, + [BBF_SERVICE_PARENT_DM] = { .name = "parent_dm", .type = BLOBMSG_TYPE_STRING }, + [BBF_SERVICE_OBJECT] = { .name = "object", .type = BLOBMSG_TYPE_STRING }, +}; + +static void service_list(struct blob_buf *bb) +{ + void *array; + + array = blobmsg_open_array(bb, "supported_cmd"); + blobmsg_add_string(bb, NULL, "register"); + blobmsg_add_string(bb, NULL, "list"); + blobmsg_close_array(bb, array); + + array = blobmsg_open_array(bb, "registered_service"); + get_list_of_registered_service(&head_registered_service, bb); + blobmsg_close_array(bb, array); +} + +static int bbfdm_service_handler(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req __attribute__((unused)), const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__BBF_SERVICE_MAX] = {NULL}; + struct blob_buf bb; + + memset(&bb, 0, sizeof(struct blob_buf)); + + blob_buf_init(&bb, 0); + + if (blobmsg_parse(service_policy, __BBF_SERVICE_MAX, tb, blob_data(msg), blob_len(msg))) { + service_list(&bb); + goto end; + } + + INFO("ubus method|%s|, name|%s|", method, obj->name); + + if (input_json) { // It's a micro-service instance + blobmsg_add_string(&bb, "error", "you are not allowed to register a micro-service for another micro-service!!"); + goto end; + } + + if (!tb[BBF_SERVICE_CMD]) { + service_list(&bb); + goto end; + } + + char *srv_cmd = blobmsg_get_string(tb[BBF_SERVICE_CMD]); + + if (is_str_eq(srv_cmd, "register")) { + + if (!tb[BBF_SERVICE_NAME]) { + blobmsg_add_string(&bb, "error", "service name should be defined!!"); + goto end; + } + + if (!tb[BBF_SERVICE_PARENT_DM]) { + blobmsg_add_string(&bb, "error", "service parent dm should be defined!!"); + goto end; + } + + if (!tb[BBF_SERVICE_OBJECT]) { + blobmsg_add_string(&bb, "error", "service object should be defined!!"); + goto end; + } + + char *srv_name = blobmsg_get_string(tb[BBF_SERVICE_NAME]); + char *srv_parent_dm = blobmsg_get_string(tb[BBF_SERVICE_PARENT_DM]); + char *srv_obj = blobmsg_get_string(tb[BBF_SERVICE_OBJECT]); + + bool res = load_service(DEAMON_DM_ROOT_OBJ, &head_registered_service, srv_name, srv_parent_dm, srv_obj); + + blobmsg_add_u8(&bb, "status", res); + } else { + service_list(&bb); + } + +end: + ubus_send_reply(ctx, req, bb.head); + blob_buf_free(&bb); + + return 0; +} + enum { BBF_NOTIFY_NAME, BBF_NOTIFY_PRAMS, @@ -965,6 +1059,7 @@ static struct ubus_method bbf_methods[] = { UBUS_METHOD("add", bbfdm_add_handler, dm_add_policy), UBUS_METHOD("del", bbfdm_del_handler, dm_del_policy), UBUS_METHOD("transaction", bbfdm_transaction_handler, transaction_policy), + UBUS_METHOD("service", bbfdm_service_handler, service_policy), UBUS_METHOD("notify_event", bbfdm_notify_event, dm_notify_event_policy), }; @@ -1057,7 +1152,7 @@ static void update_instances_list(struct list_head *inst) struct dmctx bbf_ctx = { .in_param = ROOT_NODE, .nextlevel = false, - .enable_plugins = enable_plugins, + .enable_plugins = input_json ? false : true, .instance_mode = INSTANCE_MODE_NUMBER, .dm_type = BBFDM_USP }; @@ -1200,21 +1295,47 @@ static void periodic_instance_updater(struct uloop_timeout *t) fork_instance_checker(u); } -static int bbfdm_load_deamon_config(const char *json_path) +static bool register_service(struct ubus_context *ctx) { + struct blob_buf bb; + uint32_t ubus_id; + + // check if object already present + int ret = ubus_lookup_id(ctx, UBUS_MAIN_METHOD_NAME, &ubus_id); + if (ret != 0) + return false; + + memset(&bb, 0, sizeof(struct blob_buf)); + 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); + + ubus_invoke(ctx, ubus_id, "service", bb.head, NULL, NULL, 5000); + blob_buf_free(&bb); + + return true; +} + +static int bbfdm_load_deamon_config(void) +{ + const char *json_path = input_json ? input_json : BBF_JSON_INPUT; char *opt_val = NULL; int err = 0; if (!json_path || !strlen(json_path)) return -1; - deamon_json_obj = json_object_from_file(json_path); - if (!deamon_json_obj) + json_object *json_obj = json_object_from_file(json_path); + if (!json_obj) return -1; - json_object *deamon_obj = dmjson_get_obj(deamon_json_obj, 1, "daemon"); + json_object *deamon_obj = dmjson_get_obj(json_obj, 1, "daemon"); if (!deamon_obj) { - return -1; + err = -1; + goto exit; } opt_val = dmjson_get_value(deamon_obj, 2, "config", "loglevel"); @@ -1240,64 +1361,113 @@ static int bbfdm_load_deamon_config(const char *json_path) g_subprocess_level = (unsigned int) strtoul(opt_val, NULL, 10); } - opt_val = dmjson_get_value(deamon_obj, 2, "config", "enable_plugins"); - if (opt_val && strlen(opt_val)) { - enable_plugins = (unsigned int) strtoul(opt_val, NULL, 10); - } - 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; } - DEAMON_DM_SERVICES = dmjson_get_obj(deamon_obj, 1, "services"); + if (input_json) { + 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", "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", "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, "input", "type"); if (opt_val && strlen(opt_val)) { char *file_path = dmjson_get_value(deamon_obj, 2, "input", "name"); - if (strcasecmp(opt_val, "JSON") == 0) { - enable_plugins = false; // To be sure that all additional plugins will be ignored - err= load_json_plugin(&loaded_json_files, &json_list, &json_memhead, file_path, + 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) { + 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 { + else err = -1; - } } else { err = -1; } +exit: + json_object_put(json_obj); + return err; } -static int bbfdm_init(struct bbfdm_context *u) +static int bbfdm_init(struct ubus_context *ctx) { INFO("Registering ubus objects...."); - return ubus_add_object(&u->ubus_ctx, &bbf_object); + return ubus_add_object(ctx, &bbf_object); +} + +static void lookup_event_cb(struct ubus_context *ctx, + struct ubus_event_handler *ev __attribute__((unused)), + const char *type, struct blob_attr *msg) +{ + const struct blobmsg_policy policy = { + "path", BLOBMSG_TYPE_STRING + }; + struct blob_attr *attr; + const char *path; + + if (type && strcmp(type, "ubus.object.add") != 0) + return; + + blobmsg_parse(&policy, 1, &attr, blob_data(msg), blob_len(msg)); + + if (!attr) + return; + + path = blobmsg_data(attr); + if (path && strcmp(path, UBUS_MAIN_METHOD_NAME) == 0) { + // register micro-service + register_service(ctx); + + // adding ubus method for micro-service + int err = bbfdm_init(ctx); + if (err != UBUS_STATUS_OK) + uloop_end(); + } } int main(int argc, char **argv) { struct bbfdm_context bbfdm_ctx; - const char *input_json = DEFAULT_JSON_INPUT; const char *ubus_socket = NULL; int err = 0, ch; - while ((ch = getopt(argc, argv, "hs:I:c:")) != -1) { + while ((ch = getopt(argc, argv, "hs:m:c:")) != -1) { switch (ch) { case 's': ubus_socket = optarg; break; - case 'I': + case 'm': input_json = optarg; break; case 'c': - err = bbfdm_cli_exec_command(input_json, argc-optind+1, &argv[optind-1]); + err = bbfdm_cli_exec_command(argc-optind+1, &argv[optind-1]); exit(err); case 'h': usage(argv[0]); @@ -1307,52 +1477,74 @@ int main(int argc, char **argv) } } - err = bbfdm_load_deamon_config(input_json); + if (!input_json) // It's not a micro-service instance + signal_init(); + + err = bbfdm_load_deamon_config(); if (err != UBUS_STATUS_OK) { - fprintf(stderr, "Failed to load bbfdm config from json file '%s'\n", input_json); + fprintf(stderr, "Failed to load %s config from json file (%s)\n", UBUS_METHOD_NAME, input_json ? input_json : BBF_JSON_INPUT); return -1; } - openlog("bbfdm", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); + openlog(UBUS_METHOD_NAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); - INIT_LIST_HEAD(&bbfdm_ctx.instances); - INIT_LIST_HEAD(&bbfdm_ctx.old_instances); - INIT_LIST_HEAD(&bbfdm_ctx.event_handlers); - - uloop_init(); - err = ubus_connect_ctx(&bbfdm_ctx.ubus_ctx, ubus_socket); if (err != UBUS_STATUS_OK) { - fprintf(stderr, "Failed to connect to ubus\n"); + ERR("Failed to connect to ubus"); return -1; } - signal_init(); - - err = register_events_to_ubus(&bbfdm_ctx.ubus_ctx, &bbfdm_ctx.event_handlers); - if (err != 0) - goto exit; - + uloop_init(); ubus_add_uloop(&bbfdm_ctx.ubus_ctx); - err = bbfdm_init(&bbfdm_ctx); - if (err != UBUS_STATUS_OK) - goto exit; + if (!input_json) { // It's not a micro-service instance - bbfdm_ctx.schema_timer.cb = periodic_schema_updater; - uloop_timeout_set(&bbfdm_ctx.schema_timer, BBF_SCHEMA_UPDATE_TIMEOUT); + err = bbfdm_init(&bbfdm_ctx.ubus_ctx); + if (err != UBUS_STATUS_OK) + goto exit; - // initial timer should be bigger to give more space to other applications to initialize - bbfdm_ctx.instance_timer.cb = periodic_instance_updater; - uloop_timeout_set(&bbfdm_ctx.instance_timer, 3 * g_refresh_time); + INIT_LIST_HEAD(&bbfdm_ctx.instances); + INIT_LIST_HEAD(&bbfdm_ctx.old_instances); + INIT_LIST_HEAD(&bbfdm_ctx.event_handlers); + + err = register_events_to_ubus(&bbfdm_ctx.ubus_ctx, &bbfdm_ctx.event_handlers); + if (err != 0) + goto exit; + + bbfdm_ctx.schema_timer.cb = periodic_schema_updater; + uloop_timeout_set(&bbfdm_ctx.schema_timer, BBF_SCHEMA_UPDATE_TIMEOUT); + + // initial timer should be bigger to give more space to other applications to initialize + bbfdm_ctx.instance_timer.cb = periodic_instance_updater; + uloop_timeout_set(&bbfdm_ctx.instance_timer, 3 * g_refresh_time); + + } else { // It's a micro-service instance + + bool is_registred = register_service(&bbfdm_ctx.ubus_ctx); + if (is_registred) { + // service is registred, so add ubus method for micro-service + err = bbfdm_init(&bbfdm_ctx.ubus_ctx); + if (err != UBUS_STATUS_OK) + goto exit; + } else { + // register for add event + struct ubus_event_handler add_event; + + memset(&add_event, 0, sizeof(struct ubus_event_handler)); + add_event.cb = lookup_event_cb; + ubus_register_event_handler(&bbfdm_ctx.ubus_ctx, &add_event, "ubus.object.add"); + } + } INFO("Waiting on uloop...."); uloop_run(); exit: - free_ubus_event_handler(&bbfdm_ctx.ubus_ctx, &bbfdm_ctx.event_handlers); + if (!input_json) // 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(); bbfdm_cleanup(&bbfdm_ctx); diff --git a/bbfdmd/src/cli.c b/bbfdmd/src/cli.c index 6e103935..4a9cb615 100644 --- a/bbfdmd/src/cli.c +++ b/bbfdmd/src/cli.c @@ -33,15 +33,16 @@ extern struct list_head loaded_json_files; extern struct list_head json_list; extern struct list_head json_memhead; +extern char *input_json; + #define UNUSED __attribute__((unused)) -static DMOBJ *CLIENT_DM_ROOT_OBJ = NULL; -static DM_MAP_VENDOR *CLIENT_DM_VENDOR_EXTENSION[2] = {0}; -static DM_MAP_VENDOR_EXCLUDE *CLIENT_DM_VENDOR_EXTENSION_EXCLUDE = NULL; -static json_object *CLIENT_DM_SERVICES = NULL; +static DMOBJ *CLI_DM_ROOT_OBJ = NULL; +static DM_MAP_VENDOR *CLI_DM_VENDOR_EXTENSION[2] = {0}; +static DM_MAP_VENDOR_EXCLUDE *CLI_DM_VENDOR_EXTENSION_EXCLUDE = NULL; -static void *client_lib_handle = NULL; -static json_object *client_json_obj = NULL; +static void *cli_lib_handle = NULL; +static json_object *cli_json_obj = NULL; typedef struct { struct dmctx bbf_ctx; @@ -52,23 +53,22 @@ typedef struct { char out_type[8]; char *cmd; bool ubus_status; - bool enable_plugins; -} client_data_t; +} cli_data_t; typedef struct { char *name; int num_args; - int (*exec_cmd)(client_data_t *client_data, char *argv[]); + int (*exec_cmd)(cli_data_t *cli_data, char *argv[]); char *usage; } cli_cmd_t; -static int cli_exec_help(client_data_t *client_data UNUSED, char *argv[] UNUSED); -static int cli_exec_get(client_data_t *client_data, char *argv[]); -static int cli_exec_set(client_data_t *client_data, char *argv[]); -static int cli_exec_add(client_data_t *client_data, char *argv[]); -static int cli_exec_del(client_data_t *client_data, char *argv[]); -static int cli_exec_instances(client_data_t *client_data, char *argv[]); -static int cli_exec_schema(client_data_t *client_data, char *argv[]); +static int cli_exec_help(cli_data_t *cli_data UNUSED, char *argv[] UNUSED); +static int cli_exec_get(cli_data_t *cli_data, char *argv[]); +static int cli_exec_set(cli_data_t *cli_data, char *argv[]); +static int cli_exec_add(cli_data_t *cli_data, char *argv[]); +static int cli_exec_del(cli_data_t *cli_data, char *argv[]); +static int cli_exec_instances(cli_data_t *cli_data, char *argv[]); +static int cli_exec_schema(cli_data_t *cli_data, char *argv[]); cli_cmd_t cli_commands[] = { // Name NumArgs Exec callback Usage String @@ -139,16 +139,16 @@ static void __ubus_callback(struct ubus_request *req, int type __attribute__((un if (msg == NULL || req == NULL) return; - client_data_t *client_data = (client_data_t *)req->priv; + cli_data_t *cli_data = (cli_data_t *)req->priv; struct blob_attr *parameters = get_results_array(msg); if (parameters == NULL) { - client_data->ubus_status = false; + cli_data->ubus_status = false; return; } if (blobmsg_len(parameters) == 0) { - client_data->ubus_status = true; + cli_data->ubus_status = true; return; } @@ -162,21 +162,21 @@ static void __ubus_callback(struct ubus_request *req, int type __attribute__((un if (tb[3]) { printf("ERROR: %u retrieving %s\n", blobmsg_get_u32(tb[3]), name); - client_data->ubus_status = false; + cli_data->ubus_status = false; return; } - if (strcmp(client_data->cmd, "get") == 0) + if (strcmp(cli_data->cmd, "get") == 0) printf("%s => %s\n", name, data); - else if (strcmp(client_data->cmd, "set") == 0) { + else if (strcmp(cli_data->cmd, "set") == 0) { printf("Set value of %s is successfully done\n", name); - } else if (strcmp(client_data->cmd, "add") == 0) { + } else if (strcmp(cli_data->cmd, "add") == 0) { printf("Added %s%s.\n", name, data); - } else if (strcmp(client_data->cmd, "del") == 0) { + } else if (strcmp(cli_data->cmd, "del") == 0) { printf("Deleted %s\n", name); - } else if (strcmp(client_data->cmd, "instances") == 0) { + } else if (strcmp(cli_data->cmd, "instances") == 0) { printf("%s\n", name); - } else if (strcmp(client_data->cmd, "schema") == 0) { + } else if (strcmp(cli_data->cmd, "schema") == 0) { char *type = tb[2] ? blobmsg_get_string(tb[2]) : ""; int cmd = get_dm_type(type); @@ -232,11 +232,11 @@ static void __ubus_callback(struct ubus_request *req, int type __attribute__((un } } - client_data->ubus_status = true; + cli_data->ubus_status = true; } } -static int in_ubus_out_cli_exec_cmd(client_data_t *client_data, const char *path, const char *value) +static int in_ubus_out_cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *value) { struct blob_buf b = {0}; void *table = NULL; @@ -250,20 +250,20 @@ static int in_ubus_out_cli_exec_cmd(client_data_t *client_data, const char *path if (value) blobmsg_add_string(&b, "value", value); table = blobmsg_open_table(&b, "optional"); - blobmsg_add_string(&b, "proto", (client_data->proto == BBFDM_CWMP) ? "cwmp" : "usp"); + blobmsg_add_string(&b, "proto", (cli_data->proto == BBFDM_CWMP) ? "cwmp" : "usp"); blobmsg_add_string(&b, "format", "raw"); - blobmsg_add_u32(&b, "instance_mode", client_data->instance_mode); + blobmsg_add_u32(&b, "instance_mode", cli_data->instance_mode); blobmsg_close_table(&b, table); - int e = bbfdm_ubus_invoke(client_data->in_name, client_data->cmd, b.head, __ubus_callback, client_data); + int e = bbfdm_ubus_invoke(cli_data->in_name, cli_data->cmd, b.head, __ubus_callback, cli_data); if (e < 0) { - printf("ERROR: ubus invoke for [object:%s method:%s] exit with error(%d)\n", client_data->in_name, client_data->cmd, e); + printf("ERROR: ubus invoke for [object:%s method:%s] exit with error(%d)\n", cli_data->in_name, cli_data->cmd, e); err = EXIT_FAILURE; } - if (client_data->ubus_status == false) { - printf("ERROR: ubus call for [object:%s method:%s] exit with error\n", client_data->in_name, client_data->cmd); + if (cli_data->ubus_status == false) { + printf("ERROR: ubus call for [object:%s method:%s] exit with error\n", cli_data->in_name, cli_data->cmd); err = EXIT_FAILURE; } @@ -272,8 +272,9 @@ static int in_ubus_out_cli_exec_cmd(client_data_t *client_data, const char *path return err; } -static int bbfdm_load_client_config(const char *json_path, client_data_t *client_data) +static int bbfdm_load_cli_config(cli_data_t *cli_data) { + const char *json_path = input_json ? input_json : BBF_JSON_INPUT; char *opt_val = NULL; if (!json_path || !strlen(json_path)) { @@ -281,64 +282,55 @@ static int bbfdm_load_client_config(const char *json_path, client_data_t *client return -1; } - client_json_obj = json_object_from_file(json_path); - if (!client_json_obj) { + 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(client_json_obj, 3, "client", "config", "proto"); + opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "config", "proto"); if (opt_val && strlen(opt_val)) { - client_data->proto = get_proto_type(opt_val); + cli_data->proto = get_proto_type(opt_val); } else { - client_data->proto = BBFDM_BOTH; + cli_data->proto = BBFDM_BOTH; } - opt_val = dmjson_get_value(client_json_obj, 3, "client", "config", "instance_mode"); + 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); - client_data->instance_mode = get_instance_mode(inst_mode); + cli_data->instance_mode = get_instance_mode(inst_mode); } else { - client_data->instance_mode = INSTANCE_MODE_NUMBER; + cli_data->instance_mode = INSTANCE_MODE_NUMBER; } - opt_val = dmjson_get_value(client_json_obj, 3, "client", "config", "enable_plugins"); + opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "input", "type"); if (opt_val && strlen(opt_val)) { - client_data->enable_plugins = (unsigned int) strtoul(opt_val, NULL, 10); + snprintf(cli_data->in_type, sizeof(cli_data->in_type), "%s", opt_val); } else { - client_data->enable_plugins = false; - } - - opt_val = dmjson_get_value(client_json_obj, 3, "client", "input", "type"); - if (opt_val && strlen(opt_val)) { - snprintf(client_data->in_type, sizeof(client_data->in_type), "%s", opt_val); - } else { - printf("ERROR: [client.input.type] not specified\n"); + printf("ERROR: [cli.input.type] not specified\n"); return -1; } - opt_val = dmjson_get_value(client_json_obj, 3, "client", "input", "name"); + opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "input", "name"); if (opt_val && strlen(opt_val)) { - snprintf(client_data->in_name, sizeof(client_data->in_name), "%s", opt_val); + snprintf(cli_data->in_name, sizeof(cli_data->in_name), "%s", opt_val); } else { - printf("ERROR: [client.input.name] not specified\n"); + printf("ERROR: [cli.input.name] not specified\n"); return -1; } - opt_val = dmjson_get_value(client_json_obj, 3, "client", "output", "type"); + opt_val = dmjson_get_value(cli_json_obj, 3, "cli", "output", "type"); if (opt_val && strlen(opt_val)) { - snprintf(client_data->out_type, sizeof(client_data->out_type), "%s", opt_val); + snprintf(cli_data->out_type, sizeof(cli_data->out_type), "%s", opt_val); } else { - printf("ERROR: [client.output.type] not specified\n"); + printf("ERROR: [cli.output.type] not specified\n"); return -1; } - CLIENT_DM_SERVICES = dmjson_get_obj(client_json_obj, 2, "client", "services"); - return 0; } -static int cli_exec_help(client_data_t *client_data UNUSED, char *argv[] UNUSED) +static int cli_exec_help(cli_data_t *cli_data UNUSED, char *argv[] UNUSED) { cli_cmd_t *cli_cmd; @@ -353,59 +345,59 @@ static int cli_exec_help(client_data_t *client_data UNUSED, char *argv[] UNUSED) return EXIT_SUCCESS; } -static int in_dotso_out_cli_exec_get(client_data_t *client_data, char *argv[]) +static int in_dotso_out_cli_exec_get(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - client_data->bbf_ctx.in_param = argv[0]; + cli_data->bbf_ctx.in_param = argv[0]; - err = bbf_entry_method(&client_data->bbf_ctx, BBF_GET_VALUE); + err = bbf_entry_method(&cli_data->bbf_ctx, BBF_GET_VALUE); if (!err) { struct dm_parameter *n; - list_for_each_entry(n, &client_data->bbf_ctx.list_parameter, list) { + list_for_each_entry(n, &cli_data->bbf_ctx.list_parameter, list) { printf("%s => %s\n", n->name, n->data); } } else { - printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param); + printf("ERROR: %d retrieving %s\n", err, cli_data->bbf_ctx.in_param); err = EXIT_FAILURE; } return err; } -static int in_ubus_out_cli_exec_get(client_data_t *client_data, char *argv[]) +static int in_ubus_out_cli_exec_get(cli_data_t *cli_data, char *argv[]) { - return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]); + return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); } -static int cli_exec_get(client_data_t *client_data, char *argv[]) +static int cli_exec_get(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_get(client_data, argv); - else if (strcasecmp(client_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_get(client_data, argv); + if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) + err = in_dotso_out_cli_exec_get(cli_data, argv); + else if (strcasecmp(cli_data->in_type, "UBUS") == 0) + err = in_ubus_out_cli_exec_get(cli_data, argv); else err = EXIT_FAILURE; return err; } -static int in_dotso_out_cli_exec_set(client_data_t *client_data, char *argv[]) +static int in_dotso_out_cli_exec_set(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - client_data->bbf_ctx.in_param = argv[0]; - client_data->bbf_ctx.in_value = argv[1]; + cli_data->bbf_ctx.in_param = argv[0]; + cli_data->bbf_ctx.in_value = argv[1]; - err = bbf_entry_method(&client_data->bbf_ctx, BBF_SET_VALUE); + err = bbf_entry_method(&cli_data->bbf_ctx, BBF_SET_VALUE); if (!err) { - printf("%s => Set value is successfully done\n", client_data->bbf_ctx.in_param); + printf("%s => Set value is successfully done\n", cli_data->bbf_ctx.in_param); bbf_entry_restart_services(NULL, true); } else { - printf("ERROR: %d retrieving %s => %s\n", err, client_data->bbf_ctx.in_param, client_data->bbf_ctx.in_value); + printf("ERROR: %d retrieving %s => %s\n", err, cli_data->bbf_ctx.in_param, cli_data->bbf_ctx.in_value); bbf_entry_revert_changes(NULL); err = EXIT_FAILURE; } @@ -413,37 +405,37 @@ static int in_dotso_out_cli_exec_set(client_data_t *client_data, char *argv[]) return err; } -static int in_ubus_out_cli_exec_set(client_data_t *client_data, char *argv[]) +static int in_ubus_out_cli_exec_set(cli_data_t *cli_data, char *argv[]) { - return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]); + return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); } -static int cli_exec_set(client_data_t *client_data, char *argv[]) +static int cli_exec_set(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_set(client_data, argv); - else if (strcasecmp(client_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_set(client_data, argv); + if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) + err = in_dotso_out_cli_exec_set(cli_data, argv); + else if (strcasecmp(cli_data->in_type, "UBUS") == 0) + err = in_ubus_out_cli_exec_set(cli_data, argv); else err = EXIT_FAILURE; return err; } -static int in_dotso_out_cli_exec_add(client_data_t *client_data, char *argv[]) +static int in_dotso_out_cli_exec_add(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - client_data->bbf_ctx.in_param = argv[0]; + cli_data->bbf_ctx.in_param = argv[0]; - err = bbf_entry_method(&client_data->bbf_ctx, BBF_ADD_OBJECT); + err = bbf_entry_method(&cli_data->bbf_ctx, BBF_ADD_OBJECT); if (!err) { - printf("Added %s%s.\n", client_data->bbf_ctx.in_param, client_data->bbf_ctx.addobj_instance); + printf("Added %s%s.\n", cli_data->bbf_ctx.in_param, cli_data->bbf_ctx.addobj_instance); bbf_entry_restart_services(NULL, true); } else { - printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param); + printf("ERROR: %d retrieving %s\n", err, cli_data->bbf_ctx.in_param); bbf_entry_revert_changes(NULL); err = EXIT_FAILURE; } @@ -451,37 +443,37 @@ static int in_dotso_out_cli_exec_add(client_data_t *client_data, char *argv[]) return err; } -static int in_ubus_out_cli_exec_add(client_data_t *client_data, char *argv[]) +static int in_ubus_out_cli_exec_add(cli_data_t *cli_data, char *argv[]) { - return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]); + return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); } -static int cli_exec_add(client_data_t *client_data, char *argv[]) +static int cli_exec_add(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_add(client_data, argv); - else if (strcasecmp(client_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_add(client_data, argv); + if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) + err = in_dotso_out_cli_exec_add(cli_data, argv); + else if (strcasecmp(cli_data->in_type, "UBUS") == 0) + err = in_ubus_out_cli_exec_add(cli_data, argv); else err = EXIT_FAILURE; return err; } -static int in_dotso_out_cli_exec_del(client_data_t *client_data, char *argv[]) +static int in_dotso_out_cli_exec_del(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - client_data->bbf_ctx.in_param = argv[0]; + cli_data->bbf_ctx.in_param = argv[0]; - err = bbf_entry_method(&client_data->bbf_ctx, BBF_DEL_OBJECT); + err = bbf_entry_method(&cli_data->bbf_ctx, BBF_DEL_OBJECT); if (!err) { - printf("Deleted %s\n", client_data->bbf_ctx.in_param); + printf("Deleted %s\n", cli_data->bbf_ctx.in_param); bbf_entry_restart_services(NULL, true); } else { - printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param); + printf("ERROR: %d retrieving %s\n", err, cli_data->bbf_ctx.in_param); bbf_entry_revert_changes(NULL); err = EXIT_FAILURE; } @@ -489,83 +481,83 @@ static int in_dotso_out_cli_exec_del(client_data_t *client_data, char *argv[]) return err; } -static int in_ubus_out_cli_exec_del(client_data_t *client_data, char *argv[]) +static int in_ubus_out_cli_exec_del(cli_data_t *cli_data, char *argv[]) { - return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]); + return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); } -static int cli_exec_del(client_data_t *client_data, char *argv[]) +static int cli_exec_del(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_del(client_data, argv); - else if (strcasecmp(client_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_del(client_data, argv); + if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) + err = in_dotso_out_cli_exec_del(cli_data, argv); + else if (strcasecmp(cli_data->in_type, "UBUS") == 0) + err = in_ubus_out_cli_exec_del(cli_data, argv); else err = EXIT_FAILURE; return err; } -static int in_dotso_out_cli_exec_instances(client_data_t *client_data, char *argv[]) +static int in_dotso_out_cli_exec_instances(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - client_data->bbf_ctx.in_param = argv[0]; - client_data->bbf_ctx.nextlevel = false; + cli_data->bbf_ctx.in_param = argv[0]; + cli_data->bbf_ctx.nextlevel = false; - err = bbf_entry_method(&client_data->bbf_ctx, BBF_INSTANCES); + err = bbf_entry_method(&cli_data->bbf_ctx, BBF_INSTANCES); if (!err) { struct dm_parameter *n; - list_for_each_entry(n, &client_data->bbf_ctx.list_parameter, list) { + list_for_each_entry(n, &cli_data->bbf_ctx.list_parameter, list) { printf("%s\n", n->name); } } else { - printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param); + printf("ERROR: %d retrieving %s\n", err, cli_data->bbf_ctx.in_param); err = EXIT_FAILURE; } return err; } -static int in_ubus_out_cli_exec_instances(client_data_t *client_data, char *argv[]) +static int in_ubus_out_cli_exec_instances(cli_data_t *cli_data, char *argv[]) { - return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]); + return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); } -static int cli_exec_instances(client_data_t *client_data, char *argv[]) +static int cli_exec_instances(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_instances(client_data, argv); - else if (strcasecmp(client_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_instances(client_data, argv); + if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) + err = in_dotso_out_cli_exec_instances(cli_data, argv); + else if (strcasecmp(cli_data->in_type, "UBUS") == 0) + err = in_ubus_out_cli_exec_instances(cli_data, argv); else err = EXIT_FAILURE; return err; } -static int in_dotso_out_cli_exec_schema(client_data_t *client_data, char *argv[]) +static int in_dotso_out_cli_exec_schema(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - client_data->bbf_ctx.in_param = argv[0]; - client_data->bbf_ctx.nextlevel = false; - client_data->bbf_ctx.iscommand = true; - client_data->bbf_ctx.isevent = true; - client_data->bbf_ctx.isinfo = true; + cli_data->bbf_ctx.in_param = argv[0]; + cli_data->bbf_ctx.nextlevel = false; + cli_data->bbf_ctx.iscommand = true; + cli_data->bbf_ctx.isevent = true; + cli_data->bbf_ctx.isinfo = true; - err = bbf_entry_method(&client_data->bbf_ctx, BBF_SCHEMA); + err = bbf_entry_method(&cli_data->bbf_ctx, BBF_SCHEMA); if (!err) { struct dm_parameter *n; - printf("\nDumping %s Schema...\n\n", client_data->bbf_ctx.in_param); + printf("\nDumping %s Schema...\n\n", cli_data->bbf_ctx.in_param); - list_for_each_entry(n, &client_data->bbf_ctx.list_parameter, list) { + list_for_each_entry(n, &cli_data->bbf_ctx.list_parameter, list) { int cmd = get_dm_type(n->type); printf("%s\n", n->name); @@ -605,110 +597,109 @@ static int in_dotso_out_cli_exec_schema(client_data_t *client_data, char *argv[] } } } else { - printf("ERROR: %d retrieving %s\n", err, client_data->bbf_ctx.in_param); + printf("ERROR: %d retrieving %s\n", err, cli_data->bbf_ctx.in_param); err = EXIT_FAILURE; } return err; } -static int in_ubus_out_cli_exec_schema(client_data_t *client_data, char *argv[]) +static int in_ubus_out_cli_exec_schema(cli_data_t *cli_data, char *argv[]) { - return in_ubus_out_cli_exec_cmd(client_data, argv[0], argv[1]); + return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); } -static int cli_exec_schema(client_data_t *client_data, char *argv[]) +static int cli_exec_schema(cli_data_t *cli_data, char *argv[]) { int err = EXIT_SUCCESS; - if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_schema(client_data, argv); - else if (strcasecmp(client_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_schema(client_data, argv); + if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) + err = in_dotso_out_cli_exec_schema(cli_data, argv); + else if (strcasecmp(cli_data->in_type, "UBUS") == 0) + err = in_ubus_out_cli_exec_schema(cli_data, argv); else err = EXIT_FAILURE; return err; } -static int cli_exec_command(client_data_t *client_data, int argc, char *argv[]) +static int cli_exec_command(cli_data_t *cli_data, int argc, char *argv[]) { cli_cmd_t *cli_cmd = NULL; int err = EXIT_SUCCESS; bool registred_command = false; - client_data->cmd = argv[0]; - if (!client_data->cmd || strlen(client_data->cmd) == 0) + cli_data->cmd = argv[0]; + if (!cli_data->cmd || strlen(cli_data->cmd) == 0) return EXIT_FAILURE; - if (strcasecmp(client_data->in_type, "DotSO") == 0 || strcasecmp(client_data->in_type, "JSON") == 0) { + if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) { - if (strcasecmp(client_data->in_type, "DotSO") == 0) { - if (load_dotso_plugin(&client_lib_handle, client_data->in_name, - &CLIENT_DM_ROOT_OBJ, - CLIENT_DM_VENDOR_EXTENSION, - &CLIENT_DM_VENDOR_EXTENSION_EXCLUDE) != 0) { + if (strcasecmp(cli_data->in_type, "DotSO") == 0) { + if (load_dotso_plugin(&cli_lib_handle, cli_data->in_name, + &CLI_DM_ROOT_OBJ, + CLI_DM_VENDOR_EXTENSION, + &CLI_DM_VENDOR_EXTENSION_EXCLUDE) != 0) { err = EXIT_FAILURE; goto end; } } else { - client_data->enable_plugins = false; - if (load_json_plugin(&loaded_json_files, &json_list, &json_memhead, client_data->in_name, - &CLIENT_DM_ROOT_OBJ) != 0) { + if (load_json_plugin(&loaded_json_files, &json_list, &json_memhead, cli_data->in_name, + &CLI_DM_ROOT_OBJ) != 0) { err = EXIT_FAILURE; goto end; } } - if (CLIENT_DM_ROOT_OBJ == NULL) { + if (CLI_DM_ROOT_OBJ == NULL) { err = EXIT_FAILURE; goto end; } - bbf_ctx_init(&client_data->bbf_ctx, CLIENT_DM_ROOT_OBJ, CLIENT_DM_VENDOR_EXTENSION, CLIENT_DM_VENDOR_EXTENSION_EXCLUDE, CLIENT_DM_SERVICES); + bbf_ctx_init(&cli_data->bbf_ctx, CLI_DM_ROOT_OBJ, CLI_DM_VENDOR_EXTENSION, CLI_DM_VENDOR_EXTENSION_EXCLUDE); - client_data->bbf_ctx.dm_type = client_data->proto; - client_data->bbf_ctx.instance_mode = client_data->instance_mode; - client_data->bbf_ctx.enable_plugins = client_data->enable_plugins; - } else if (strcasecmp(client_data->in_type, "UBUS") != 0) { + cli_data->bbf_ctx.dm_type = cli_data->proto; + cli_data->bbf_ctx.instance_mode = cli_data->instance_mode; + cli_data->bbf_ctx.enable_plugins = input_json ? false : true; + } else if (strcasecmp(cli_data->in_type, "UBUS") != 0) { return -1; } for (size_t i = 0; i < ARRAY_SIZE(cli_commands); i++) { cli_cmd = &cli_commands[i]; - if (strcmp(client_data->cmd, cli_cmd->name) == 0) { + if (strcmp(cli_data->cmd, cli_cmd->name) == 0) { if (argc-1 < cli_cmd->num_args) { printf("ERROR: Number of arguments for %s method is wrong(%d), it should be %d\n", cli_cmd->name, argc-1, cli_cmd->num_args); - cli_commands[0].exec_cmd(client_data, NULL); + cli_commands[0].exec_cmd(cli_data, NULL); err = EXIT_FAILURE; goto end; } - err = cli_cmd->exec_cmd(client_data, &argv[1]); + err = cli_cmd->exec_cmd(cli_data, &argv[1]); registred_command = true; break; } } if (!registred_command) { - printf("ERROR: Unknown command: %s\n", client_data->cmd); - cli_commands[0].exec_cmd(client_data, NULL); + printf("ERROR: Unknown command: %s\n", cli_data->cmd); + cli_commands[0].exec_cmd(cli_data, NULL); err = EXIT_FAILURE; } end: - if (strcasecmp(client_data->in_type, "DotSO") == 0) { - if (CLIENT_DM_ROOT_OBJ) { - bbf_ctx_clean(&client_data->bbf_ctx); - bbf_global_clean(CLIENT_DM_ROOT_OBJ); + if (strcasecmp(cli_data->in_type, "DotSO") == 0) { + if (CLI_DM_ROOT_OBJ) { + bbf_ctx_clean(&cli_data->bbf_ctx); + bbf_global_clean(CLI_DM_ROOT_OBJ); } - free_dotso_plugin(client_lib_handle); - } else if (strcasecmp(client_data->in_type, "JSON") == 0) { - if (CLIENT_DM_ROOT_OBJ) { - bbf_ctx_clean(&client_data->bbf_ctx); - bbf_global_clean(CLIENT_DM_ROOT_OBJ); + free_dotso_plugin(cli_lib_handle); + } else if (strcasecmp(cli_data->in_type, "JSON") == 0) { + if (CLI_DM_ROOT_OBJ) { + bbf_ctx_clean(&cli_data->bbf_ctx); + bbf_global_clean(CLI_DM_ROOT_OBJ); } free_json_plugin(); } @@ -716,14 +707,14 @@ end: return err; } -int bbfdm_cli_exec_command(const char *json_path, int argc, char *argv[]) +int bbfdm_cli_exec_command(int argc, char *argv[]) { - client_data_t client_data = {0}; + cli_data_t cli_data = {0}; int err = EXIT_SUCCESS; - memset(&client_data, 0, sizeof(client_data_t)); + memset(&cli_data, 0, sizeof(cli_data_t)); - err = bbfdm_load_client_config(json_path, &client_data); + err = bbfdm_load_cli_config(&cli_data); if (err) return EXIT_FAILURE; @@ -733,11 +724,11 @@ int bbfdm_cli_exec_command(const char *json_path, int argc, char *argv[]) return EXIT_FAILURE; } - err = cli_exec_command(&client_data, argc, argv); + err = cli_exec_command(&cli_data, argc, argv); - if (client_json_obj) { - json_object_put(client_json_obj); - client_json_obj = NULL; + if (cli_json_obj) { + json_object_put(cli_json_obj); + cli_json_obj = NULL; } return err; } diff --git a/bbfdmd/src/cli.h b/bbfdmd/src/cli.h index 6af42898..e933f247 100644 --- a/bbfdmd/src/cli.h +++ b/bbfdmd/src/cli.h @@ -20,4 +20,4 @@ * 02110-1301 USA */ -int bbfdm_cli_exec_command(const char *json_path, int argc, char *argv[]); +int bbfdm_cli_exec_command(int argc, char *argv[]); diff --git a/bbfdmd/src/common.h b/bbfdmd/src/common.h index f886b20a..8b6f3083 100644 --- a/bbfdmd/src/common.h +++ b/bbfdmd/src/common.h @@ -20,6 +20,7 @@ #define BBF_ADD_EVENT "AddObj" #define BBF_DEL_EVENT "DelObj" #define BBF_EVENT "event" +#define BBF_JSON_INPUT "/etc/bbfdm/input.json" #define MAX_DM_KEY_LEN 256 #define MAX_DM_PATH 1024 @@ -39,7 +40,6 @@ extern DMOBJ *DEAMON_DM_ROOT_OBJ; extern DM_MAP_VENDOR *DEAMON_DM_VENDOR_EXTENSION[2]; extern DM_MAP_VENDOR_EXCLUDE *DEAMON_DM_VENDOR_EXTENSION_EXCLUDE; -extern json_object *DEAMON_DM_SERVICES; bool match(const char *string, const char *pattern); bool is_str_eq(const char *s1, const char *s2); diff --git a/bbfdmd/src/events.c b/bbfdmd/src/events.c index 31ab855f..82408133 100644 --- a/bbfdmd/src/events.c +++ b/bbfdmd/src/events.c @@ -27,7 +27,7 @@ #include extern char UBUS_METHOD_NAME[32]; -extern bool enable_plugins; +extern char *input_json; static struct event_map_list ev_map_list[] = { /* { event name, DM Path, .arguments[] = { event_args, dm_args } } */ @@ -275,7 +275,7 @@ bool is_registered_event(char *name) .iscommand = false, .isevent = true, .isinfo = false, - .enable_plugins = enable_plugins, + .enable_plugins = input_json ? false : true, .instance_mode = INSTANCE_MODE_NUMBER, .dm_type = BBFDM_USP }; diff --git a/bbfdmd/src/get_helper.c b/bbfdmd/src/get_helper.c index 9a12ba50..bc67a9e7 100644 --- a/bbfdmd/src/get_helper.c +++ b/bbfdmd/src/get_helper.c @@ -35,7 +35,6 @@ DMOBJ *DEAMON_DM_ROOT_OBJ = NULL; DM_MAP_VENDOR *DEAMON_DM_VENDOR_EXTENSION[2] = {0}; DM_MAP_VENDOR_EXCLUDE *DEAMON_DM_VENDOR_EXTENSION_EXCLUDE = NULL; -json_object *DEAMON_DM_SERVICES = NULL; // uloop.h does not have versions, below line is to use // deprecated uloop_timeout_remaining for the time being @@ -90,7 +89,7 @@ void bb_add_string(struct blob_buf *bb, const char *name, const char *value) void bbf_init(struct dmctx *dm_ctx) { - bbf_ctx_init(dm_ctx, DEAMON_DM_ROOT_OBJ, DEAMON_DM_VENDOR_EXTENSION, DEAMON_DM_VENDOR_EXTENSION_EXCLUDE, DEAMON_DM_SERVICES); + bbf_ctx_init(dm_ctx, DEAMON_DM_ROOT_OBJ, DEAMON_DM_VENDOR_EXTENSION, DEAMON_DM_VENDOR_EXTENSION_EXCLUDE); } void bbf_cleanup(struct dmctx *dm_ctx) diff --git a/gitlab-ci/bbfdmd-functional-test.sh b/gitlab-ci/bbfdmd-functional-test.sh index 90970479..a455633c 100755 --- a/gitlab-ci/bbfdmd-functional-test.sh +++ b/gitlab-ci/bbfdmd-functional-test.sh @@ -56,9 +56,10 @@ gcovr -r . --xml -o ./funl-test-coverage.xml gcovr -r . date +%s > timestamp.log -echo "Checking memory leaks..." -grep -q "Leak" /tmp/memory-report.xml -error_on_zero $? +check_valgrind_xml "Main Service bbfdmd" "/tmp/memory-report.xml" +check_valgrind_xml "Micro Service bbfdm_dataelementsd" "/tmp/memory-report-dataelements.xml" +check_valgrind_xml "Micro Service bbfdm_bulkdatad" "/tmp/memory-report-bulkdata.xml" +check_valgrind_xml "Micro Service bbfdm_periodicstatsd" "/tmp/memory-report-periodicstats.xml" if [ "${fault}" -ne 0 ]; then echo "Failed running ubus-api-validator fault[$fault]" diff --git a/gitlab-ci/install-dependencies.sh b/gitlab-ci/install-dependencies.sh index 8298b622..ac33c8e4 100755 --- a/gitlab-ci/install-dependencies.sh +++ b/gitlab-ci/install-dependencies.sh @@ -20,7 +20,7 @@ install_libwifi_dataelements ${1} # Install datamodel plugins only when pipeline trigger for bbfdm if [ -z "${1}" ]; then - git clone -b devel --depth 1 https://dev.iopsys.eu/feed/iopsys.git /opt/dev/iopsys + git clone -b service_registration --depth 1 https://dev.iopsys.eu/feed/iopsys.git /opt/dev/iopsys git clone -b devel --depth 1 https://dev.iopsys.eu/bbf/bulkdata.git /opt/dev/bulkdata cp -f /opt/dev/iopsys/urlfilter/files/etc/bbfdm/json/urlfilter.json /etc/bbfdm/json @@ -28,7 +28,10 @@ if [ -z "${1}" ]; then cp -f /opt/dev/iopsys/obuspa/files/etc/bbfdm/json/TransferComplete.json /etc/bbfdm/json cp -f /opt/dev/iopsys/icwmp/files/etc/bbfdm/json/CWMPManagementServer.json /etc/bbfdm/json cp -f /opt/dev/iopsys/ponmngr/files/etc/bbfdm/json/xpon.json /etc/bbfdm/json - cp -f /opt/dev/bulkdata/bbf_plugin/bulkdata.json /etc/bbfdm/json + + mkdir -p /etc/bbfdm/services/bulkdata + cp -f /opt/dev/bulkdata/bbf_plugin/bulkdata.json /etc/bbfdm/services/bulkdata + cp -f /opt/dev/iopsys/bulkdata/files/etc/bbfdm/services/bulkdata/input.json /etc/bbfdm/services/bulkdata # install usermngr plugin install_libusermngr diff --git a/gitlab-ci/iopsys-supervisord.conf b/gitlab-ci/iopsys-supervisord.conf index 98963bcc..fc7573a6 100755 --- a/gitlab-ci/iopsys-supervisord.conf +++ b/gitlab-ci/iopsys-supervisord.conf @@ -6,7 +6,7 @@ priority=1 command=/bin/bash -c "/usr/sbin/ubusd" [program:rpcd] -autorestart=true +autorestart=false numprocs_start=1 startretries=0 priority=2 @@ -24,4 +24,18 @@ autorestart=false numprocs_start=3 startretries=0 priority=4 -command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-report-dataelements.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/bbfdmd -I /tmp/wifi_dataelements.json" +command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-report-dataelements.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/bbfdmd -m /tmp/wifi_dataelements.json" + +[program:bbfdm_bulkdatad] +autorestart=false +numprocs_start=4 +startretries=0 +priority=5 +command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-report-bulkdata.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/bbfdmd -m /etc/bbfdm/services/bulkdata/input.json" + +[program:bbfdm_periodicstatsd] +autorestart=false +numprocs_start=5 +startretries=0 +priority=6 +command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/tmp/memory-report-periodicstats.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /usr/sbin/bbfdmd -m /etc/bbfdm/services/periodicstats/input.json" diff --git a/gitlab-ci/memory-test.sh b/gitlab-ci/memory-test.sh index 5081e722..259a8cf6 100755 --- a/gitlab-ci/memory-test.sh +++ b/gitlab-ci/memory-test.sh @@ -44,6 +44,8 @@ run_valgrind_redirect -c get Device. run_valgrind_redirect -c schema Device. +run_valgrind_verbose -c get Device.BulkData. + run_valgrind_verbose -c get Device.RootDataModelVersion run_valgrind_verbose -c get Device.IP.Interface.*.IPv6Address.*.IPAddress diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh index e1df686c..f07df97d 100755 --- a/gitlab-ci/shared.sh +++ b/gitlab-ci/shared.sh @@ -68,7 +68,7 @@ function install_libbbf() mkdir -p build cd build - cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS" -DBBFDMD_ENABLED=ON -DBBF_TR181=ON -DBBF_TR104=ON -DBBF_TR143=ON -DWITH_OPENSSL=ON -DBBF_JSON_PLUGIN=ON -DBBF_DOTSO_PLUGIN=ON -DBBF_VENDOR_EXTENSION=ON -DBBF_WIFI_DATAELEMENTS=OFF -DBBF_VENDOR_LIST="$VENDOR_LIST" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/ + cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS" -DWITH_OPENSSL=ON -DBBF_JSON_PLUGIN=ON -DBBF_DOTSO_PLUGIN=ON -DBBF_VENDOR_EXTENSION=ON -DBBF_WIFI_DATAELEMENTS=OFF -DBBF_VENDOR_LIST="$VENDOR_LIST" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/ exec_cmd_verbose make echo "installing libbbf" @@ -102,7 +102,6 @@ function install_libwifi_dataelements() exec_cmd_verbose make -C test/wifi_dataelements/ echo "installing libwifi_dataelements" - cp -f test/wifi_dataelements/input.json /etc/bbfdm/input.json cp -f test/wifi_dataelements/wifi_dataelements.json /tmp/wifi_dataelements.json cp -f test/wifi_dataelements/libwifi_dataelements.so /tmp/libwifi_dataelements.so } @@ -118,7 +117,9 @@ function install_libperiodicstats() exec_cmd_verbose make -C /opt/dev/periodicstats/ echo "installing libperiodicstats" - cp -f /opt/dev/periodicstats/bbf_plugin/libperiodicstats.so /usr/lib/bbfdm + mkdir -p /etc/bbfdm/services/periodicstats + cp -f /opt/dev/periodicstats/bbf_plugin/libperiodicstats.so /etc/bbfdm/services/periodicstats + cp -f /opt/dev/iopsys/periodicstats/files/etc/bbfdm/services/periodicstats/input.json /etc/bbfdm/services/periodicstats } function install_libcwmpdm() @@ -148,6 +149,21 @@ function error_on_zero() } +function check_valgrind_xml() { + echo "${1}: Checking memory leaks..." + echo "checking UninitCondition" + grep -q "UninitCondition" ${2} + error_on_zero $? + + echo "checking Leak_PossiblyLost" + grep -q "Leak_PossiblyLost" ${2} + error_on_zero $? + + echo "checking Leak_DefinitelyLost" + grep -q "Leak_DefinitelyLost" ${2} + error_on_zero $? +} + function generate_report() { exec_cmd tap-junit --name "${1}" --input "${2}" --output report diff --git a/json/input.json b/json/input.json index 40077b2d..123bc9f4 100755 --- a/json/input.json +++ b/json/input.json @@ -1,21 +1,7 @@ { "daemon": { "config": { - "refresh_time": 10, - "enable_plugins": 1 }, - "services": [ - { - "ubus_obj": "bbfdm.bulkdata", - "obj_mount": "Device.", - "obj_name": "BulkData" - }, - { - "ubus_obj": "bbfdm.periodicstats", - "obj_mount": "Device.", - "obj_name": "PeriodicStatistics" - } - ], "input": { "type": "DotSo", "name": "/lib/libbbfdm.so" @@ -25,11 +11,10 @@ "name": "bbfdm" } }, - "client": { + "cli": { "config": { "proto": "both", - "instance_mode": 0, - "enable_plugins": 0 + "instance_mode": 0 }, "input": { "type": "UBUS", diff --git a/libbbfdm-api/dmapi.h b/libbbfdm-api/dmapi.h index 69b41f0a..afcab7b7 100644 --- a/libbbfdm-api/dmapi.h +++ b/libbbfdm-api/dmapi.h @@ -177,7 +177,6 @@ struct dmctx { DMOBJ *dm_entryobj; DM_MAP_VENDOR *dm_vendor_extension[2]; DM_MAP_VENDOR_EXCLUDE *dm_vendor_extension_exclude; - json_object *services_obj; bool nextlevel; bool iswildcard; int faultcode; diff --git a/libbbfdm-api/dmentry.c b/libbbfdm-api/dmentry.c index 0ee18d3f..6a08d071 100644 --- a/libbbfdm-api/dmentry.c +++ b/libbbfdm-api/dmentry.c @@ -22,15 +22,13 @@ LIST_HEAD(global_memhead); void bbf_ctx_init(struct dmctx *ctx, DMOBJ *tEntryObj, DM_MAP_VENDOR *tVendorExtension[], - DM_MAP_VENDOR_EXCLUDE *tVendorExtensionExclude, - json_object *services_obj) + DM_MAP_VENDOR_EXCLUDE *tVendorExtensionExclude) { INIT_LIST_HEAD(&ctx->list_parameter); ctx->dm_entryobj = tEntryObj; ctx->dm_vendor_extension[0] = tVendorExtension ? tVendorExtension[0] : NULL; ctx->dm_vendor_extension[1] = tVendorExtension ? tVendorExtension[1] : NULL; ctx->dm_vendor_extension_exclude = tVendorExtensionExclude; - ctx->services_obj = services_obj; dm_uci_init(); } diff --git a/libbbfdm-api/dmentry.h b/libbbfdm-api/dmentry.h index 17d4ed08..6256ba54 100644 --- a/libbbfdm-api/dmentry.h +++ b/libbbfdm-api/dmentry.h @@ -17,8 +17,7 @@ void bbf_ctx_init(struct dmctx *ctx, DMOBJ *tEntryObj, DM_MAP_VENDOR *tVendorExtension[], - DM_MAP_VENDOR_EXCLUDE *tVendorExtensionExclude, - json_object *services_obj); + DM_MAP_VENDOR_EXCLUDE *tVendorExtensionExclude); void bbf_ctx_clean(struct dmctx *ctx); void bbf_ctx_init_sub(struct dmctx *ctx, DMOBJ *tEntryObj, @@ -40,4 +39,8 @@ int adm_entry_get_linker_value(struct dmctx *ctx, char *param, char **value); void bbf_entry_restart_services(struct blob_buf *bb, bool restart_services); void bbf_entry_revert_changes(struct blob_buf *bb); +void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf *bb); +bool load_service(DMOBJ *main_dm, struct list_head *srv_list, char *srv_name, char *srv_parent_dm, char *srv_obj); +void free_services_from_list(struct list_head *clist); + #endif //__DMENTRY_H__ diff --git a/libbbfdm-api/dmplugin.c b/libbbfdm-api/dmplugin.c index 9ed7d37b..f78a7bfa 100644 --- a/libbbfdm-api/dmplugin.c +++ b/libbbfdm-api/dmplugin.c @@ -29,6 +29,14 @@ static bool first_boot = false; extern struct list_head global_memhead; +struct service +{ + struct list_head list; + char *name; + char *parent_dm; + char *object; +}; + #if defined(BBFDM_ENABLE_JSON_PLUGIN) || defined(BBFDM_ENABLE_DOTSO_PLUGIN) static char *get_folder_path(bool json_path) { @@ -109,58 +117,106 @@ static bool check_stats_folder(bool json_path) } #endif /* (BBFDM_ENABLE_JSON_PLUGIN || BBFDM_ENABLE_DOTSO_PLUGIN) */ -static void load_services(struct dmctx *ctx) + +static bool add_service_to_main_tree(DMOBJ *main_dm, char *srv_name, char *srv_parent_dm, char *srv_obj) { - json_object *service = NULL; + DMOBJ *dm_entryobj = NULL; - if (!ctx->services_obj) - return; + bool obj_exists = find_entry_obj(main_dm, srv_parent_dm, &dm_entryobj); + if (obj_exists == false || !dm_entryobj) + return false; - size_t nbre_services = json_object_array_length(ctx->services_obj); + if (dm_entryobj->nextdynamicobj == NULL) { + dm_entryobj->nextdynamicobj = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj)); + dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].idx_type = INDX_JSON_MOUNT; + dm_entryobj->nextdynamicobj[INDX_LIBRARY_MOUNT].idx_type = INDX_LIBRARY_MOUNT; + dm_entryobj->nextdynamicobj[INDX_VENDOR_MOUNT].idx_type = INDX_VENDOR_MOUNT; + dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].idx_type = INDX_SERVICE_MOUNT; + } - for (size_t i = 0; i < nbre_services; i++) { - service = json_object_array_get_idx(ctx->services_obj, i); + if (dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj == NULL) { + dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj = calloc(2, sizeof(DMOBJ *)); + } - char *obj_mount = dmjson_get_value(service, 1, "obj_mount"); - if (DM_STRLEN(obj_mount) == 0) - continue; + if (dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] == NULL) { + dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] = dm_dynamic_calloc(&global_memhead, 2, sizeof(struct dm_obj_s)); + ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).obj = dm_dynamic_strdup(&global_memhead, srv_obj); + ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).checkdep = dm_dynamic_strdup(&global_memhead, srv_name); + } else { + int idx = get_entry_idx(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0]); + dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] = dm_dynamic_realloc(&global_memhead, dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0], (idx + 2) * sizeof(struct dm_obj_s)); + memset(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s)); + ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[idx]).obj = dm_dynamic_strdup(&global_memhead, srv_obj); + ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[idx]).checkdep = dm_dynamic_strdup(&global_memhead, srv_name); + } - char *obj_name = dmjson_get_value(service, 1, "obj_name"); - if (DM_STRLEN(obj_name) == 0) - continue; + return true; +} - char *ubus_obj = dmjson_get_value(service, 1, "ubus_obj"); - if (DM_STRLEN(ubus_obj) == 0) - continue; +static bool is_service_registered(struct list_head *srvlist, char *srv_name) +{ + struct service *srv = NULL; - DMOBJ *dm_entryobj = NULL; - bool obj_exists = find_entry_obj(ctx->dm_entryobj, obj_mount, &dm_entryobj); - if (obj_exists == false || !dm_entryobj) - continue; + list_for_each_entry(srv, srvlist, list) { + if (DM_STRCMP(srv->name, srv_name) == 0) + return true; + } - if (dm_entryobj->nextdynamicobj == NULL) { - dm_entryobj->nextdynamicobj = calloc(__INDX_DYNAMIC_MAX, sizeof(struct dm_dynamic_obj)); - dm_entryobj->nextdynamicobj[INDX_JSON_MOUNT].idx_type = INDX_JSON_MOUNT; - dm_entryobj->nextdynamicobj[INDX_LIBRARY_MOUNT].idx_type = INDX_LIBRARY_MOUNT; - dm_entryobj->nextdynamicobj[INDX_VENDOR_MOUNT].idx_type = INDX_VENDOR_MOUNT; - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].idx_type = INDX_SERVICE_MOUNT; - } + return false; +} - if (dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj == NULL) { - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj = calloc(2, sizeof(DMOBJ *)); - } +static void add_service_to_list(struct list_head *srvlist, char *srv_name, char *srv_parent_dm, char *srv_object) +{ + struct service *srv = NULL; - if (dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] == NULL) { - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] = dm_dynamic_calloc(&global_memhead, 2, sizeof(struct dm_obj_s)); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).obj = dm_dynamic_strdup(&global_memhead, obj_name); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[0]).checkdep = dm_dynamic_strdup(&global_memhead, ubus_obj); - } else { - int idx = get_entry_idx(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0]); - dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] = dm_dynamic_realloc(&global_memhead, dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0], (idx + 2) * sizeof(struct dm_obj_s)); - memset(dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0] + (idx + 1), 0, sizeof(struct dm_obj_s)); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[idx]).obj = dm_dynamic_strdup(&global_memhead, obj_name); - ((dm_entryobj->nextdynamicobj[INDX_SERVICE_MOUNT].nextobj[0])[idx]).checkdep = dm_dynamic_strdup(&global_memhead, ubus_obj); - } + srv = calloc(1, sizeof(struct service)); + list_add_tail(&srv->list, srvlist); + + srv->name = strdup(srv_name); + srv->parent_dm = strdup(srv_parent_dm); + srv->object = strdup(srv_object); +} + +void free_services_from_list(struct list_head *clist) +{ + struct service *srv = NULL; + + while (clist->next != clist) { + srv = list_entry(clist->next, struct service, list); + list_del(&srv->list); + free(srv->name); + free(srv->parent_dm); + free(srv->object); + free(srv); + } +} + +bool load_service(DMOBJ *main_dm, struct list_head *srv_list, char *srv_name, char *srv_parent_dm, char *srv_obj) +{ + if (!main_dm || !srv_list || !srv_name || !srv_parent_dm || !srv_obj) + return false; + + if (is_service_registered(srv_list, srv_name)) + return false; + + if (!add_service_to_main_tree(main_dm, srv_name, srv_parent_dm, srv_obj)) + return false; + + add_service_to_list(srv_list, srv_name, srv_parent_dm, srv_obj); + return true; +} + +void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf *bb) +{ + struct service *srv = NULL; + void *table = NULL; + + list_for_each_entry(srv, srvlist, list) { + table = blobmsg_open_table(bb, NULL); + blobmsg_add_string(bb, "name", srv->name); + blobmsg_add_string(bb, "parent_dm", srv->parent_dm); + blobmsg_add_string(bb, "object", srv->object); + blobmsg_close_table(bb, table); } } @@ -378,12 +434,6 @@ void load_plugins(struct dmctx *ctx) #endif /* BBF_VENDOR_EXTENSION */ } - if (first_boot == false) { - // Load main objects exposed via services section - free_specific_dynamic_node(ctx->dm_entryobj, INDX_SERVICE_MOUNT); - load_services(ctx); - } - first_boot = true; } diff --git a/libbbfdm/CMakeLists.txt b/libbbfdm/CMakeLists.txt index 29e6cbd3..697ea41e 100644 --- a/libbbfdm/CMakeLists.txt +++ b/libbbfdm/CMakeLists.txt @@ -57,16 +57,19 @@ ENDIF(BBF_TR471) IF(WITH_WOLFSSL) SET(SSL_LIBS wolfssl) + SET(CRYPTO_LIBS crypto) add_compile_definitions(LWOLFSSL) ENDIF(WITH_WOLFSSL) IF(WITH_OPENSSL) SET(SSL_LIBS ssl) + SET(CRYPTO_LIBS crypto) add_compile_definitions(LOPENSSL) ENDIF(WITH_OPENSSL) IF(WITH_MBEDTLS) SET(SSL_LIBS mbedtls) + SET(CRYPTO_LIBS mbedcrypto) add_compile_definitions(LMBEDTLS) ENDIF(WITH_MBEDTLS) @@ -90,7 +93,7 @@ ENDIF(BBF_VENDOR_EXTENSION) ADD_LIBRARY(bbfdm SHARED ${BBF_DM_SOURCES} ${BBF_TR181_SOURCES} ${BBF_TR104_SOURCES} ${BBF_TR143_SOURCES} ${BBF_TR471_SOURCES} ${BBF_VENDOR_EXTENSION_SOURCES}) -TARGET_LINK_LIBRARIES(bbfdm uci ubus ubox json-c blobmsg_json curl bbfdm-api ${SSL_LIBS}) +TARGET_LINK_LIBRARIES(bbfdm uci ubus ubox json-c blobmsg_json curl bbfdm-api ${SSL_LIBS} ${CRYPTO_LIBS}) INSTALL(TARGETS bbfdm LIBRARY DESTINATION usr/lib) diff --git a/libbbfdm/dmtree/tr181/routing.c b/libbbfdm/dmtree/tr181/routing.c index 71e800af..8f40e63b 100644 --- a/libbbfdm/dmtree/tr181/routing.c +++ b/libbbfdm/dmtree/tr181/routing.c @@ -1008,9 +1008,9 @@ static int get_RoutingRouteInformationInterfaceSetting_Interface(char *refparam, snprintf(cmd, sizeof(cmd), "ip -6 route show"); - FILE *pp = fopen(PROC_ROUTE6, "r"); - if (pp != NULL) { - while (fgets(line, MAX_ROUTE_LEN, pp) != NULL) { + FILE *fp = fopen(PROC_ROUTE6, "r"); + if (fp != NULL) { + while (fgets(line, MAX_ROUTE_LEN, fp) != NULL) { remove_new_line(line); if (parse_route6_line(line, &route6)) @@ -1020,7 +1020,7 @@ static int get_RoutingRouteInformationInterfaceSetting_Interface(char *refparam, break; } - pclose(pp); + fclose(fp); } if (DM_STRLEN(route6.iface)) { diff --git a/schemas/ubus/bbfdm.json b/schemas/ubus/bbfdm.json index 4fa9d7ca..0ba881a8 100644 --- a/schemas/ubus/bbfdm.json +++ b/schemas/ubus/bbfdm.json @@ -99,6 +99,13 @@ "status" ] }, + "srv_type_t": { + "type": "string", + "enum": [ + "register", + "list" + ] + }, "format_t": { "type": "string", "default": "pretty", @@ -779,6 +786,53 @@ "output" ] }, + "service": { + "title": "Register a micro-service in the main service", + "type": "object", + "properties": { + "input": { + "type": "object", + "properties": { + "cmd": { + "$ref": "#/definitions/srv_type_t" + }, + "name": { + "type": "string", + "description": "Name of the micro-service ubus object" + }, + "parent_dm": { + "type": "string", + "description": "Object path where the micro-service object will be added" + }, + "object": { + "type": "string", + "description": "Name of the micro-service object" + } + }, + "required": [ + "cmd" + ] + }, + "output": { + "type": "object", + "properties": { + "status": { + "type": "boolean" + }, + "error": { + "type": "string" + } + }, + "required": [ + "status" + ] + } + }, + "required": [ + "input", + "output" + ] + }, "notify_event": { "title": "notify occurance of an event on ubus", "type": "object", diff --git a/test/cmocka/functional_test_bbfd.c b/test/cmocka/functional_test_bbfd.c index e7e2cfff..134815bd 100644 --- a/test/cmocka/functional_test_bbfd.c +++ b/test/cmocka/functional_test_bbfd.c @@ -23,7 +23,7 @@ static int setup(void **state) if (!ctx) return -1; - bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE, NULL); + bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); // Enable Plugins ctx->enable_plugins = true; diff --git a/test/cmocka/unit_test_bbfd.c b/test/cmocka/unit_test_bbfd.c index 02bd2c78..a7c58b90 100644 --- a/test/cmocka/unit_test_bbfd.c +++ b/test/cmocka/unit_test_bbfd.c @@ -28,7 +28,7 @@ static int setup(void **state) if (!ctx) return -1; - bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE, NULL); + bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); // Enable Plugins ctx->enable_plugins = true; @@ -594,7 +594,7 @@ static void test_api_bbfdm_json_get_value(void **state) assert_true(&first_entry->list != &ctx->list_parameter); bbf_ctx_clean_sub(ctx); - bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE, NULL); + bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); // Enable Plugins ctx->enable_plugins = true; @@ -610,7 +610,7 @@ static void test_api_bbfdm_json_get_value(void **state) assert_true(&first_entry->list != &ctx->list_parameter); bbf_ctx_clean_sub(ctx); - bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE, NULL); + bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); // Enable Plugins ctx->enable_plugins = true; @@ -690,7 +690,7 @@ static void test_api_bbfdm_library_get_value(void **state) assert_true(&first_entry->list != &ctx->list_parameter); bbf_ctx_clean_sub(ctx); - bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE, NULL); + bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); // Enable Plugins ctx->enable_plugins = true; @@ -704,7 +704,7 @@ static void test_api_bbfdm_library_get_value(void **state) assert_true(&first_entry->list != &ctx->list_parameter); bbf_ctx_clean_sub(ctx); - bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE, NULL); + bbf_ctx_init(ctx, TR181_ROOT_TREE, TR181_VENDOR_EXTENSION, TR181_VENDOR_EXTENSION_EXCLUDE); // Enable Plugins ctx->enable_plugins = true; diff --git a/test/wifi_dataelements/input.json b/test/wifi_dataelements/input.json deleted file mode 100755 index 70e7267b..00000000 --- a/test/wifi_dataelements/input.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "daemon": { - "config": { - "refresh_time": 10, - "enable_plugins": 1 - }, - "services": [ - { - "ubus_obj": "bbfdm.dataelements", - "obj_mount": "Device.WiFi.", - "obj_name": "DataElements" - } - ], - "input": { - "type": "DotSo", - "name": "/lib/libbbfdm.so" - }, - "output": { - "type": "UBUS", - "name": "bbfdm" - } - }, - "client": { - "config": { - "proto": "both", - "instance_mode": 0, - "enable_plugins": 0 - }, - "input": { - "type": "UBUS", - "name": "bbfdm" - }, - "output": { - "type": "CLI" - } - } -} diff --git a/test/wifi_dataelements/wifi_dataelements.json b/test/wifi_dataelements/wifi_dataelements.json index e507ea2a..f9348f54 100755 --- a/test/wifi_dataelements/wifi_dataelements.json +++ b/test/wifi_dataelements/wifi_dataelements.json @@ -1,30 +1,15 @@ { "daemon": { - "config": { - "refresh_time": 3600, - "enable_plugins": 0 - }, "input": { "type": "DotSo", "name": "/tmp/libwifi_dataelements.so" }, "output": { "type": "UBUS", - "name": "bbfdm.dataelements" - } - }, - "client": { - "config": { - "proto": "both", - "instance_mode": 0, - "enable_plugins": 0 - }, - "input": { - "type": "UBUS", - "name": "bbfdm.dataelements" - }, - "output": { - "type": "CLI" + "name": "bbfdm.dataelements", + "parent_dm": "Device.WiFi.", + "object": "DataElements", + "root_obj": "bbfdm" } } }