Browse Source

remove path based invoke functions, add stub implementation for invoking method calls

Felix Fietkau 13 years ago
parent
commit
527d252333
6 changed files with 170 additions and 57 deletions
  1. 36 4
      cli.c
  2. 65 47
      libubus.c
  3. 0 4
      libubus.h
  4. 1 0
      ubusd_obj.c
  5. 2 1
      ubusd_obj.h
  6. 66 1
      ubusd_proto.c

+ 36 - 4
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]);
 	}

+ 65 - 47
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) {

+ 0 - 4
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);

+ 1 - 0
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;

+ 2 - 1
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);

+ 66 - 1
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);