mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2026-03-14 05:00:58 +01:00
Signal handler for microservice
This commit is contained in:
parent
7ddd1064e4
commit
9d93c075af
7 changed files with 297 additions and 168 deletions
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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[]);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@
|
|||
#include "get_helper.h"
|
||||
#include <libubus.h>
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue