X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fubus.git;a=blobdiff_plain;f=libubus-obj.c;h=990d04bd9844b8d590c555193742575e58e1458f;hp=cf50904a7d45092b8b72a2e88a3e4766455c4e98;hb=e59b44573423ad608d0752b46a6073222db9ed45;hpb=9f706a2d27719ff39bbe71472f48a791ec306164 diff --git a/libubus-obj.c b/libubus-obj.c index cf50904..990d04b 100644 --- a/libubus-obj.c +++ b/libubus-obj.c @@ -14,34 +14,66 @@ #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 (!obj || !attrbuf[UBUS_ATTR_TARGET]) + return; - if (!attrbuf[UBUS_ATTR_OBJID]) + if (obj->methods != &watch_method) return; - req.object = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]); + s = container_of(obj, struct ubus_subscriber, obj); + if (s->remove_cb) + s->remove_cb(ctx, s, blob_get_u32(attrbuf[UBUS_ATTR_TARGET])); +} - if (!attrbuf[UBUS_ATTR_METHOD]) { - ret = UBUS_STATUS_INVALID_ARGUMENT; - goto send; - } +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 = { + .fd = -1, + }; + int method; + int ret; + bool no_reply = false; - obj = avl_find_element(&ctx->objects, &req.object, obj, avl); if (!obj) { ret = UBUS_STATUS_NOT_FOUND; goto send; } + if (!attrbuf[UBUS_ATTR_METHOD]) { + ret = UBUS_STATUS_INVALID_ARGUMENT; + goto send; + } + + if (attrbuf[UBUS_ATTR_NO_REPLY]) + no_reply = blob_get_int8(attrbuf[UBUS_ATTR_NO_REPLY]); + + req.peer = hdr->peer; + req.seq = hdr->seq; + req.object = obj->id; + if (attrbuf[UBUS_ATTR_USER] && attrbuf[UBUS_ATTR_GROUP]) { + req.acl.user = blobmsg_get_string(attrbuf[UBUS_ATTR_USER]); + req.acl.group = blobmsg_get_string(attrbuf[UBUS_ATTR_GROUP]); + req.acl.object = obj->name; + } for (method = 0; method < obj->n_methods; method++) if (!obj->methods[method].name || !strcmp(obj->methods[method].name, @@ -56,13 +88,59 @@ found: ret = obj->methods[method].handler(ctx, obj, &req, blob_data(attrbuf[UBUS_ATTR_METHOD]), attrbuf[UBUS_ATTR_DATA]); - if (req.deferred) + if (req.deferred || no_reply) return; send: ubus_complete_deferred_request(ctx, &req, ret); } +void __hidden ubus_process_obj_msg(struct ubus_context *ctx, struct ubus_msghdr_buf *buf) +{ + void (*cb)(struct ubus_context *, struct ubus_msghdr *, + struct ubus_object *, struct blob_attr **); + struct ubus_msghdr *hdr = &buf->hdr; + struct blob_attr **attrbuf; + struct ubus_object *obj; + uint32_t objid; + void *prev_data = NULL; + + attrbuf = ubus_parse_msg(buf->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; + } + + if (buf == &ctx->msgbuf) { + prev_data = buf->data; + buf->data = NULL; + } + + cb(ctx, hdr, obj, attrbuf); + + if (prev_data) { + if (buf->data) + free(prev_data); + else + buf->data = prev_data; + } +} + static void ubus_add_object_cb(struct ubus_request *req, int type, struct blob_attr *msg) { struct ubus_object *obj = req->priv; @@ -87,8 +165,12 @@ static void ubus_push_method_data(const struct ubus_method *m) mtbl = blobmsg_open_table(&b, m->name); - for (i = 0; i < m->n_policy; i++) + for (i = 0; i < m->n_policy; i++) { + if (m->mask && !(m->mask & (1 << i))) + continue; + blobmsg_add_u32(&b, m->policy[i].name, m->policy[i].type); + } blobmsg_close_table(&b, mtbl); }