add support for deferring a reply to a method invoke call
authorFelix Fietkau <nbd@openwrt.org>
Mon, 1 Oct 2012 12:09:19 +0000 (14:09 +0200)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 1 Oct 2012 12:09:19 +0000 (14:09 +0200)
libubus.c
libubus.h

index 5488f3b8dcc6c1f05ed0250aa3bbe2c19ec18e0c..6291e757792e517b31a57805dc3f3b2874873065 100644 (file)
--- a/libubus.c
+++ b/libubus.c
@@ -342,11 +342,18 @@ static struct ubus_request *ubus_find_request(struct ubus_context *ctx, uint32_t
        return NULL;
 }
 
+void ubus_complete_deferred_request(struct ubus_context *ctx, struct ubus_request_data *req, int ret)
+{
+       blob_buf_init(&b, 0);
+       blob_put_int32(&b, UBUS_ATTR_STATUS, ret);
+       blob_put_int32(&b, UBUS_ATTR_OBJID, req->object);
+       ubus_send_msg(ctx, req->seq, b.head, UBUS_MSG_STATUS, req->peer);
+}
+
 static void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr)
 {
        struct ubus_request_data req;
        struct ubus_object *obj;
-       uint32_t objid = 0;
        int method;
        int ret = 0;
 
@@ -357,14 +364,14 @@ static void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hd
        if (!attrbuf[UBUS_ATTR_OBJID])
                return;
 
-       objid = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
+       req.object = blob_get_u32(attrbuf[UBUS_ATTR_OBJID]);
 
        if (!attrbuf[UBUS_ATTR_METHOD]) {
                ret = UBUS_STATUS_INVALID_ARGUMENT;
                goto send;
        }
 
-       obj = avl_find_element(&ctx->objects, &objid, obj, avl);
+       obj = avl_find_element(&ctx->objects, &req.object, obj, avl);
        if (!obj) {
                ret = UBUS_STATUS_NOT_FOUND;
                goto send;
@@ -381,16 +388,14 @@ static void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hd
        goto send;
 
 found:
-       req.object = objid;
        ret = obj->methods[method].handler(ctx, obj, &req,
                                           blob_data(attrbuf[UBUS_ATTR_METHOD]),
                                           attrbuf[UBUS_ATTR_DATA]);
+       if (req.deferred)
+               return;
 
 send:
-       blob_buf_init(&b, 0);
-       blob_put_int32(&b, UBUS_ATTR_STATUS, ret);
-       blob_put_int32(&b, UBUS_ATTR_OBJID, objid);
-       ubus_send_msg(ctx, req.seq, b.head, UBUS_MSG_STATUS, req.peer);
+       ubus_complete_deferred_request(ctx, &req, ret);
 }
 
 static void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr)
index 99cbbb44701f96621489ce906cfe42b38a58bc61..59d981e7141ec6b80ecb63bce52a7729833d15ea 100644 (file)
--- a/libubus.h
+++ b/libubus.h
@@ -132,6 +132,7 @@ struct ubus_request_data {
        uint32_t object;
        uint32_t peer;
        uint32_t seq;
+       bool deferred;
 };
 
 struct ubus_request {
@@ -220,6 +221,17 @@ int ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method
 int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
                    struct blob_attr *msg);
 
+static inline void ubus_defer_request(struct ubus_context *ctx,
+                                     struct ubus_request_data *req,
+                                     struct ubus_request_data *new_req)
+{
+    memcpy(new_req, req, sizeof(*req));
+    req->deferred = true;
+}
+
+void ubus_complete_deferred_request(struct ubus_context *ctx,
+                                   struct ubus_request_data *req, int ret);
+
 /* ----------- events ----------- */
 
 int ubus_send_event(struct ubus_context *ctx, const char *id,