This commit is contained in:
Amin Ben Romdhane 2025-01-24 15:49:12 +01:00
parent 8bc63723e0
commit 485c2ada13
6 changed files with 346 additions and 0 deletions

View file

@ -195,6 +195,7 @@ struct dmctx {
unsigned int dm_type;
unsigned char inparam_isparam;
unsigned char findparam;
unsigned int amin_num_of_ms;
char *in_param;
char *in_value;
@ -261,6 +262,7 @@ enum browse_type_enum {
enum {
BBF_GET_VALUE,
BBF_GET_VALUE_ASYNC,
BBF_SCHEMA,
BBF_INSTANCES,
BBF_GET_NAME,

View file

@ -1173,6 +1173,42 @@ static int get_ubus_value(struct dmctx *dmctx, struct dmnode *node)
return 0;
}
static int get_ubus_value_async(struct dmctx *dmctx, struct dmnode *node)
{
char *ubus_name = node->obj->checkdep;
char *in_path = (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, "Device") == 0) ? node->current_object : dmctx->in_param;
struct blob_buf blob = {0};
int timeout = 5000;
if ((dm_is_micro_service() == false) && ((dmctx->dm_type & node->obj->bbfdm_type) == false)) {
BBF_DEBUG("[%s] Ignore unsupported proto objects [%s], in[%d], datamodel[%d]", __func__, ubus_name, dmctx->dm_type, node->obj->bbfdm_type);
return 0;
}
if (node->obj->bbfdm_type == BBFDM_CWMP) {
timeout = 10000;
}
memset(&blob, 0, sizeof(struct blob_buf));
blob_buf_init(&blob, 0);
blobmsg_add_string(&blob, "path", in_path);
prepare_optional_table(dmctx, &blob);
BBF_ERR("UBUS GET: ubus call %s get '{\"path\":\"%s\"}'", ubus_name, in_path);
int res = ubus_call_blob_msg(ubus_name, "get", &blob, timeout, __get_ubus_value, dmctx);
blob_buf_free(&blob);
if (res)
return FAULT_9005;
if (dmctx->faultcode)
return dmctx->faultcode;
return 0;
}
static void __get_ubus_supported_dm(struct ubus_request *req, int type, struct blob_attr *msg)
{
struct blob_attr *cur = NULL;
@ -1884,6 +1920,139 @@ int dm_entry_get_value(struct dmctx *dmctx)
return (findparam_check && dmctx->findparam) ? 0 : err;
}
/* **********
* get value async
* **********/
static int get_value_async_obj(DMOBJECT_ARGS)
{
return 0;
}
static int get_value_async_param(DMPARAM_ARGS)
{
if (node->is_ubus_service) {
return get_ubus_value_async(dmctx, node);
} else {
char full_param[MAX_DM_PATH] = {0};
char *value = dmstrdup("");
snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter);
(leaf->getvalue)(full_param, dmctx, data, instance, &value);
if ((leaf->dm_flags & DM_FLAG_SECURE) && (dmctx->dm_type == BBFDM_CWMP)) {
value = dmstrdup("");
} else if (value && *value) {
if (leaf->dm_flags & DM_FLAG_REFERENCE) {
value = get_value_by_reference(dmctx, value);
} else {
value = check_value_by_type(value, leaf->type);
}
} else {
value = get_default_value_by_type(leaf->type);
}
fill_blob_param(&dmctx->bb, full_param, value, DMT_TYPE[leaf->type], leaf->dm_flags);
}
return 0;
}
static int mobj_get_value_async_in_param(DMOBJECT_ARGS)
{
return 0;
}
static int mparam_get_value_async_in_param(DMPARAM_ARGS)
{
if (node->is_ubus_service) {
int err = get_ubus_value_async(dmctx, node);
if (err)
return FAULT_9005;
dmctx->findparam = (dmctx->iswildcard) ? 1 : 0;
dmctx->stop = (dmctx->iswildcard) ? false : true;
} else {
char full_param[MAX_DM_PATH] = {0};
char *value = dmstrdup("");
snprintf(full_param, sizeof(full_param), "%s%s", node->current_object, leaf->parameter);
if (dmctx->iswildcard) {
if (dm_strcmp_wildcard(dmctx->in_param, full_param) != 0)
return FAULT_9005;
} else {
if (DM_STRCMP(dmctx->in_param, full_param) != 0)
return FAULT_9005;
}
(leaf->getvalue)(full_param, dmctx, data, instance, &value);
if ((leaf->dm_flags & DM_FLAG_SECURE) && (dmctx->dm_type == BBFDM_CWMP)) {
value = dmstrdup("");
} else if (value && *value) {
if (leaf->dm_flags & DM_FLAG_REFERENCE) {
value = get_value_by_reference(dmctx, value);
} else
value = check_value_by_type(value, leaf->type);
} else {
value = get_default_value_by_type(leaf->type);
}
fill_blob_param(&dmctx->bb, full_param, value, DMT_TYPE[leaf->type], leaf->dm_flags);
dmctx->findparam = (dmctx->iswildcard) ? 1 : 0;
dmctx->stop = (dmctx->iswildcard) ? false : true;
}
return 0;
}
int dm_entry_get_value_async(struct dmctx *dmctx)
{
int err = 0;
unsigned char findparam_check = 0;
DMOBJ *root = dmctx->dm_entryobj;
DMNODE node = {.current_object = ""};
unsigned int len = DM_STRLEN(dmctx->in_param);
if ((len > 2 && dmctx->in_param[len - 1] == '.' && dmctx->in_param[len - 2] == '*') ||
(dmctx->in_param[0] == '.' && len == 1))
return FAULT_9005;
if (dmctx->in_param[0] == '\0' || rootcmp(dmctx->in_param, root->obj) == 0) {
dmctx->inparam_isparam = 0;
dmctx->method_obj = get_value_obj;
dmctx->method_param = get_value_param;
dmctx->checkobj = NULL;
dmctx->checkleaf = NULL;
dmctx->findparam = 1;
dmctx->stop = 0;
findparam_check = 1;
} else if (dmctx->in_param[len - 1] == '.') {
dmctx->inparam_isparam = 0;
dmctx->findparam = 0;
dmctx->stop = 0;
dmctx->checkobj = (dmctx->iswildcard) ? plugin_obj_wildcard_match : plugin_obj_match;
dmctx->checkleaf = (dmctx->iswildcard) ? plugin_leaf_wildcard_match : plugin_leaf_match;
dmctx->method_obj = get_value_async_obj;
dmctx->method_param = get_value_async_param;
findparam_check = 1;
} else {
dmctx->inparam_isparam = 1;
dmctx->findparam = 0;
dmctx->stop = 0;
dmctx->checkobj = (dmctx->iswildcard) ? plugin_obj_wildcard_match : plugin_obj_match;
dmctx->checkleaf = (dmctx->iswildcard) ? plugin_leaf_wildcard_match : plugin_leaf_match;
dmctx->method_obj = mobj_get_value_async_in_param;
dmctx->method_param = mparam_get_value_async_in_param;
findparam_check = (dmctx->iswildcard) ? 1 : 0;
}
err = dm_browse(dmctx, &node, root, NULL, NULL);
return (findparam_check && dmctx->findparam) ? 0 : err;
}
/* **********
* get name
* **********/

View file

@ -42,6 +42,7 @@ void fill_blob_operate(struct blob_buf *bb, const char *path, const char *data,
int string_to_bool(const char *v, bool *b);
char *get_value_by_reference(struct dmctx *ctx, char *value);
int dm_entry_get_value(struct dmctx *dmctx);
int dm_entry_get_value_async(struct dmctx *dmctx);
int dm_entry_get_name(struct dmctx *ctx);
int dm_entry_get_supported_dm(struct dmctx *ctx);
int dm_entry_get_instances(struct dmctx *ctx);

View file

@ -204,6 +204,11 @@ int bbf_entry_method(struct dmctx *ctx, int cmd)
case BBF_GET_VALUE:
fault = dm_entry_get_value(ctx);
break;
case BBF_GET_VALUE_ASYNC:
BBF_ERR("ctx->in_param=%s", ctx->in_param);
fault = dm_entry_get_value_async(ctx);
BBF_ERR("fault=%d", fault);
break;
case BBF_SCHEMA:
fault = dm_entry_get_supported_dm(ctx);
break;

View file

@ -266,6 +266,171 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _
return 0;
}
static bbfdm_data_t *amin_data = NULL;
struct request_tracker {
struct ubus_request ubus_req;
struct uloop_timeout timeout;
char object_name[128];
};
static void request_timeout_handler(struct uloop_timeout *t)
{
struct request_tracker *tracker = container_of(t, struct request_tracker, timeout);
BBF_ERR("Timeout occurred for object: %s\n", tracker->object_name);
ubus_abort_request(amin_data->ctx, &tracker->ubus_req);
// Add a timeout response to the consolidated response
blobmsg_add_string(&amin_data->bb, "timeout", "called");
// Decrement the pending request count
amin_data->pending_requests--;
// Check if all requests are done
if (amin_data->pending_requests == 0) {
BBF_ERR("All requests completed.\n");
ubus_send_reply(amin_data->ctx, &amin_data->amin_new_req, amin_data->bb.head);
ubus_complete_deferred_request(amin_data->ctx, &amin_data->amin_new_req, UBUS_STATUS_OK);
blob_buf_free(&amin_data->bb);
}
// Clean up the tracker
FREE(tracker);
}
static void ubus_result_callback(struct ubus_request *req, int type, struct blob_attr *msg)
{
struct request_tracker *tracker = container_of(req, struct request_tracker, ubus_req);
/*if (msg) {
char *result = blobmsg_format_json_indent(msg, true, -1);
BBF_ERR("Response from object %s: %s\n", tracker->object_name, result);
FREE(result);
}*/
blobmsg_add_string(&amin_data->bb, "result_callback", "true");
// Cancel the timeout for this request
uloop_timeout_cancel(&tracker->timeout);
// Decrement the pending request count
amin_data->pending_requests--;
// Check if all requests are done
if (amin_data->pending_requests == 0) {
BBF_ERR("All requests completed.");
ubus_send_reply(amin_data->ctx, &amin_data->amin_new_req, amin_data->bb.head);
ubus_complete_deferred_request(amin_data->ctx, &amin_data->amin_new_req, UBUS_STATUS_OK);
blob_buf_free(&amin_data->bb);
}
}
static void ubus_request_complete(struct ubus_request *req, int ret)
{
BBF_ERR("Request completed with status: %d", ret);
struct request_tracker *tracker = container_of(req, struct request_tracker, ubus_req);
FREE(tracker);
}
static void invoke_object(const char *object_name)
{
struct blob_buf req_buf = {0};
uint32_t id;
// Look up the object ID
if (ubus_lookup_id(amin_data->ctx, object_name, &id)) {
BBF_ERR("Failed to lookup object: %s", object_name);
return;
}
memset(&req_buf, 0, sizeof(struct blob_buf));
blob_buf_init(&req_buf, 0);
struct request_tracker *tracker = calloc(1, sizeof(struct request_tracker));
if (!tracker) {
BBF_ERR("Failed to allocate memory for request tracker");
blob_buf_free(&req_buf);
return;
}
snprintf(tracker->object_name, sizeof(tracker->object_name), "%s", object_name);
tracker->timeout.cb = request_timeout_handler;
uloop_timeout_set(&tracker->timeout, 5000);
// Invoke the method asynchronously
if (ubus_invoke_async(amin_data->ctx, id, "status", req_buf.head, &tracker->ubus_req)) {
BBF_ERR("Failed to invoke method asynchronously for object: %s", object_name);
uloop_timeout_cancel(&tracker->timeout);
free(tracker);
} else {
tracker->ubus_req.data_cb = ubus_result_callback;
tracker->ubus_req.complete_cb = ubus_request_complete;
ubus_complete_request_async(amin_data->ctx, &tracker->ubus_req);
}
blob_buf_free(&req_buf);
}
static int bbfdm_get_async_handler(struct ubus_context *ctx, struct ubus_object *obj __attribute__((unused)),
struct ubus_request_data *req, const char *method __attribute__((unused)),
struct blob_attr *msg)
{
struct blob_attr *tb[__DM_GET_MAX];
bbfdm_data_t *data = calloc(1, sizeof(bbfdm_data_t));
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 UBUS_STATUS_UNKNOWN_ERROR;
}
memset(data, 0, sizeof(bbfdm_data_t));
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]) {
char *path = blobmsg_get_string(tb[DM_GET_PATH]);
snprintf(data->path, sizeof(data->path), "%s", path);
} else {
return UBUS_STATUS_INVALID_ARGUMENT;
}
data->ctx = ctx;
data->req = req;
fill_optional_data(data, tb[DM_GET_OPTIONAL]);
memset(&data->bb, 0, sizeof(struct blob_buf));
blob_buf_init(&data->bb, 0);
blobmsg_add_string(&data->bb, "path", data->path);
ubus_defer_request(ctx, req, &data->amin_new_req);
//bbfdm_get_value_async(&data);
const char *objects[] = { "wifi.dataelements.collector", "wifi.ap.test1_0", "wifi" };
int num_objects = sizeof(objects) / sizeof(objects[0]);
data->pending_requests = num_objects;
amin_data = data;
for (int i = 0; i < num_objects; i++) {
invoke_object(objects[i]);
}
return 0;
}
static const struct blobmsg_policy dm_schema_policy[] = {
[DM_SCHEMA_PATH] = { .name = "path", .type = BLOBMSG_TYPE_STRING },
[DM_SCHEMA_PATHS] = { .name = "paths", .type = BLOBMSG_TYPE_ARRAY },
@ -735,6 +900,7 @@ static int bbfdm_notify_event(struct ubus_context *ctx, struct ubus_object *obj,
static struct ubus_method bbf_methods[] = {
UBUS_METHOD("get", bbfdm_get_handler, dm_get_policy),
UBUS_METHOD("get_async", bbfdm_get_async_handler, dm_get_policy),
UBUS_METHOD("schema", bbfdm_schema_handler, dm_schema_policy),
UBUS_METHOD("instances", bbfdm_instances_handler, dm_instances_policy),
UBUS_METHOD("set", bbfdm_set_handler, dm_set_policy),

View file

@ -48,9 +48,12 @@ struct ev_handler_node {
typedef struct bbfdm_data {
struct ubus_context *ctx;
struct ubus_request_data *req;
struct ubus_request_data amin_new_req; //new
struct list_head *plist;
struct dmctx bbf_ctx;
struct blob_buf bb;
char path[256]; //new
int pending_requests; //new
uint8_t depth;
bool is_raw;
} bbfdm_data_t;