X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fubus.git;a=blobdiff_plain;f=libubus-obj.c;h=47bdb0a4e758683a4c044b4e56dfa1968b8d4acc;hp=532a7fa72ab548c3ce65608ebf92a2bf2db42603;hb=af63ab64af10798468ca1453de2360fcda44aab9;hpb=a6f52f058e52c7720afb05e5e4e51648e636b940 diff --git a/libubus-obj.c b/libubus-obj.c index 532a7fa..47bdb0a 100644 --- a/libubus-obj.c +++ b/libubus-obj.c @@ -14,34 +14,62 @@ #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; + for (method = 0; method < obj->n_methods; method++) if (!obj->methods[method].name || !strcmp(obj->methods[method].name, @@ -56,13 +84,44 @@ 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 *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(ubus_msghdr_data(hdr)); + 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; @@ -87,8 +146,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); }