remove path based invoke functions, add stub implementation for invoking method calls
authorFelix Fietkau <nbd@openwrt.org>
Mon, 31 Jan 2011 01:41:32 +0000 (02:41 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 31 Jan 2011 01:41:32 +0000 (02:41 +0100)
cli.c
libubus.c
libubus.h
ubusd_obj.c
ubusd_obj.h
ubusd_proto.c

diff --git a/cli.c b/cli.c
index bc884cd..e6b1278 100644 (file)
--- a/cli.c
+++ b/cli.c
@@ -2,6 +2,7 @@
 
 static struct blob_buf b;
 static struct ubus_context *ctx;
+static uint32_t objid;
 
 static void receive_lookup(struct ubus_request *req, int type, struct blob_attr *msg)
 {
@@ -27,6 +28,31 @@ static void receive_lookup(struct ubus_request *req, int type, struct blob_attr
        }
 }
 
+static void store_objid(struct ubus_request *req, int type, struct blob_attr *msg)
+{
+       struct blob_attr **attr;
+
+       attr = ubus_parse_msg(msg);
+       if (!attr[UBUS_ATTR_OBJID])
+               return;
+
+       objid = blob_get_int32(attr[UBUS_ATTR_OBJID]);
+}
+
+static uint32_t get_object(const char *name)
+{
+       struct ubus_request req;
+
+       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;
+       if (ubus_complete_request(ctx, &req))
+               return 0;
+
+       return objid;
+}
+
 static int usage(char *prog)
 {
        fprintf(stderr,
@@ -54,9 +80,9 @@ int main(int argc, char **argv)
        if (argc < 2)
                return usage(argv[0]);
 
-       blob_buf_init(&b, 0);
-
        if (!strcmp(cmd, "list")) {
+               blob_buf_init(&b, 0);
+
                if (argc == 3)
                        blob_put_string(&b, UBUS_ATTR_OBJPATH, argv[2]);
 
@@ -66,9 +92,15 @@ int main(int argc, char **argv)
                if (argc < 4 || argc > 5)
                        return usage(argv[0]);
 
-               blob_put_string(&b, UBUS_ATTR_OBJPATH, argv[2]);
+               if (get_object(argv[2]) == 0) {
+                       fprintf(stderr, "Object not found\n");
+                       return 1;
+               }
+
+               blob_buf_init(&b, 0);
+               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, 0);
+               ubus_start_request(ctx, &req, b.head, UBUS_MSG_INVOKE, objid);
        } else {
                return usage(argv[0]);
        }
index 9e93aed..7bf67a7 100644 (file)
--- a/libubus.c
+++ b/libubus.c
@@ -66,23 +66,19 @@ out:
        return err;
 }
 
-int ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
-                      struct blob_attr *msg, int cmd, uint32_t peer)
+static int ubus_send_msg(struct ubus_context *ctx, uint32_t seq,
+                        struct blob_attr *msg, int cmd, uint32_t peer)
 {
        struct ubus_msghdr hdr;
        struct iovec iov[2] = {
                STATIC_IOV(hdr)
        };
 
-       memset(req, 0, sizeof(*req));
        hdr.version = 0;
        hdr.type = cmd;
-       hdr.seq = ++ctx->request_seq;
+       hdr.seq = seq;
        hdr.peer = peer;
 
-       req->peer = hdr.peer;
-       req->seq = hdr.seq;
-
        if (!msg) {
                blob_buf_init(&b, 0);
                msg = b.head;
@@ -90,12 +86,22 @@ int ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
 
        iov[1].iov_base = (char *) msg;
        iov[1].iov_len = blob_raw_len(msg);
-       INIT_LIST_HEAD(&req->list);
-       INIT_LIST_HEAD(&req->pending);
 
        return writev(ctx->sock.fd, iov, 2);
 }
 
+int ubus_start_request(struct ubus_context *ctx, struct ubus_request *req,
+                      struct blob_attr *msg, int cmd, uint32_t peer)
+{
+       memset(req, 0, sizeof(*req));
+
+       INIT_LIST_HEAD(&req->list);
+       INIT_LIST_HEAD(&req->pending);
+       req->peer = peer;
+       req->seq = ++ctx->request_seq;
+       return ubus_send_msg(ctx, req->seq, msg, cmd, peer);
+}
+
 static bool recv_retry(int fd, struct iovec *iov, bool wait)
 {
        int bytes;
@@ -232,26 +238,60 @@ static void ubus_req_data(struct ubus_request *req, struct ubus_msghdr *hdr)
        list_add(&data->list, &req->pending);
 }
 
-static void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr)
+static struct ubus_request *ubus_find_request(struct ubus_context *ctx, uint32_t seq, uint32_t peer)
 {
        struct ubus_request *req;
 
        list_for_each_entry(req, &ctx->requests, list) {
-               if (hdr->seq != req->seq || hdr->peer != req->peer)
+               if (seq != req->seq || peer != req->peer)
                        continue;
 
-               switch(hdr->type) {
-               case UBUS_MSG_STATUS:
-                       ubus_process_req_status(req, hdr);
-                       return;
-               case UBUS_MSG_DATA:
-                       if (req->data_cb)
-                               ubus_req_data(req, hdr);
-                       break;
-               default:
-                       DPRINTF("unknown message type: %d\n", hdr->type);
+               return req;
+       }
+       return NULL;
+}
+
+static void ubus_process_invoke(struct ubus_context *ctx, struct ubus_msghdr *hdr)
+{
+       uint32_t objid = 0;
+       int ret = 0;
+
+       ubus_parse_msg(hdr->data);
+
+       if (attrbuf[UBUS_ATTR_OBJID])
+               objid = blob_get_int32(attrbuf[UBUS_ATTR_OBJID]);
+
+       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, hdr->seq, b.head, UBUS_MSG_STATUS, hdr->peer);
+}
+
+static void ubus_process_msg(struct ubus_context *ctx, struct ubus_msghdr *hdr)
+{
+       struct ubus_request *req;
+
+       switch(hdr->type) {
+       case UBUS_MSG_STATUS:
+               req = ubus_find_request(ctx, hdr->seq, hdr->peer);
+               if (!req)
                        break;
-               }
+
+               ubus_process_req_status(req, hdr);
+               break;
+
+       case UBUS_MSG_DATA:
+               req = ubus_find_request(ctx, hdr->seq, hdr->peer);
+               if (req && req->data_cb)
+                       ubus_req_data(req, hdr);
+               break;
+
+       case UBUS_MSG_INVOKE:
+               ubus_process_invoke(ctx, hdr);
+               break;
+       default:
+               DPRINTF("unknown message type: %d\n", hdr->type);
+               break;
        }
 }
 
@@ -305,8 +345,7 @@ int ubus_complete_request(struct ubus_context *ctx, struct ubus_request *req)
                                ubus_req_data(req, hdr);
                        continue;
                default:
-                       DPRINTF("unknown message type: %d\n", hdr->type);
-                       continue;
+                       goto skip;
                }
 
 skip:
@@ -314,28 +353,6 @@ skip:
        }
 }
 
-void ubus_invoke_path_async(struct ubus_context *ctx, const char *path, const char *method,
-                       struct blob_attr *msg, struct ubus_request *req)
-{
-       blob_buf_init(&b, 0);
-       blob_put_string(&b, UBUS_ATTR_OBJPATH, path);
-       blob_put_string(&b, UBUS_ATTR_METHOD, method);
-       blob_put(&b, UBUS_ATTR_DATA, blob_data(msg), blob_len(msg));
-
-       ubus_start_request(ctx, req, b.head, UBUS_MSG_INVOKE, 0);
-}
-
-int ubus_invoke_path(struct ubus_context *ctx, const char *path, const char *method,
-                struct blob_attr *msg, ubus_data_handler_t cb, void *priv)
-{
-       struct ubus_request req;
-
-       ubus_invoke_path_async(ctx, path, method, msg, &req);
-       req.data_cb = cb;
-       req.priv = priv;
-       return ubus_complete_request(ctx, &req);
-}
-
 void ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method,
                        struct blob_attr *msg, struct ubus_request *req)
 {
@@ -344,7 +361,7 @@ void ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *metho
        blob_put_string(&b, UBUS_ATTR_METHOD, method);
        blob_put(&b, UBUS_ATTR_DATA, blob_data(msg), blob_len(msg));
 
-       ubus_start_request(ctx, req, b.head, UBUS_MSG_INVOKE, 0);
+       ubus_start_request(ctx, req, b.head, UBUS_MSG_INVOKE, obj);
 }
 
 int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
@@ -511,6 +528,7 @@ struct ubus_context *ubus_connect(const char *path)
        }
 
        ctx->local_id = hdr.hdr.peer;
+       INIT_LIST_HEAD(&ctx->requests);
        free(buf);
 
        if (!ctx->local_id) {
index 3da5d21..bd3d736 100644 (file)
--- a/libubus.h
+++ b/libubus.h
@@ -130,14 +130,10 @@ void ubus_abort_request(struct ubus_context *ctx, struct ubus_request *req);
 /* invoke a method on a specific object */
 int ubus_invoke(struct ubus_context *ctx, uint32_t obj, const char *method,
                 struct blob_attr *msg, ubus_data_handler_t cb, void *priv);
-int ubus_invoke_path(struct ubus_context *ctx, const char *path, const char *method,
-                struct blob_attr *msg, ubus_data_handler_t cb, void *priv);
 
 /* asynchronous version of ubus_invoke() */
 void ubus_invoke_async(struct ubus_context *ctx, uint32_t obj, const char *method,
                        struct blob_attr *msg, struct ubus_request *req);
-void ubus_invoke_path_async(struct ubus_context *ctx, const char *path, const char *method,
-                       struct blob_attr *msg, struct ubus_request *req);
 
 /* make an object visible to remote connections */
 int ubus_publish(struct ubus_context *ctx, struct ubus_object *obj);
index 5e08fab..a702fa6 100644 (file)
@@ -109,6 +109,7 @@ struct ubus_object *ubusd_create_object(struct ubus_client *cl, struct blob_attr
        }
 
        obj->type = type;
+       obj->client = cl;
        list_add(&obj->list, &cl->objects);
 
        return obj;
index 943ee13..2064084 100644 (file)
@@ -27,8 +27,9 @@ struct ubus_object {
        struct list_head list;
 
        struct ubus_object_type *type;
-
        struct avl_node path;
+
+       struct ubus_client *client;
 };
 
 struct ubus_object *ubusd_create_object(struct ubus_client *cl, struct blob_attr **attr);
index 8a69541..3c5a236 100644 (file)
@@ -13,6 +13,8 @@ static const struct blob_attr_info ubus_policy[UBUS_ATTR_MAX] = {
        [UBUS_ATTR_SIGNATURE] = { .type = BLOB_ATTR_NESTED },
        [UBUS_ATTR_OBJTYPE] = { .type = BLOB_ATTR_INT32 },
        [UBUS_ATTR_OBJPATH] = { .type = BLOB_ATTR_STRING },
+       [UBUS_ATTR_OBJID] = { .type = BLOB_ATTR_INT32 },
+       [UBUS_ATTR_STATUS] = { .type = BLOB_ATTR_INT32 },
 };
 
 struct blob_attr **ubus_parse_msg(struct blob_attr *msg)
@@ -163,7 +165,66 @@ static int ubusd_handle_lookup(struct ubus_client *cl, struct ubus_msg_buf *ub)
 
 static int ubusd_handle_invoke(struct ubus_client *cl, struct ubus_msg_buf *ub)
 {
-       return UBUS_STATUS_NOT_FOUND;
+       struct ubus_object *obj = NULL;
+       struct blob_attr **attr;
+       const char *method;
+
+       attr = ubus_parse_msg(ub->data);
+       if (!attr[UBUS_ATTR_METHOD])
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
+       if (attr[UBUS_ATTR_OBJID]) {
+               struct ubus_id *id;
+               id = ubus_find_id(&objects, blob_get_int32(attr[UBUS_ATTR_OBJID]));
+               if (id)
+                       obj = container_of(id, struct ubus_object, id);
+       } else if (attr[UBUS_ATTR_OBJPATH]) {
+               const char *objpath = blob_data(attr[UBUS_ATTR_OBJPATH]);
+               obj = avl_find_element(&path, objpath, obj, path);
+       }
+       if (!obj)
+               return UBUS_STATUS_NOT_FOUND;
+
+       method = blob_data(attr[UBUS_ATTR_METHOD]);
+       blob_buf_init(&b, 0);
+       blob_put_int32(&b, UBUS_ATTR_OBJID, obj->id.id);
+       blob_put_string(&b, UBUS_ATTR_METHOD, method);
+       if (attr[UBUS_ATTR_DATA])
+               blob_put(&b, UBUS_ATTR_DATA, blob_data(attr[UBUS_ATTR_DATA]),
+                        blob_len(attr[UBUS_ATTR_DATA]));
+
+       ubus_msg_free(ub);
+
+       ub = ubus_reply_from_blob(ub, true);
+       if (!ub)
+               return UBUS_STATUS_NO_DATA;
+
+       ub->hdr.type = UBUS_MSG_INVOKE;
+       ub->hdr.peer = cl->id.id;
+       ubus_msg_send(obj->client, ub);
+
+       return -1;
+}
+
+static int ubusd_handle_status(struct ubus_client *cl, struct ubus_msg_buf *ub)
+{
+       struct blob_attr **attr;
+
+       attr = ubus_parse_msg(ub->data);
+       if (!attr[UBUS_ATTR_OBJID] || !attr[UBUS_ATTR_STATUS])
+               goto error;
+
+       cl = ubusd_get_client_by_id(ub->hdr.peer);
+       if (!cl)
+               goto error;
+
+       ub->hdr.peer = blob_get_int32(attr[UBUS_ATTR_OBJID]);
+       ubus_msg_send(cl, ub);
+       return -1;
+
+error:
+       ubus_msg_free(ub);
+       return -1;
 }
 
 static const ubus_cmd_cb handlers[__UBUS_MSG_LAST] = {
@@ -171,6 +232,7 @@ static const ubus_cmd_cb handlers[__UBUS_MSG_LAST] = {
        [UBUS_MSG_PUBLISH] = ubusd_handle_publish,
        [UBUS_MSG_LOOKUP] = ubusd_handle_lookup,
        [UBUS_MSG_INVOKE] = ubusd_handle_invoke,
+       [UBUS_MSG_STATUS] = ubusd_handle_status,
 };
 
 void ubusd_receive_message(struct ubus_client *cl, struct ubus_msg_buf *ub)
@@ -189,6 +251,9 @@ void ubusd_receive_message(struct ubus_client *cl, struct ubus_msg_buf *ub)
        else
                ret = UBUS_STATUS_INVALID_COMMAND;
 
+       if (ret == -1)
+               return;
+
        ubus_msg_free(ub);
 
        *retmsg_data = htonl(ret);