mirror of
https://dev.iopsys.eu/bbf/bbfdm.git
synced 2026-02-20 11:28:37 +01:00
Example
This commit is contained in:
parent
8bc63723e0
commit
485c2ada13
6 changed files with 346 additions and 0 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* **********/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue