libubus: reduce code duplication and add stack depth protection for unsubscribe/notify callbacks
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
This commit is contained in:
parent
0fccce4445
commit
7cd33a8e3a
4 changed files with 75 additions and 72 deletions
|
@ -23,10 +23,9 @@ void ubus_handle_data(struct uloop_fd *u, unsigned int events);
|
|||
int ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
|
||||
struct blob_attr *msg, int cmd, uint32_t peer);
|
||||
void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr);
|
||||
void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr);
|
||||
int __hidden ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
|
||||
struct blob_attr *msg, int cmd, uint32_t peer);
|
||||
void ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr);
|
||||
void ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr);
|
||||
void ubus_process_obj_msg(struct ubus_context*ctx, struct ubus_msghdr *hdr);
|
||||
extern const struct ubus_method watch_method;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,33 +14,54 @@
|
|||
#include "libubus.h"
|
||||
#include "libubus-internal.h"
|
||||
|
||||
void __hidden ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr)
|
||||
static void
|
||||
ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr,
|
||||
struct ubus_object *obj, struct blob_attr **attrbuf)
|
||||
{
|
||||
struct blob_attr **attrbuf;
|
||||
struct ubus_request_data req = {};
|
||||
struct ubus_object *obj;
|
||||
int method;
|
||||
int ret = 0;
|
||||
struct ubus_subscriber *s;
|
||||
|
||||
req.peer = hdr->peer;
|
||||
req.seq = hdr->seq;
|
||||
attrbuf = ubus_parse_msg(hdr->data);
|
||||
|
||||
if (!attrbuf[UBUS_ATTR_OBJID])
|
||||
if (!obj || !attrbuf[UBUS_ATTR_TARGET])
|
||||
return;
|
||||
|
||||
req.object = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
|
||||
if (obj->methods != &watch_method)
|
||||
return;
|
||||
|
||||
s = container_of(obj, struct ubus_subscriber, obj);
|
||||
s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET]));
|
||||
}
|
||||
|
||||
static void
|
||||
ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr,
|
||||
struct ubus_object *obj, struct blob_attr **attrbuf)
|
||||
{
|
||||
if (!obj || !attrbuf[UBUS_ATTR_ACTIVE])
|
||||
return;
|
||||
|
||||
obj->has_subscribers = blob_get_u8(attrbuf[UBUS_ATTR_ACTIVE]);
|
||||
if (obj->subscribe_cb)
|
||||
obj->subscribe_cb(ctx, obj);
|
||||
}
|
||||
static void
|
||||
ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr,
|
||||
struct ubus_object *obj, struct blob_attr **attrbuf)
|
||||
{
|
||||
struct ubus_request_data req = {};
|
||||
int method;
|
||||
int ret;
|
||||
|
||||
if (!obj) {
|
||||
ret = UBUS_STATUS_NOT_FOUND;
|
||||
goto send;
|
||||
}
|
||||
|
||||
if (!attrbuf[UBUS_ATTR_METHOD]) {
|
||||
ret = UBUS_STATUS_INVALID_ARGUMENT;
|
||||
goto send;
|
||||
}
|
||||
|
||||
obj = avl_find_element(&ctx->objects, &req.object, obj, avl);
|
||||
if (!obj) {
|
||||
ret = UBUS_STATUS_NOT_FOUND;
|
||||
goto send;
|
||||
}
|
||||
req.peer = hdr->peer;
|
||||
req.seq = hdr->seq;
|
||||
req.object = obj->id;
|
||||
|
||||
for (method = 0; method < obj->n_methods; method++)
|
||||
if (!obj->methods[method].name ||
|
||||
|
@ -63,6 +84,37 @@ send:
|
|||
ubus_complete_deferred_request(ctx, &req, ret);
|
||||
}
|
||||
|
||||
void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr)
|
||||
{
|
||||
void (*cb)(struct ubus_context *, struct ubus_msghdr *,
|
||||
struct ubus_object *, struct blob_attr **);
|
||||
struct blob_attr **attrbuf;
|
||||
struct ubus_object *obj;
|
||||
uint32_t objid;
|
||||
|
||||
attrbuf = ubus_parse_msg(hdr->data);
|
||||
if (!attrbuf[UBUS_ATTR_OBJID])
|
||||
return;
|
||||
|
||||
objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
|
||||
obj = avl_find_element(&ctx->objects, &objid, obj, avl);
|
||||
|
||||
switch (hdr->type) {
|
||||
case UBUS_MSG_INVOKE:
|
||||
cb = ubus_process_invoke;
|
||||
break;
|
||||
case UBUS_MSG_UNSUBSCRIBE:
|
||||
cb = ubus_process_unsubscribe;
|
||||
break;
|
||||
case UBUS_MSG_NOTIFY:
|
||||
cb = ubus_process_notify;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
cb(ctx, hdr, obj, attrbuf);
|
||||
}
|
||||
|
||||
static void ubus_add_object_cb(struct ubus_request *req, int type, struct blob_attr *msg)
|
||||
{
|
||||
struct ubus_object *obj = req->priv;
|
||||
|
|
|
@ -25,7 +25,7 @@ static int ubus_subscriber_cb(struct ubus_context *ctx, struct ubus_object *obj,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct ubus_method watch_method = {
|
||||
const struct ubus_method watch_method __hidden = {
|
||||
.name = NULL,
|
||||
.handler = ubus_subscriber_cb,
|
||||
};
|
||||
|
@ -66,45 +66,3 @@ int ubus_unsubscribe(struct ubus_context *ctx, struct ubus_subscriber *obj, uint
|
|||
return __ubus_subscribe_request(ctx, &obj->obj, id, UBUS_MSG_UNSUBSCRIBE);
|
||||
}
|
||||
|
||||
void __hidden ubus_process_unsubscribe(struct ubus_context *ctx, struct ubus_msghdr *hdr)
|
||||
{
|
||||
struct ubus_subscriber *s;
|
||||
struct blob_attr **attrbuf;
|
||||
struct ubus_object *obj;
|
||||
uint32_t objid;
|
||||
|
||||
attrbuf = ubus_parse_msg(hdr->data);
|
||||
if (!attrbuf[UBUS_ATTR_OBJID] || !attrbuf[UBUS_ATTR_TARGET])
|
||||
return;
|
||||
|
||||
objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
|
||||
obj = avl_find_element(&ctx->objects, &objid, obj, avl);
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
if (obj->methods != &watch_method)
|
||||
return;
|
||||
|
||||
s = container_of(obj, struct ubus_subscriber, obj);
|
||||
s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET]));
|
||||
}
|
||||
|
||||
void __hidden ubus_process_notify(struct ubus_context *ctx, struct ubus_msghdr *hdr)
|
||||
{
|
||||
struct blob_attr **attrbuf;
|
||||
struct ubus_object *obj;
|
||||
uint32_t objid;
|
||||
|
||||
attrbuf = ubus_parse_msg(hdr->data);
|
||||
if (!attrbuf[UBUS_ATTR_OBJID] || !attrbuf[UBUS_ATTR_ACTIVE])
|
||||
return;
|
||||
|
||||
objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
|
||||
obj = avl_find_element(&ctx->objects, &objid, obj, avl);
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
obj->has_subscribers = blob_get_u8(attrbuf[UBUS_ATTR_ACTIVE]);
|
||||
if (obj->subscribe_cb)
|
||||
obj->subscribe_cb(ctx, obj);
|
||||
}
|
||||
|
|
12
libubus.c
12
libubus.c
|
@ -214,6 +214,8 @@ void __hidden ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr
|
|||
break;
|
||||
|
||||
case UBUS_MSG_INVOKE:
|
||||
case UBUS_MSG_UNSUBSCRIBE:
|
||||
case UBUS_MSG_NOTIFY:
|
||||
if (ctx->stack_depth > 2) {
|
||||
pending = calloc(1, sizeof(*pending) +
|
||||
blob_raw_len(hdr->data));
|
||||
|
@ -225,17 +227,9 @@ void __hidden ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr
|
|||
blob_raw_len(hdr->data));
|
||||
list_add(&pending->list, &ctx->pending);
|
||||
} else {
|
||||
ubus_process_invoke(ctx, hdr);
|
||||
ubus_process_obj_msg(ctx, hdr);
|
||||
}
|
||||
break;
|
||||
|
||||
case UBUS_MSG_UNSUBSCRIBE:
|
||||
ubus_process_unsubscribe(ctx, hdr);
|
||||
break;
|
||||
|
||||
case UBUS_MSG_NOTIFY:
|
||||
ubus_process_notify(ctx, hdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue