add support for data replies
authorFelix Fietkau <nbd@openwrt.org>
Mon, 31 Jan 2011 16:18:10 +0000 (17:18 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 31 Jan 2011 16:18:10 +0000 (17:18 +0100)
cli.c
libubus.c
libubus.h
listener.c

diff --git a/cli.c b/cli.c
index e6b127884c20217df7e593537cb2b1a3b550fa27..a1c90fee8cc42f13436fa7aed466cde2091a4c54 100644 (file)
--- a/cli.c
+++ b/cli.c
@@ -28,6 +28,14 @@ static void receive_lookup(struct ubus_request *req, int type, struct blob_attr
        }
 }
 
+static void receive_data(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+       if (!msg)
+               return;
+
+       fprintf(stderr, "%s\n", blobmsg_format_json(msg, true));
+}
+
 static void store_objid(struct ubus_request *req, int type, struct blob_attr *msg)
 {
        struct blob_attr **attr;
@@ -46,7 +54,7 @@ static uint32_t get_object(const char *name)
        blob_buf_init(&b, 0);
        blob_put_string(&b, UBUS_ATTR_OBJPATH, name);
        ubus_start_request(ctx, &req, b.head, UBUS_MSG_LOOKUP, 0);
-       req.data_cb = store_objid;
+       req.raw_data_cb = store_objid;
        if (ubus_complete_request(ctx, &req))
                return 0;
 
@@ -87,7 +95,7 @@ int main(int argc, char **argv)
                        blob_put_string(&b, UBUS_ATTR_OBJPATH, argv[2]);
 
                ubus_start_request(ctx, &req, b.head, UBUS_MSG_LOOKUP, 0);
-               req.data_cb = receive_lookup;
+               req.raw_data_cb = receive_lookup;
        } else if (!strcmp(cmd, "call")) {
                if (argc < 4 || argc > 5)
                        return usage(argv[0]);
@@ -101,6 +109,7 @@ int main(int argc, char **argv)
                blob_put_int32(&b, UBUS_ATTR_OBJID, objid);
                blob_put_string(&b, UBUS_ATTR_METHOD, argv[3]);
                ubus_start_request(ctx, &req, b.head, UBUS_MSG_INVOKE, objid);
+               req.data_cb = receive_data;
        } else {
                return usage(argv[0]);
        }
index 64190f78df2e294b7ec8389628520bc0b26d3e6e..1342ba19463810d09220c29017ca452db60c3e82 100644 (file)
--- a/libubus.c
+++ b/libubus.c
@@ -183,6 +183,20 @@ static bool ubus_get_status(struct ubus_msghdr *hdr, int *ret)
        return true;
 }
 
+static void req_data_cb(struct ubus_request *req, int type, struct blob_attr *data)
+{
+       struct blob_attr **attr;
+
+       if (req->raw_data_cb)
+               req->raw_data_cb(req, type, data);
+
+       if (!req->data_cb)
+               return;
+
+       attr = ubus_parse_msg(data);
+       req->data_cb(req, type, attr[UBUS_ATTR_DATA]);
+}
+
 static void ubus_process_req_data(struct ubus_request *req)
 {
        struct ubus_pending_data *data;
@@ -192,7 +206,7 @@ static void ubus_process_req_data(struct ubus_request *req)
                        struct ubus_pending_data, list);
                list_del(&data->list);
                if (!req->cancelled)
-                       req->data_cb(req, data->type, data->data);
+                       req_data_cb(req, data->type, data->data);
                free(data);
        }
 }
@@ -232,7 +246,7 @@ static void ubus_req_data(struct ubus_request *req, struct ubus_msghdr *hdr)
 
        if (!req->blocked) {
                req->blocked = true;
-               req->data_cb(req, hdr->type, hdr->data);
+               req_data_cb(req, hdr->type, hdr->data);
                ubus_process_req_data(req);
                req->blocked = false;
 
@@ -304,7 +318,8 @@ found:
        req.object = objid;
        req.peer = hdr->peer;
        req.seq = hdr->seq;
-       ret = obj->methods[method].handler(obj, &req, obj->methods[method].name,
+       ret = obj->methods[method].handler(ctx, obj, &req,
+                                          obj->methods[method].name,
                                           attrbuf[UBUS_ATTR_DATA]);
 
 send:
@@ -329,7 +344,7 @@ static void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr)
 
        case UBUS_MSG_DATA:
                req = ubus_find_request(ctx, hdr->seq, hdr->peer);
-               if (req && req->data_cb)
+               if (req && (req->data_cb || req->raw_data_cb))
                        ubus_req_data(req, hdr);
                break;
 
@@ -396,7 +411,7 @@ int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req)
                case UBUS_MSG_STATUS:
                        return ubus_process_req_status(req, hdr);
                case UBUS_MSG_DATA:
-                       if (req->data_cb)
+                       if (req->data_cb || req->raw_data_cb)
                                ubus_req_data(req, hdr);
                        continue;
                default:
@@ -408,6 +423,21 @@ skip:
        }
 }
 
+int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
+                   struct blob_attr *msg)
+{
+       int ret;
+
+       blob_buf_init(&b, 0);
+       blob_put_int32(&b, UBUS_ATTR_OBJID, req->object);
+       blob_put(&b, UBUS_ATTR_DATA, blob_data(msg), blob_len(msg));
+       ret = ubus_send_msg(ctx, req->seq, b.head, UBUS_MSG_DATA, req->peer);
+       if (ret < 0)
+               return UBUS_STATUS_NO_DATA;
+
+       return 0;
+}
+
 void ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method,
                        struct blob_attr *msg, struct ubus_request *req)
 {
@@ -523,7 +553,7 @@ int ubus_publish(struct ubus_context *ctx, struct ubus_object *obj)
                return UBUS_STATUS_INVALID_ARGUMENT;
 
        ubus_start_request(ctx, &req, b.head, UBUS_MSG_PUBLISH, 0);
-       req.data_cb = ubus_publish_cb;
+       req.raw_data_cb = ubus_publish_cb;
        req.priv = obj;
        ret = ubus_complete_request(ctx, &req);
        if (ret)
index b741e652916e7b0488b0da6f9ae8b82e0cbd08a2..86581182082995e06dde13712d6c63be5be2419a 100644 (file)
--- a/libubus.h
+++ b/libubus.h
@@ -6,12 +6,13 @@
 #include "ubusmsg.h"
 #include "ubus_common.h"
 
+struct ubus_context;
 struct ubus_msg_src;
 struct ubus_object;
 struct ubus_request;
 struct ubus_request_data;
 
-typedef int (*ubus_handler_t)(struct ubus_object *obj,
+typedef int (*ubus_handler_t)(struct ubus_context *ctx, struct ubus_object *obj,
                              struct ubus_request_data *req,
                              const char *method, struct blob_attr *msg);
 typedef void (*ubus_data_handler_t)(struct ubus_request *req,
@@ -105,6 +106,7 @@ struct ubus_request {
        uint32_t peer;
        uint32_t seq;
 
+       ubus_data_handler_t raw_data_cb;
        ubus_data_handler_t data_cb;
        ubus_complete_handler_t complete_cb;
 
@@ -152,4 +154,6 @@ void ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *metho
 /* make an object visible to remote connections */
 int ubus_publish(struct ubus_context *ctx, struct ubus_object *obj);
 
-
+/* send a reply to an incoming object method call */
+int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req,
+                   struct blob_attr *msg);
index ffd8d6e5161075fa7592620e0584daaa780b3182..188cda8edcaa15b0a4dad9f8d2e02ace827c0012 100644 (file)
@@ -1,6 +1,7 @@
 #include "libubus.h"
 
 static struct ubus_context *ctx;
+struct blob_buf b;
 
 static const struct ubus_signature test_object_sig[] = {
        UBUS_METHOD_START("hello"),
@@ -15,10 +16,13 @@ static const struct ubus_signature test_object_sig[] = {
 static struct ubus_object_type test_object_type =
        UBUS_OBJECT_TYPE("test", test_object_sig);
 
-static int test_hello(struct ubus_object *obj, struct ubus_request_data *req,
-                         const char *method, struct blob_attr *msg)
+static int test_hello(struct ubus_context *ctx, struct ubus_object *obj,
+                     struct ubus_request_data *req, const char *method,
+                     struct blob_attr *msg)
 {
-       fprintf(stderr, "Hello, world!\n");
+       blob_buf_init(&b, 0);
+       blobmsg_add_string(&b, "message", "Hello, world!\n");
+       ubus_send_reply(ctx, req, b.head);
        return 0;
 }