From 527d2523330cb41e23a435d89352680d108c789a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 31 Jan 2011 02:41:32 +0100 Subject: [PATCH] remove path based invoke functions, add stub implementation for invoking method calls --- cli.c | 40 ++++++++++++++++-- libubus.c | 112 +++++++++++++++++++++++++++++--------------------- libubus.h | 4 -- ubusd_obj.c | 1 + ubusd_obj.h | 3 +- ubusd_proto.c | 67 +++++++++++++++++++++++++++++- 6 files changed, 170 insertions(+), 57 deletions(-) diff --git a/cli.c b/cli.c index bc884cd..e6b1278 100644 --- 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]); } diff --git a/libubus.c b/libubus.c index 9e93aed..7bf67a7 100644 --- 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) { diff --git a/libubus.h b/libubus.h index 3da5d21..bd3d736 100644 --- 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); diff --git a/ubusd_obj.c b/ubusd_obj.c index 5e08fab..a702fa6 100644 --- a/ubusd_obj.c +++ b/ubusd_obj.c @@ -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; diff --git a/ubusd_obj.h b/ubusd_obj.h index 943ee13..2064084 100644 --- a/ubusd_obj.h +++ b/ubusd_obj.h @@ -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); diff --git a/ubusd_proto.c b/ubusd_proto.c index 8a69541..3c5a236 100644 --- a/ubusd_proto.c +++ b/ubusd_proto.c @@ -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); -- 2.25.1