mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2025-12-10 07:44:39 +01:00
Redesign the handling of references based on uci instance_db
This commit is contained in:
parent
e3757b5f37
commit
8389f3d9bd
20 changed files with 288 additions and 531 deletions
|
|
@ -56,7 +56,7 @@ static int bbfdm_handler_async(struct ubus_context *ctx, struct ubus_object *obj
|
||||||
return UBUS_STATUS_UNKNOWN_ERROR;
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name);
|
BBFDM_INFO("START: ubus method|%s|, name|%s|", method, obj->name);
|
||||||
|
|
||||||
snprintf(context->requested_path, sizeof(context->requested_path), "%s", blobmsg_get_string(tb[BBFDM_PATH]));
|
snprintf(context->requested_path, sizeof(context->requested_path), "%s", blobmsg_get_string(tb[BBFDM_PATH]));
|
||||||
snprintf(context->ubus_method, sizeof(context->ubus_method), "%s", method);
|
snprintf(context->ubus_method, sizeof(context->ubus_method), "%s", method);
|
||||||
|
|
@ -66,13 +66,6 @@ static int bbfdm_handler_async(struct ubus_context *ctx, struct ubus_object *obj
|
||||||
memset(&context->tmp_bb, 0, sizeof(struct blob_buf));
|
memset(&context->tmp_bb, 0, sizeof(struct blob_buf));
|
||||||
blob_buf_init(&context->tmp_bb, 0);
|
blob_buf_init(&context->tmp_bb, 0);
|
||||||
|
|
||||||
if (strcmp(method, "get") == 0) {
|
|
||||||
INIT_LIST_HEAD(&context->linker_list);
|
|
||||||
|
|
||||||
// Send linker cleanup event for all services
|
|
||||||
send_linker_cleanup_event(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
fill_optional_input(tb[BBFDM_INPUT], &requested_proto, &context->raw_format);
|
fill_optional_input(tb[BBFDM_INPUT], &requested_proto, &context->raw_format);
|
||||||
|
|
||||||
ubus_defer_request(ctx, req, &context->request_data);
|
ubus_defer_request(ctx, req, &context->request_data);
|
||||||
|
|
|
||||||
|
|
@ -111,33 +111,6 @@ static void sync_callback(struct ubus_request *req, int type __attribute__((unus
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void generate_reference_to_set(const char *in_value, char *output_str, size_t output_str_len)
|
|
||||||
{
|
|
||||||
char token_buffer[MAX_VALUE_LENGTH] = {0};
|
|
||||||
char *token = NULL, *saveptr = NULL;
|
|
||||||
unsigned pos = 0;
|
|
||||||
|
|
||||||
if (!output_str || output_str_len == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
output_str[0] = '\0'; // Ensure output buffer is initialized
|
|
||||||
|
|
||||||
if (!in_value || in_value[0] == '\0') // Empty value, nothing to make
|
|
||||||
return;
|
|
||||||
|
|
||||||
bbfdm_strncpy(token_buffer, in_value, sizeof(token_buffer));
|
|
||||||
|
|
||||||
for (token = strtok_r(token_buffer, ",", &saveptr); token; token = strtok_r(NULL, ",", &saveptr)) {
|
|
||||||
char *reference_value = get_reference_data(token, "reference_value");
|
|
||||||
pos += snprintf(&output_str[pos], output_str_len - pos, "%s=>%s##,", token, reference_value ? reference_value : "");
|
|
||||||
BBFDM_FREE(reference_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos > 0) {
|
|
||||||
output_str[pos - 1] = 0; // Remove trailing comma
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_attr *msg, struct blob_buf *bb_response)
|
void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_attr *msg, struct blob_buf *bb_response)
|
||||||
{
|
{
|
||||||
struct blob_buf req_buf = {0};
|
struct blob_buf req_buf = {0};
|
||||||
|
|
@ -151,37 +124,7 @@ void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_at
|
||||||
blob_buf_init(&req_buf, 0);
|
blob_buf_init(&req_buf, 0);
|
||||||
|
|
||||||
blob_for_each_attr(attr, msg, remaining) {
|
blob_for_each_attr(attr, msg, remaining) {
|
||||||
if (strcmp(ubus_method, "set") == 0 &&
|
blobmsg_add_field(&req_buf, blobmsg_type(attr), blobmsg_name(attr), blobmsg_data(attr), blobmsg_len(attr));
|
||||||
strcmp(blobmsg_name(attr), "value") == 0 &&
|
|
||||||
blobmsg_type(attr) == BLOBMSG_TYPE_STRING &&
|
|
||||||
strncmp(BBFDM_ROOT_OBJECT, blobmsg_get_string(attr), strlen(BBFDM_ROOT_OBJECT)) == 0) {
|
|
||||||
char reference_to_set[MAX_VALUE_LENGTH] = {0};
|
|
||||||
|
|
||||||
generate_reference_to_set(blobmsg_get_string(attr), reference_to_set, sizeof(reference_to_set));
|
|
||||||
blobmsg_add_string(&req_buf, blobmsg_name(attr), reference_to_set);
|
|
||||||
} if (strcmp(ubus_method, "set") == 0 &&
|
|
||||||
strcmp(blobmsg_name(attr), "obj_path") == 0 &&
|
|
||||||
blobmsg_type(attr) == BLOBMSG_TYPE_TABLE) {
|
|
||||||
struct blob_attr *__attr = NULL;
|
|
||||||
int rem = 0;
|
|
||||||
|
|
||||||
void *table = blobmsg_open_table(&req_buf, "obj_path");
|
|
||||||
|
|
||||||
blobmsg_for_each_attr(__attr, attr, rem) {
|
|
||||||
if (blobmsg_type(__attr) == BLOBMSG_TYPE_STRING && strncmp(BBFDM_ROOT_OBJECT, blobmsg_get_string(__attr), strlen(BBFDM_ROOT_OBJECT)) == 0) {
|
|
||||||
char reference_to_set[MAX_VALUE_LENGTH] = {0};
|
|
||||||
|
|
||||||
generate_reference_to_set(blobmsg_get_string(__attr), reference_to_set, sizeof(reference_to_set));
|
|
||||||
blobmsg_add_string(&req_buf, blobmsg_name(__attr), reference_to_set);
|
|
||||||
} else {
|
|
||||||
blobmsg_add_string(&req_buf, blobmsg_name(__attr), blobmsg_get_string(__attr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blobmsg_close_table(&req_buf, table);
|
|
||||||
} else {
|
|
||||||
blobmsg_add_field(&req_buf, blobmsg_type(attr), blobmsg_name(attr), blobmsg_data(attr), blobmsg_len(attr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_log_level == LOG_DEBUG) {
|
if (g_log_level == LOG_DEBUG) {
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ struct blob_attr *get_results_array(struct blob_attr *msg);
|
||||||
|
|
||||||
bool proto_matches(unsigned int dm_type, const enum bbfdmd_type_enum type);
|
bool proto_matches(unsigned int dm_type, const enum bbfdmd_type_enum type);
|
||||||
|
|
||||||
char *get_reference_data(const char *path, const char *method_name);
|
|
||||||
|
|
||||||
void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_attr *msg, struct blob_buf *bb_response);
|
void run_sync_call(const char *ubus_obj, const char *ubus_method, struct blob_attr *msg, struct blob_buf *bb_response);
|
||||||
|
|
||||||
#endif /* BBFDMD_COMMON_H */
|
#endif /* BBFDMD_COMMON_H */
|
||||||
|
|
|
||||||
|
|
@ -19,154 +19,6 @@
|
||||||
|
|
||||||
extern int g_log_level;
|
extern int g_log_level;
|
||||||
|
|
||||||
static void add_linker_entry(struct async_request_context *ctx, const char *linker_path, const char *linker_value)
|
|
||||||
{
|
|
||||||
struct linker_args *linker = calloc(1, sizeof(struct linker_args));
|
|
||||||
if (!linker)
|
|
||||||
return;
|
|
||||||
|
|
||||||
list_add_tail(&linker->list, &ctx->linker_list);
|
|
||||||
linker->path = strdup(linker_path ? linker_path : "");
|
|
||||||
linker->value = strdup(linker_value ? linker_value : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_linker_entries(struct async_request_context *ctx)
|
|
||||||
{
|
|
||||||
struct linker_args *linker = NULL, *tmp = NULL;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(linker, tmp, &ctx->linker_list, list) {
|
|
||||||
list_del(&linker->list);
|
|
||||||
BBFDM_FREE(linker->path);
|
|
||||||
BBFDM_FREE(linker->value);
|
|
||||||
BBFDM_FREE(linker);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool is_reference_value(struct blob_attr *flags)
|
|
||||||
{
|
|
||||||
struct blob_attr *flag = NULL;
|
|
||||||
int rem = 0;
|
|
||||||
|
|
||||||
if (!flags || blobmsg_type(flags) != BLOBMSG_TYPE_ARRAY)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
blobmsg_for_each_attr(flag, flags, rem) {
|
|
||||||
if (strcmp(blobmsg_get_string(flag), "Reference") == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fill_blob_param(struct blob_buf *bb, struct blob_attr *path, const char *data, struct blob_attr *type, struct blob_attr *flags)
|
|
||||||
{
|
|
||||||
if (!bb || !path || !data || !type)
|
|
||||||
return;
|
|
||||||
|
|
||||||
void *table = blobmsg_open_table(bb, NULL);
|
|
||||||
|
|
||||||
if (path) {
|
|
||||||
blobmsg_add_field(bb, blobmsg_type(path), blobmsg_name(path), blobmsg_data(path), blobmsg_len(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
blobmsg_add_string(bb, "data", data);
|
|
||||||
|
|
||||||
if (type) {
|
|
||||||
blobmsg_add_field(bb, blobmsg_type(type), blobmsg_name(type), blobmsg_data(type), blobmsg_len(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags) {
|
|
||||||
blobmsg_add_field(bb, blobmsg_type(flags), blobmsg_name(flags), blobmsg_data(flags), blobmsg_len(flags));
|
|
||||||
}
|
|
||||||
|
|
||||||
blobmsg_close_table(bb, table);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void resolve_reference_path(struct async_request_context *ctx, struct blob_attr *data, char *output, size_t output_len)
|
|
||||||
{
|
|
||||||
if (!ctx || !output || output_len == 0) {
|
|
||||||
BBFDM_ERR("Invalid arguments");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
output[0] = 0; // Ensure output buffer is initialized
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
BBFDM_ERR("Invalid data value");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *ref_path = blobmsg_get_string(data);
|
|
||||||
if (!ref_path || ref_path[0] == '\0') // Empty reference path, nothing to resolve
|
|
||||||
return;
|
|
||||||
|
|
||||||
char buffer[MAX_VALUE_LENGTH] = {0};
|
|
||||||
snprintf(buffer, sizeof(buffer), "%s", ref_path);
|
|
||||||
|
|
||||||
// Check if it is a reference path (separator ',') or list paths (separator ';')
|
|
||||||
bool is_ref_list = strchr(ref_path, ';') != NULL;
|
|
||||||
char *token = NULL, *saveptr = NULL;
|
|
||||||
unsigned pos = 0;
|
|
||||||
|
|
||||||
for (token = strtok_r(buffer, is_ref_list ? ";" : ",", &saveptr);
|
|
||||||
token;
|
|
||||||
token = strtok_r(NULL, is_ref_list ? ";" : ",", &saveptr)) {
|
|
||||||
|
|
||||||
// If token does not contain '[', it’s a direct reference
|
|
||||||
if (!strchr(token, '[')) {
|
|
||||||
pos += snprintf(&output[pos], output_len - pos, "%s,", token);
|
|
||||||
if (!is_ref_list) break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for token in the linker list
|
|
||||||
struct linker_args *linker = NULL;
|
|
||||||
bool linker_found = false;
|
|
||||||
bool linker_empty = false;
|
|
||||||
list_for_each_entry(linker, &ctx->linker_list, list) {
|
|
||||||
if (strcmp(linker->path, token) == 0) {
|
|
||||||
linker_found = true;
|
|
||||||
|
|
||||||
if (linker->value[0] != '\0') {
|
|
||||||
pos += snprintf(&output[pos], output_len - pos, "%s,", linker->value);
|
|
||||||
} else {
|
|
||||||
linker_empty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linker_found) {
|
|
||||||
if (linker_empty) continue;
|
|
||||||
if (!is_ref_list) break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not found, attempt to resolve via micro-services
|
|
||||||
{
|
|
||||||
// Try to get reference value from micro-services directly
|
|
||||||
char *reference_path = get_reference_data(token, "reference_path");
|
|
||||||
|
|
||||||
// Add path to list in order to be used by other parameters
|
|
||||||
add_linker_entry(ctx, token, reference_path ? reference_path : "");
|
|
||||||
|
|
||||||
// Reference value is found
|
|
||||||
if (reference_path != NULL) {
|
|
||||||
pos += snprintf(&output[pos], output_len - pos, "%s,", reference_path);
|
|
||||||
BBFDM_FREE(reference_path);
|
|
||||||
if (!is_ref_list) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pos > 0) {
|
|
||||||
output[pos - 1] = 0; // Remove trailing comma
|
|
||||||
} else {
|
|
||||||
BBFDM_INFO("Can't resolve reference path '%s' -> Set its value to empty", ref_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void prepare_and_send_response(struct async_request_context *ctx)
|
static void prepare_and_send_response(struct async_request_context *ctx)
|
||||||
{
|
{
|
||||||
struct blob_attr *attr = NULL;
|
struct blob_attr *attr = NULL;
|
||||||
|
|
@ -189,28 +41,7 @@ static void prepare_and_send_response(struct async_request_context *ctx)
|
||||||
blobmsg_close_table(&bb_raw, table);
|
blobmsg_close_table(&bb_raw, table);
|
||||||
} else {
|
} else {
|
||||||
blobmsg_for_each_attr(attr, ctx->tmp_bb.head, remaining) {
|
blobmsg_for_each_attr(attr, ctx->tmp_bb.head, remaining) {
|
||||||
|
blobmsg_add_blob(&bb_raw, attr);
|
||||||
if (strcmp(ctx->ubus_method, "get") == 0) {
|
|
||||||
struct blob_attr *fields[4];
|
|
||||||
const struct blobmsg_policy policy[4] = {
|
|
||||||
{ "path", BLOBMSG_TYPE_STRING },
|
|
||||||
{ "data", BLOBMSG_TYPE_STRING },
|
|
||||||
{ "type", BLOBMSG_TYPE_STRING },
|
|
||||||
{ "flags", BLOBMSG_TYPE_ARRAY },
|
|
||||||
};
|
|
||||||
|
|
||||||
blobmsg_parse(policy, 4, fields, blobmsg_data(attr), blobmsg_len(attr));
|
|
||||||
|
|
||||||
if (is_reference_value(fields[3])) {
|
|
||||||
char data[MAX_VALUE_LENGTH] = {0};
|
|
||||||
resolve_reference_path(ctx, fields[1], data, sizeof(data));
|
|
||||||
fill_blob_param(&bb_raw, fields[0], data, fields[2], fields[3]);
|
|
||||||
} else {
|
|
||||||
blobmsg_add_blob(&bb_raw, attr);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
blobmsg_add_blob(&bb_raw, attr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,13 +68,10 @@ void send_response(struct async_request_context *ctx)
|
||||||
{
|
{
|
||||||
prepare_and_send_response(ctx);
|
prepare_and_send_response(ctx);
|
||||||
|
|
||||||
if (strcmp(ctx->ubus_method, "get") == 0) {
|
|
||||||
send_linker_cleanup_event(ctx->ubus_ctx);
|
|
||||||
free_linker_entries(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
ubus_complete_deferred_request(ctx->ubus_ctx, &ctx->request_data, UBUS_STATUS_OK);
|
ubus_complete_deferred_request(ctx->ubus_ctx, &ctx->request_data, UBUS_STATUS_OK);
|
||||||
blob_buf_free(&ctx->tmp_bb);
|
blob_buf_free(&ctx->tmp_bb);
|
||||||
|
|
||||||
|
BBFDM_INFO("END: ubus method|%s|, name|bbfdm|", ctx->ubus_method);
|
||||||
BBFDM_FREE(ctx);
|
BBFDM_FREE(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,14 +191,3 @@ void run_async_call(struct async_request_context *ctx, const char *ubus_obj, str
|
||||||
|
|
||||||
blob_buf_free(&req_buf);
|
blob_buf_free(&req_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_linker_cleanup_event(struct ubus_context *ctx)
|
|
||||||
{
|
|
||||||
struct blob_buf bb = {0};
|
|
||||||
|
|
||||||
memset(&bb, 0, sizeof(struct blob_buf));
|
|
||||||
blob_buf_init(&bb, 0);
|
|
||||||
ubus_send_event(ctx, "bbfdm.linker.cleanup", bb.head);
|
|
||||||
blob_buf_free(&bb);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ struct linker_args {
|
||||||
struct async_request_context {
|
struct async_request_context {
|
||||||
struct ubus_context *ubus_ctx;
|
struct ubus_context *ubus_ctx;
|
||||||
struct ubus_request_data request_data;
|
struct ubus_request_data request_data;
|
||||||
struct list_head linker_list;
|
|
||||||
struct blob_buf tmp_bb;
|
struct blob_buf tmp_bb;
|
||||||
bool service_list_processed;
|
bool service_list_processed;
|
||||||
bool path_matched;
|
bool path_matched;
|
||||||
|
|
@ -45,8 +44,6 @@ struct ubus_request_tracker {
|
||||||
char request_name[128];
|
char request_name[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
void send_linker_cleanup_event(struct ubus_context *ctx);
|
|
||||||
|
|
||||||
void run_async_call(struct async_request_context *ctx, const char *ubus_obj, struct blob_attr *msg);
|
void run_async_call(struct async_request_context *ctx, const char *ubus_obj, struct blob_attr *msg);
|
||||||
void send_response(struct async_request_context *ctx);
|
void send_response(struct async_request_context *ctx);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,73 +253,3 @@ bool is_path_match(const char *requested_path, unsigned int requested_proto, ser
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_ubus_object_name(const char *path)
|
|
||||||
{
|
|
||||||
service_entry_t *service = NULL;
|
|
||||||
|
|
||||||
list_for_each_entry(service, ®istered_services, list) {
|
|
||||||
|
|
||||||
if (!is_path_match(path, BBFDMD_BOTH, service))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return service->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void reference_data_callback(struct ubus_request *req, int type __attribute__((unused)), struct blob_attr *msg)
|
|
||||||
{
|
|
||||||
struct blob_attr *fields[1];
|
|
||||||
const struct blobmsg_policy policy[1] = {
|
|
||||||
{ "data", BLOBMSG_TYPE_STRING },
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!req || !msg)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char *reference_data = (char *)req->priv;
|
|
||||||
|
|
||||||
if (!reference_data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
blobmsg_parse(policy, 1, fields, blobmsg_data(msg), blobmsg_len(msg));
|
|
||||||
|
|
||||||
if (fields[0]) {
|
|
||||||
snprintf(reference_data, MAX_PATH_LENGTH - 1, "%s", blobmsg_get_string(fields[0]));
|
|
||||||
BBFDM_DEBUG("reference_data '%s'", reference_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *get_reference_data(const char *path, const char *method_name)
|
|
||||||
{
|
|
||||||
struct blob_buf req_buf = {0};
|
|
||||||
char reference_value[MAX_PATH_LENGTH] = {0};
|
|
||||||
|
|
||||||
if (!path)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
char *ubus_obj = get_ubus_object_name(path);
|
|
||||||
if (!ubus_obj)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
reference_value[0] = 0;
|
|
||||||
|
|
||||||
memset(&req_buf, 0, sizeof(struct blob_buf));
|
|
||||||
blob_buf_init(&req_buf, 0);
|
|
||||||
|
|
||||||
blobmsg_add_string(&req_buf, "path", path);
|
|
||||||
|
|
||||||
if (g_log_level == LOG_DEBUG) {
|
|
||||||
char *json_str = blobmsg_format_json_indent(req_buf.head, true, -1);
|
|
||||||
BBFDM_DEBUG("### ubus call %s %s '%s' ###", ubus_obj, method_name, json_str);
|
|
||||||
BBFDM_FREE(json_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
BBFDM_UBUS_INVOKE_SYNC(ubus_obj, method_name, req_buf.head, 2000, reference_data_callback, &reference_value);
|
|
||||||
|
|
||||||
blob_buf_free(&req_buf);
|
|
||||||
|
|
||||||
return (reference_value[0] != 0) ? strdup(reference_value) : NULL;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ function install_ethmngr_as_micro_service()
|
||||||
install_libeasy
|
install_libeasy
|
||||||
install_libethernet
|
install_libethernet
|
||||||
|
|
||||||
exec_cmd git clone https://dev.iopsys.eu/hal/ethmngr.git /opt/dev/ethmngr
|
exec_cmd git clone -b redesign_reference https://dev.iopsys.eu/hal/ethmngr.git /opt/dev/ethmngr
|
||||||
exec_cmd make -C /opt/dev/ethmngr
|
exec_cmd make -C /opt/dev/ethmngr
|
||||||
exec_cmd cp -f /opt/dev/ethmngr/ethmngr /usr/sbin/ethmngr
|
exec_cmd cp -f /opt/dev/ethmngr/ethmngr /usr/sbin/ethmngr
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -222,23 +222,98 @@ int bbf_set_alias(struct dmctx *ctx, struct uci_section *s, const char *option_n
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int resolve_path(const char *base_path, const char *key_name, char *key_value, char *out, size_t out_len)
|
||||||
|
{
|
||||||
|
struct uci_section *idb_s = NULL;
|
||||||
|
struct uci_list *uci_list = NULL;
|
||||||
|
struct uci_element *e = NULL;
|
||||||
|
char hash_str[9] = {0};
|
||||||
|
char *star_pos = strchr(base_path, '*');
|
||||||
|
|
||||||
|
if (!star_pos) {
|
||||||
|
// No wildcard, directly search
|
||||||
|
calculate_hash(base_path, hash_str, sizeof(hash_str));
|
||||||
|
|
||||||
|
idb_s = dmuci_get_section_bbfdm("instance_db", hash_str);
|
||||||
|
if (idb_s == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dmuci_get_value_by_section_list(idb_s, "idb_child", &uci_list);
|
||||||
|
if (uci_list == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uci_foreach_element(uci_list, e) {
|
||||||
|
char *value = NULL;
|
||||||
|
|
||||||
|
dmuci_get_option_value_string_bbfdm("instance_db", e->name, key_name, &value);
|
||||||
|
|
||||||
|
if (DM_STRLEN(value) && DM_STRCMP(value, key_value) == 0) {
|
||||||
|
char *instance = NULL;
|
||||||
|
|
||||||
|
dmuci_get_option_value_string_bbfdm("instance_db", e->name, "instance", &instance);
|
||||||
|
|
||||||
|
if (DM_STRLEN(instance)) {
|
||||||
|
snprintf(out, out_len, "%s%s", base_path, instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split path at first '*'
|
||||||
|
char temp_path[256] = {0};
|
||||||
|
|
||||||
|
DM_STRNCPY(temp_path, base_path, star_pos - base_path + 1);
|
||||||
|
BBF_ERR("## temp_path=%s ##", temp_path);
|
||||||
|
|
||||||
|
calculate_hash(temp_path, hash_str, sizeof(hash_str));
|
||||||
|
|
||||||
|
idb_s = dmuci_get_section_bbfdm("instance_db", hash_str);
|
||||||
|
if (idb_s == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dmuci_get_value_by_section_list(idb_s, "idb_child", &uci_list);
|
||||||
|
if (uci_list == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
uci_foreach_element(uci_list, e) {
|
||||||
|
char *instance = NULL;
|
||||||
|
|
||||||
|
// No wildcard, directly search
|
||||||
|
dmuci_get_option_value_string_bbfdm("instance_db", e->name, "instance", &instance);
|
||||||
|
|
||||||
|
if (DM_STRLEN(instance)) {
|
||||||
|
char new_path[512] = {0};
|
||||||
|
|
||||||
|
snprintf(new_path, sizeof(new_path), "%s%s%s", temp_path, instance, star_pos + 1);
|
||||||
|
|
||||||
|
if (resolve_path(new_path, key_name, key_value, out, out_len) == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_path, const char *key_name, char *key_value, char *out, size_t out_len)
|
int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_path, const char *key_name, char *key_value, char *out, size_t out_len)
|
||||||
{
|
{
|
||||||
char param_path[1024] = {0};
|
char ref_value[1024] = {0};
|
||||||
char *value = NULL;
|
|
||||||
|
|
||||||
if (DM_STRLEN(base_path) == 0) {
|
if (DM_STRLEN(base_path) == 0) {
|
||||||
BBF_ERR("Reference base path should not be empty!!!");
|
BBF_ERR("Reference base path is empty. A non-empty base path is required");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DM_STRLEN(key_name) == 0) {
|
if (DM_STRLEN(key_name) == 0) {
|
||||||
BBF_ERR("Reference key name should not be empty!!!");
|
BBF_ERR("Reference key name is empty. A valid key name is required");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DM_STRLEN(key_value) == 0) {
|
if (DM_STRLEN(key_value) == 0) {
|
||||||
BBF_DEBUG("Reference key value should not be empty!!!");
|
BBF_DEBUG("Reference key value is empty. A valid key value is required");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,32 +322,23 @@ int bbfdm_get_references(struct dmctx *ctx, int match_action, const char *base_p
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(param_path, sizeof(param_path), "%s*.%s", base_path, key_name);
|
size_t len = DM_STRLEN(out);
|
||||||
|
|
||||||
adm_entry_get_reference_param(ctx, param_path, key_value, &value);
|
if (len > 0 && match_action == MATCH_FIRST) {
|
||||||
|
BBF_ERR("Reference has already been resolved ('%s'). Skipping next possibility ('%s')", out, base_path);
|
||||||
size_t len = strlen(out);
|
|
||||||
|
|
||||||
if (DM_STRLEN(value) != 0) {
|
|
||||||
|
|
||||||
if (out_len - len < strlen(value)) {
|
|
||||||
BBF_ERR("Buffer overflow detected. The output buffer is not large enough to hold the additional data!!!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(&out[len], out_len - len, "%s%s", len ? (match_action == MATCH_FIRST ? "," : ";") : "", value);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_len - len < strlen(base_path) + strlen(key_name) + strlen(key_value) + 9) { // 9 = 'path[key_name==\"key_value\"].'
|
if (resolve_path(base_path, key_name, key_value, ref_value, sizeof(ref_value)) != 0) {
|
||||||
BBF_ERR("Buffer overflow detected. The output buffer is not large enough to hold the additional data!!!");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(param_path, sizeof(param_path), "%s[%s==\"%s\"].", base_path, key_name, key_value);
|
if (out_len - len < DM_STRLEN(ref_value) + 1) {
|
||||||
|
BBF_ERR("Buffer overflow detected. Output buffer is not large enough to hold the resolved reference value");
|
||||||
snprintf(&out[len], out_len - len, "%s%s", len ? (match_action == MATCH_FIRST ? "," : ";") : "", param_path);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(&out[len], out_len - len, "%s%s", len ? "," : "", ref_value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,7 @@ struct dmctx {
|
||||||
typedef struct dmnode {
|
typedef struct dmnode {
|
||||||
DMOBJ *obj;
|
DMOBJ *obj;
|
||||||
struct dmnode *parent;
|
struct dmnode *parent;
|
||||||
|
struct uci_section *idb_s;
|
||||||
char *current_object;
|
char *current_object;
|
||||||
void *prev_data;
|
void *prev_data;
|
||||||
char *prev_instance;
|
char *prev_instance;
|
||||||
|
|
@ -273,6 +274,7 @@ enum {
|
||||||
BBF_DEL_OBJECT,
|
BBF_DEL_OBJECT,
|
||||||
BBF_OPERATE,
|
BBF_OPERATE,
|
||||||
BBF_EVENT,
|
BBF_EVENT,
|
||||||
|
BBF_INSTANCES_DB
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
|
||||||
|
|
@ -1972,3 +1972,86 @@ int dm_entry_event(struct dmctx *dmctx)
|
||||||
|
|
||||||
return (dmctx->stop) ? err : USP_FAULT_INVALID_PATH;
|
return (dmctx->stop) ? err : USP_FAULT_INVALID_PATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* **********
|
||||||
|
* get instances data base
|
||||||
|
* **********/
|
||||||
|
static struct uci_section *get_uci_instance_db_section(const char *object, const char *sec_name)
|
||||||
|
{
|
||||||
|
struct uci_section *idb_s = NULL;
|
||||||
|
char hash_str[9] = {0};
|
||||||
|
|
||||||
|
calculate_hash(object, hash_str, sizeof(hash_str));
|
||||||
|
|
||||||
|
idb_s = dmuci_get_section_bbfdm("instance_db", hash_str);
|
||||||
|
if (idb_s == NULL) {
|
||||||
|
dmuci_add_section_bbfdm("instance_db", sec_name, &idb_s);
|
||||||
|
dmuci_rename_section_by_section(idb_s, hash_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
//BBF_ERR("%s: node.current_object=%s && hash_str=%s && idb_s=%p && section_name=%s", sec_name, object, hash_str, idb_s, section_name(idb_s));
|
||||||
|
return idb_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mobj_get_instances_db(DMOBJECT_ARGS)
|
||||||
|
{
|
||||||
|
//BBF_ERR("#### OBJ: node->current_object=%s && node->is_instanceobj=%d && node->obj->obj=%s ####", node->current_object, node->is_instanceobj, node->obj->obj);
|
||||||
|
|
||||||
|
if (node->is_instanceobj == 0 && node->obj->browseinstobj != NULL) {
|
||||||
|
node->idb_s = get_uci_instance_db_section(node->current_object, "idb_parent");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->is_instanceobj == 1) {
|
||||||
|
node->idb_s = get_uci_instance_db_section(node->current_object, "idb_child");
|
||||||
|
dmuci_set_value_by_section_bbfdm(node->idb_s, "instance", instance);
|
||||||
|
|
||||||
|
struct uci_list *uci_list = NULL;
|
||||||
|
|
||||||
|
dmuci_get_value_by_section_list(node->parent->idb_s, "idb_child", &uci_list);
|
||||||
|
if (!value_exists_in_uci_list(uci_list, section_name(node->idb_s)))
|
||||||
|
dmuci_add_list_value_by_section(node->parent->idb_s, "idb_child", section_name(node->idb_s));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mparam_get_instances_db(DMPARAM_ARGS)
|
||||||
|
{
|
||||||
|
if (node->is_instanceobj == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
char full_param[MAX_DM_PATH] = {0};
|
||||||
|
char *value = dmstrdup("");
|
||||||
|
|
||||||
|
snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter);
|
||||||
|
|
||||||
|
//BBF_ERR("LEAF: node->current_object=%s && leaf->parameter=%s && node->is_instanceobj=%d && node->obj->obj=%s", node->current_object, leaf->parameter, node->is_instanceobj, node->obj->obj);
|
||||||
|
|
||||||
|
(leaf->getvalue)(full_param, dmctx, data, instance, &value);
|
||||||
|
|
||||||
|
if (leaf->dm_flags & DM_FLAG_UNIQUE) {
|
||||||
|
dmuci_set_value_by_section_bbfdm(node->idb_s, leaf->parameter, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_entry_instances_db(struct dmctx *ctx)
|
||||||
|
{
|
||||||
|
DMOBJ *root = ctx->dm_entryobj;
|
||||||
|
DMNODE node = {.current_object = ""};
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
ctx->inparam_isparam = 0;
|
||||||
|
ctx->findparam = 1;
|
||||||
|
ctx->stop = 0;
|
||||||
|
ctx->checkobj = NULL;
|
||||||
|
ctx->checkleaf = NULL;
|
||||||
|
ctx->method_obj = mobj_get_instances_db;
|
||||||
|
ctx->method_param = mparam_get_instances_db;
|
||||||
|
|
||||||
|
err = dm_browse(ctx, &node, root, NULL, NULL);
|
||||||
|
|
||||||
|
return (ctx->findparam == 0) ? err : 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ int dm_entry_set_value(struct dmctx *dmctx);
|
||||||
int dm_entry_object_exists(struct dmctx *dmctx);
|
int dm_entry_object_exists(struct dmctx *dmctx);
|
||||||
int dm_entry_operate(struct dmctx *dmctx);
|
int dm_entry_operate(struct dmctx *dmctx);
|
||||||
int dm_entry_event(struct dmctx *dmctx);
|
int dm_entry_event(struct dmctx *dmctx);
|
||||||
|
int dm_entry_instances_db(struct dmctx *ctx);
|
||||||
int dm_entry_get_reference_param(struct dmctx *dmctx);
|
int dm_entry_get_reference_param(struct dmctx *dmctx);
|
||||||
int dm_entry_get_reference_value(struct dmctx *dmctx);
|
int dm_entry_get_reference_value(struct dmctx *dmctx);
|
||||||
int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance);
|
int dm_link_inst_obj(struct dmctx *dmctx, DMNODE *parent_node, void *data, char *instance);
|
||||||
|
|
|
||||||
|
|
@ -2196,3 +2196,22 @@ bool is_str_eq(const char *s1, const char *s2)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef uint32_t HashValue;
|
||||||
|
|
||||||
|
#define FNV_OFFSET_BASIS 0x811C9DC5
|
||||||
|
#define FNV_PRIME 0x1000193
|
||||||
|
|
||||||
|
// Function to calculate FNV-1 hash
|
||||||
|
void calculate_hash(const char *input, char *output, size_t out_len)
|
||||||
|
{
|
||||||
|
HashValue hash = FNV_OFFSET_BASIS;
|
||||||
|
|
||||||
|
while (*input != '\0') {
|
||||||
|
hash *= FNV_PRIME; // Multiply hash by prime
|
||||||
|
hash ^= (uint8_t)(*input); // XOR with current character
|
||||||
|
input++;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(output, out_len, "%08X", hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,4 +239,6 @@ long upload_file(const char *file_path, const char *url, const char *username, c
|
||||||
int get_proto_type(const char *proto);
|
int get_proto_type(const char *proto);
|
||||||
bool is_str_eq(const char *s1, const char *s2);
|
bool is_str_eq(const char *s1, const char *s2);
|
||||||
|
|
||||||
|
void calculate_hash(const char *input, char *output, size_t out_len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,9 @@ int bbf_entry_method(struct dmctx *ctx, int cmd)
|
||||||
case BBF_EVENT:
|
case BBF_EVENT:
|
||||||
fault = dm_entry_event(ctx);
|
fault = dm_entry_event(ctx);
|
||||||
break;
|
break;
|
||||||
|
case BBF_INSTANCES_DB:
|
||||||
|
fault = dm_entry_instances_db(ctx);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bbf_fault_map(ctx, fault);
|
return bbf_fault_map(ctx, fault);
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,17 @@ int dmuci_get_section_type(const char *package, const char *section, char **valu
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**** UCI SECTION EXIST *****/
|
||||||
|
struct uci_section *dmuci_get_section(const char *package, const char *section)
|
||||||
|
{
|
||||||
|
struct uci_ptr ptr = {0};
|
||||||
|
|
||||||
|
if (dmuci_lookup_ptr(uci_ctx, &ptr, package, section, NULL, NULL))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return ptr.s;
|
||||||
|
}
|
||||||
|
|
||||||
int dmuci_get_option_value_string(const char *package, const char *section, const char *option, char **value)
|
int dmuci_get_option_value_string(const char *package, const char *section, const char *option, char **value)
|
||||||
{
|
{
|
||||||
struct uci_ptr ptr = {0};
|
struct uci_ptr ptr = {0};
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,15 @@ int dmuci_get_section_type_##UCI_PATH(const char *package, const char *section,c
|
||||||
uci_ctx = save_uci_ctx; \
|
uci_ctx = save_uci_ctx; \
|
||||||
return res; \
|
return res; \
|
||||||
}\
|
}\
|
||||||
|
struct uci_section *dmuci_get_section_##UCI_PATH(const char *package, const char *section) \
|
||||||
|
{\
|
||||||
|
struct uci_context *save_uci_ctx; \
|
||||||
|
save_uci_ctx = uci_ctx; \
|
||||||
|
uci_ctx = uci_ctx_##UCI_PATH; \
|
||||||
|
struct uci_section *res = dmuci_get_section(package, section); \
|
||||||
|
uci_ctx = save_uci_ctx; \
|
||||||
|
return res; \
|
||||||
|
}\
|
||||||
int dmuci_get_option_value_string_##UCI_PATH(const char *package, const char *section, const char *option, char **value) \
|
int dmuci_get_option_value_string_##UCI_PATH(const char *package, const char *section, const char *option, char **value) \
|
||||||
{\
|
{\
|
||||||
struct uci_context *save_uci_ctx; \
|
struct uci_context *save_uci_ctx; \
|
||||||
|
|
@ -306,6 +315,7 @@ int dmuci_add_list_value_by_section(struct uci_section *s, const char *option, c
|
||||||
int dmuci_del_list_value_by_section(struct uci_section *s, const char *option, const char *value);
|
int dmuci_del_list_value_by_section(struct uci_section *s, const char *option, const char *value);
|
||||||
int dmuci_rename_section_by_section(struct uci_section *s, const char *value);
|
int dmuci_rename_section_by_section(struct uci_section *s, const char *value);
|
||||||
int dmuci_reoder_section_by_section(struct uci_section *s, char *pos);
|
int dmuci_reoder_section_by_section(struct uci_section *s, char *pos);
|
||||||
|
struct uci_section *dmuci_get_section(const char *package, const char *section);
|
||||||
struct uci_section *dmuci_walk_section(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);
|
struct uci_section *dmuci_walk_section(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);
|
||||||
struct uci_section *dmuci_walk_all_sections(const char *package, struct uci_section *prev_section, int walk);
|
struct uci_section *dmuci_walk_all_sections(const char *package, struct uci_section *prev_section, int walk);
|
||||||
|
|
||||||
|
|
@ -318,6 +328,7 @@ int dmuci_delete_by_section_unnamed_bbfdm(struct uci_section *s, const char *opt
|
||||||
int dmuci_delete_by_section_bbfdm(struct uci_section *s, const char *option, const char *value);
|
int dmuci_delete_by_section_bbfdm(struct uci_section *s, const char *option, const char *value);
|
||||||
int dmuci_commit_package_bbfdm(char *package);
|
int dmuci_commit_package_bbfdm(char *package);
|
||||||
int dmuci_commit_bbfdm(void);
|
int dmuci_commit_bbfdm(void);
|
||||||
|
struct uci_section *dmuci_get_section_bbfdm(const char *package, const char *section);
|
||||||
struct uci_section *dmuci_walk_section_bbfdm(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);
|
struct uci_section *dmuci_walk_section_bbfdm(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);
|
||||||
|
|
||||||
struct uci_section *dmuci_walk_section_varstate(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);
|
struct uci_section *dmuci_walk_section_varstate(const char *package, const char *stype, const void *arg1, const void *arg2, int cmp , int (*filter)(struct uci_section *s, const void *value), struct uci_section *prev_section, int walk);
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,6 @@ static void bbfdm_ctx_cleanup(struct bbfdm_context *u)
|
||||||
{
|
{
|
||||||
bbf_global_clean(DEAMON_DM_ROOT_OBJ);
|
bbf_global_clean(DEAMON_DM_ROOT_OBJ);
|
||||||
|
|
||||||
free_path_list(&u->linker_list);
|
|
||||||
free_path_list(&u->obj_list);
|
|
||||||
|
|
||||||
/* DotSo Plugin */
|
/* DotSo Plugin */
|
||||||
bbfdm_free_dotso_plugin(u, &deamon_lib_handle);
|
bbfdm_free_dotso_plugin(u, &deamon_lib_handle);
|
||||||
|
|
||||||
|
|
@ -75,42 +72,6 @@ static void fill_optional_data(bbfdm_data_t *data, struct blob_attr *msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *get_value_by_reference_path(struct dmctx *ctx, char *reference_path)
|
|
||||||
{
|
|
||||||
char path[MAX_DM_PATH] = {0};
|
|
||||||
char key_name[256], key_value[256];
|
|
||||||
char *reference_value = NULL;
|
|
||||||
regmatch_t pmatch[2];
|
|
||||||
|
|
||||||
if (!ctx || !reference_path)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!match(reference_path, "\\[(.*?)\\]", 2, pmatch))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
snprintf(path, pmatch[0].rm_so + 1, "%s", reference_path);
|
|
||||||
int len = DM_STRLEN(path);
|
|
||||||
if (!len)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
char *match_str = reference_path + pmatch[1].rm_so;
|
|
||||||
if (DM_STRLEN(match_str) == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
int n = sscanf(match_str, "%255[^=]==\"%255[^\"]\"", key_name, key_value);
|
|
||||||
if (n != 2) {
|
|
||||||
n = sscanf(match_str, "%255[^=]==%255[^]]", key_name, key_value);
|
|
||||||
if (n != 2)
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(path + len, sizeof(path) - len, "*.%s", key_name);
|
|
||||||
|
|
||||||
adm_entry_get_reference_param(ctx, path, key_value, &reference_value);
|
|
||||||
|
|
||||||
return reference_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void async_req_free(struct bbfdm_async_req *r)
|
static void async_req_free(struct bbfdm_async_req *r)
|
||||||
{
|
{
|
||||||
free(r);
|
free(r);
|
||||||
|
|
@ -621,108 +582,40 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bbfdm_ref_path_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
static int refresh_instance_db(void)
|
||||||
struct ubus_request_data *req, const char *method,
|
|
||||||
struct blob_attr *msg)
|
|
||||||
{
|
{
|
||||||
struct blob_attr *tb[__DM_GET_MAX];
|
struct dmctx bbf_ctx = {
|
||||||
struct bbfdm_context *u;
|
.in_param = ROOT_NODE
|
||||||
struct pvNode *node = NULL;
|
};
|
||||||
struct blob_buf bb;
|
|
||||||
bool reference_value_found = false;
|
|
||||||
|
|
||||||
if (blobmsg_parse(dm_get_policy, __DM_GET_MAX, tb, blob_data(msg), blob_len(msg))) {
|
|
||||||
BBF_ERR("Failed to parse blob");
|
|
||||||
return UBUS_STATUS_UNKNOWN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tb[DM_GET_PATH])
|
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
u = container_of(ctx, struct bbfdm_context, ubus_ctx);
|
|
||||||
if (u == NULL) {
|
|
||||||
BBF_ERR("failed to get the bbfdm context");
|
|
||||||
return UBUS_STATUS_UNKNOWN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name);
|
|
||||||
|
|
||||||
char *path = blobmsg_get_string(tb[DM_GET_PATH]);
|
|
||||||
|
|
||||||
if (!match_with_path_list(&u->obj_list, path))
|
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
memset(&bb, 0, sizeof(struct blob_buf));
|
|
||||||
blob_buf_init(&bb, 0);
|
|
||||||
|
|
||||||
list_for_each_entry(node, &u->linker_list, list) {
|
|
||||||
if (strcmp(node->param, path) == 0) {
|
|
||||||
bb_add_string(&bb, "data", node->val);
|
|
||||||
reference_value_found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!reference_value_found) {
|
|
||||||
struct dmctx bbf_ctx = {0};
|
|
||||||
|
|
||||||
bbf_init(&bbf_ctx);
|
|
||||||
char *reference_path = get_value_by_reference_path(&bbf_ctx, path);
|
|
||||||
|
|
||||||
add_pv_list(path, reference_path, NULL, &u->linker_list);
|
|
||||||
bb_add_string(&bb, "data", reference_path ? reference_path : "");
|
|
||||||
|
|
||||||
bbf_cleanup(&bbf_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
ubus_send_reply(ctx, req, bb.head);
|
|
||||||
blob_buf_free(&bb);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int bbfdm_ref_value_handler(struct ubus_context *ctx, struct ubus_object *obj,
|
|
||||||
struct ubus_request_data *req, const char *method,
|
|
||||||
struct blob_attr *msg)
|
|
||||||
{
|
|
||||||
struct blob_attr *tb[__DM_GET_MAX];
|
|
||||||
struct bbfdm_context *u;
|
|
||||||
struct dmctx bbf_ctx = {0};
|
|
||||||
char *reference_value = NULL;
|
|
||||||
struct blob_buf bb;
|
|
||||||
|
|
||||||
if (blobmsg_parse(dm_get_policy, __DM_GET_MAX, tb, blob_data(msg), blob_len(msg))) {
|
|
||||||
BBF_ERR("Failed to parse blob");
|
|
||||||
return UBUS_STATUS_UNKNOWN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tb[DM_GET_PATH])
|
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
u = container_of(ctx, struct bbfdm_context, ubus_ctx);
|
|
||||||
if (u == NULL) {
|
|
||||||
BBF_ERR("failed to get the bbfdm context");
|
|
||||||
return UBUS_STATUS_UNKNOWN_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
BBFDM_INFO("ubus method|%s|, name|%s|", method, obj->name);
|
|
||||||
|
|
||||||
char *reference_path = blobmsg_get_string(tb[DM_GET_PATH]);
|
|
||||||
|
|
||||||
if (!match_with_path_list(&u->obj_list, reference_path))
|
|
||||||
return UBUS_STATUS_INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
memset(&bb, 0, sizeof(struct blob_buf));
|
|
||||||
blob_buf_init(&bb, 0);
|
|
||||||
|
|
||||||
bbf_init(&bbf_ctx);
|
bbf_init(&bbf_ctx);
|
||||||
|
int res = bbfdm_cmd_exec(&bbf_ctx, BBF_INSTANCES_DB);
|
||||||
|
|
||||||
adm_entry_get_reference_value(&bbf_ctx, reference_path, &reference_value);
|
if (!res) {
|
||||||
|
// Apply all bbfdm changes
|
||||||
bb_add_string(&bb, "data", reference_value ? reference_value : "");
|
dmuci_commit_bbfdm();
|
||||||
|
}
|
||||||
|
|
||||||
bbf_cleanup(&bbf_ctx);
|
bbf_cleanup(&bbf_ctx);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bbfdm_refresh_db(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method,
|
||||||
|
struct blob_attr *msg)
|
||||||
|
{
|
||||||
|
struct blob_buf bb = {0};
|
||||||
|
|
||||||
|
BBF_INFO("ubus method|%s|, name|%s|", method, obj->name);
|
||||||
|
|
||||||
|
memset(&bb, 0, sizeof(struct blob_buf));
|
||||||
|
blob_buf_init(&bb, 0);
|
||||||
|
|
||||||
|
int res = refresh_instance_db();
|
||||||
|
|
||||||
|
blobmsg_add_u8(&bb, "status", !res ? true : false);
|
||||||
|
|
||||||
ubus_send_reply(ctx, req, bb.head);
|
ubus_send_reply(ctx, req, bb.head);
|
||||||
blob_buf_free(&bb);
|
blob_buf_free(&bb);
|
||||||
|
|
||||||
|
|
@ -737,8 +630,7 @@ static struct ubus_method bbf_methods[] = {
|
||||||
UBUS_METHOD("operate", bbfdm_operate_handler, dm_operate_policy),
|
UBUS_METHOD("operate", bbfdm_operate_handler, dm_operate_policy),
|
||||||
UBUS_METHOD("add", bbfdm_add_handler, dm_add_policy),
|
UBUS_METHOD("add", bbfdm_add_handler, dm_add_policy),
|
||||||
UBUS_METHOD("del", bbfdm_del_handler, dm_del_policy),
|
UBUS_METHOD("del", bbfdm_del_handler, dm_del_policy),
|
||||||
UBUS_METHOD("reference_path", bbfdm_ref_path_handler, dm_get_policy),
|
UBUS_METHOD_NOARG("refresh_db", bbfdm_refresh_db)
|
||||||
UBUS_METHOD("reference_value", bbfdm_ref_value_handler, dm_get_policy),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE("", bbf_methods);
|
static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE("", bbf_methods);
|
||||||
|
|
@ -766,30 +658,8 @@ static int regiter_ubus_object(struct ubus_context *ctx)
|
||||||
return ubus_add_object(ctx, &bbf_object);
|
return ubus_add_object(ctx, &bbf_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bbfdm_linker_cb(struct ubus_context *ctx, struct ubus_event_handler *ev,
|
|
||||||
const char *type, struct blob_attr *msg)
|
|
||||||
{
|
|
||||||
if (!type || !msg)
|
|
||||||
return;
|
|
||||||
|
|
||||||
struct bbfdm_context *u;
|
|
||||||
|
|
||||||
u = container_of(ctx, struct bbfdm_context, ubus_ctx);
|
|
||||||
if (u == NULL) {
|
|
||||||
BBF_ERR("failed to get the bbfdm context");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(type, "bbfdm.linker.cleanup") == 0) {
|
|
||||||
//BBF_ERR("bbfdm.linker.cleanup");
|
|
||||||
free_pv_list(&u->linker_list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bbfdm_ctx_init(struct bbfdm_context *bbfdm_ctx)
|
static void bbfdm_ctx_init(struct bbfdm_context *bbfdm_ctx)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&bbfdm_ctx->linker_list);
|
|
||||||
INIT_LIST_HEAD(&bbfdm_ctx->obj_list);
|
|
||||||
INIT_LIST_HEAD(&bbfdm_ctx->event_handlers);
|
INIT_LIST_HEAD(&bbfdm_ctx->event_handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -852,8 +722,6 @@ static int load_micro_service_data_model(struct bbfdm_context *daemon_ctx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct ubus_event_handler bbfdm_linker_handler = { .cb = bbfdm_linker_cb };
|
|
||||||
|
|
||||||
int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
|
int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
@ -861,7 +729,7 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
|
||||||
err = ubus_connect_ctx(&bbfdm_ctx->ubus_ctx, NULL);
|
err = ubus_connect_ctx(&bbfdm_ctx->ubus_ctx, NULL);
|
||||||
if (err != UBUS_STATUS_OK) {
|
if (err != UBUS_STATUS_OK) {
|
||||||
BBF_ERR("Failed to connect to ubus");
|
BBF_ERR("Failed to connect to ubus");
|
||||||
return -5; // Error code -5 indicating that ubus_ctx is connected
|
return -5; // Error code -5 indicating that ubus_ctx is not connected
|
||||||
}
|
}
|
||||||
|
|
||||||
uloop_init();
|
uloop_init();
|
||||||
|
|
@ -885,11 +753,13 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx)
|
||||||
if (err != UBUS_STATUS_OK)
|
if (err != UBUS_STATUS_OK)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
err = register_events_to_ubus(&bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers);
|
err = refresh_instance_db();
|
||||||
if (err != 0)
|
if (err) {
|
||||||
return err;
|
BBF_ERR("Failed to refresh instance data base");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return ubus_register_event_handler(&bbfdm_ctx->ubus_ctx, &bbfdm_linker_handler, "bbfdm.linker.cleanup");
|
return register_events_to_ubus(&bbfdm_ctx->ubus_ctx, &bbfdm_ctx->event_handlers);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bbfdm_ubus_regiter_free(struct bbfdm_context *bbfdm_ctx)
|
int bbfdm_ubus_regiter_free(struct bbfdm_context *bbfdm_ctx)
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,6 @@ struct bbfdm_context {
|
||||||
bbfdm_config_t config;
|
bbfdm_config_t config;
|
||||||
struct ubus_context ubus_ctx;
|
struct ubus_context ubus_ctx;
|
||||||
struct list_head event_handlers;
|
struct list_head event_handlers;
|
||||||
struct list_head linker_list;
|
|
||||||
struct list_head obj_list;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ev_handler_node {
|
struct ev_handler_node {
|
||||||
|
|
|
||||||
|
|
@ -66,15 +66,6 @@ int bbfdm_load_internal_plugin(struct bbfdm_context *bbfdm_ctx, DM_MAP_OBJ *dyna
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dynamic_obj[i].root_obj != NULL && bbfdm_ctx != NULL) {
|
|
||||||
struct dm_obj_s *entryobj = dynamic_obj[i].root_obj;
|
|
||||||
for (; (entryobj && entryobj->obj); entryobj++) {
|
|
||||||
char path[MAX_DM_PATH] = {0};
|
|
||||||
snprintf(path, sizeof(path), "%s%s.", node_obj, entryobj->obj);
|
|
||||||
add_path_list(path, &bbfdm_ctx->obj_list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
node_obj[len-1] = 0;
|
node_obj[len-1] = 0;
|
||||||
|
|
||||||
dm_entryobj[i].obj = node_obj;
|
dm_entryobj[i].obj = node_obj;
|
||||||
|
|
@ -196,10 +187,6 @@ static int bbfdm_load_json_plugin(struct bbfdm_context *bbfdm_ctx, struct list_h
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char path[MAX_DM_PATH] = {0};
|
|
||||||
snprintf(path, sizeof(path), "%s%s.", obj_prefix, obj_name);
|
|
||||||
add_path_list(path, &bbfdm_ctx->obj_list);
|
|
||||||
|
|
||||||
// Remove '.' from object prefix
|
// Remove '.' from object prefix
|
||||||
if (obj_prefix[obj_prefix_len - 1] == '.')
|
if (obj_prefix[obj_prefix_len - 1] == '.')
|
||||||
obj_prefix[obj_prefix_len - 1] = 0;
|
obj_prefix[obj_prefix_len - 1] = 0;
|
||||||
|
|
|
||||||
26
test/files/etc/config/schedules
Normal file
26
test/files/etc/config/schedules
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
config global 'global'
|
||||||
|
option enable '1'
|
||||||
|
|
||||||
|
config schedule 'schedule_1'
|
||||||
|
option enable '0'
|
||||||
|
list day 'Monday'
|
||||||
|
list day 'Tuesday'
|
||||||
|
list day 'Wednesday'
|
||||||
|
list day 'Thursday'
|
||||||
|
list day 'Friday'
|
||||||
|
list day 'Saturday'
|
||||||
|
list day 'Sunday'
|
||||||
|
option duration '1'
|
||||||
|
|
||||||
|
config schedule 'schedule_2'
|
||||||
|
option enable '0'
|
||||||
|
list day 'Monday'
|
||||||
|
list day 'Tuesday'
|
||||||
|
list day 'Wednesday'
|
||||||
|
list day 'Thursday'
|
||||||
|
list day 'Friday'
|
||||||
|
list day 'Saturday'
|
||||||
|
list day 'Sunday'
|
||||||
|
option duration '1'
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue