From f9f602533a454891dc5a6f1df1bd0e624295ab1f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 7 Feb 2011 01:25:28 +0100 Subject: [PATCH] add code for sending events and fix the code for receiving events --- cli.c | 24 ++++++++++++---- libubus.c | 19 ++++++++++++- libubus.h | 3 ++ ubusd.h | 2 ++ ubusd_event.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++-------- ubusd_proto.c | 2 +- 6 files changed, 118 insertions(+), 20 deletions(-) diff --git a/cli.c b/cli.c index 2d30fc5..6084a71 100644 --- a/cli.c +++ b/cli.c @@ -62,12 +62,8 @@ static void receive_event(struct ubus_context *ctx, struct ubus_event_handler *e { char *str; - if (msg) - str = blobmsg_format_json(msg, true); - else - str = ""; - - fprintf(stderr, "\"%s\":{ %s }\n", type, str); + str = blobmsg_format_json(msg, true); + printf("\"%s\": %s\n", type, str); free(str); } @@ -105,6 +101,17 @@ static int ubus_cli_listen(struct ubus_context *ctx, int argc, char **argv) return 0; } +static int ubus_cli_send(struct ubus_context *ctx, int argc, char **argv) +{ + blob_buf_init(&b, 0); + if (argc == 2 && !blobmsg_add_json_from_string(&b, argv[1])) { + fprintf(stderr, "Failed to parse message data\n"); + return UBUS_STATUS_INVALID_ARGUMENT; + } + + return ubus_send_event(ctx, argv[0], b.head); +} + static int usage(const char *prog) { fprintf(stderr, @@ -116,6 +123,7 @@ static int usage(const char *prog) " - list [] List objects\n" " - call [] Call an object method\n" " - listen [...] Listen for events\n" + " - send [] Send an event\n" "\n", prog); return 1; } @@ -180,6 +188,10 @@ int main(int argc, char **argv) ret = ubus_invoke(ctx, id, argv[1], b.head, receive_data, NULL); } else if (!strcmp(cmd, "listen")) { ret = ubus_cli_listen(ctx, argc, argv); + } else if (!strcmp(cmd, "send")) { + if (argc < 1 || argc > 2) + return usage(progname); + ret = ubus_cli_send(ctx, argc, argv); } else { return usage(progname); } diff --git a/libubus.c b/libubus.c index 3b100f1..cc59006 100644 --- a/libubus.c +++ b/libubus.c @@ -323,7 +323,7 @@ found: req.peer = hdr->peer; req.seq = hdr->seq; ret = obj->methods[method].handler(ctx, obj, &req, - obj->methods[method].name, + blob_data(attrbuf[UBUS_ATTR_METHOD]), attrbuf[UBUS_ATTR_DATA]); send: @@ -732,6 +732,23 @@ int ubus_register_event_handler(struct ubus_context *ctx, return 0; } +int ubus_send_event(struct ubus_context *ctx, const char *id, + struct blob_attr *data) +{ + struct ubus_request req; + void *s; + + blob_buf_init(&b, 0); + blob_put_int32(&b, UBUS_ATTR_OBJID, UBUS_SYSTEM_OBJECT_EVENT); + blob_put_string(&b, UBUS_ATTR_METHOD, "send"); + s = blob_nest_start(&b, UBUS_ATTR_DATA); + blobmsg_add_string(&b, "id", id); + blobmsg_add_field(&b, BLOBMSG_TYPE_TABLE, "data", blob_data(data), blob_len(data)); + blob_nest_end(&b, s); + + ubus_start_request(ctx, &req, b.head, UBUS_MSG_INVOKE, UBUS_SYSTEM_OBJECT_EVENT); + return ubus_complete_request(ctx, &req); +} static void ubus_default_connection_lost(struct ubus_context *ctx) { diff --git a/libubus.h b/libubus.h index e0f8ab2..9f21647 100644 --- a/libubus.h +++ b/libubus.h @@ -185,6 +185,9 @@ int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req, struct blob_attr *msg); /* ----------- events ----------- */ +int ubus_send_event(struct ubus_context *ctx, const char *id, + struct blob_attr *data); + int ubus_register_event_handler(struct ubus_context *ctx, struct ubus_event_handler *ev, const char *pattern); diff --git a/ubusd.h b/ubusd.h index 00ffd04..e3a8e49 100644 --- a/ubusd.h +++ b/ubusd.h @@ -12,6 +12,8 @@ #define UBUSD_CLIENT_BACKLOG 32 #define UBUS_OBJ_HASH_BITS 4 +extern struct blob_buf b; + struct ubus_msg_buf { uint32_t refcount; /* ~0: uses external data buffer */ struct ubus_msghdr hdr; diff --git a/ubusd_event.c b/ubusd_event.c index 3396ebf..dfffdee 100644 --- a/ubusd_event.c +++ b/ubusd_event.c @@ -3,6 +3,7 @@ static struct avl_tree patterns; static LIST_HEAD(catch_all); static struct ubus_object *event_obj; +static int event_seq = 0; enum evs_type { EVS_PATTERN, @@ -60,14 +61,14 @@ void ubusd_event_cleanup_object(struct ubus_object *obj) } enum { - EVMSG_PATTERN, - EVMSG_OBJECT, - EVMSG_LAST, + EVREG_PATTERN, + EVREG_OBJECT, + EVREG_LAST, }; -static struct blobmsg_policy ev_policy[] = { - [EVMSG_PATTERN] = { .name = "pattern", .type = BLOBMSG_TYPE_STRING }, - [EVMSG_OBJECT] = { .name = "object", .type = BLOBMSG_TYPE_INT32 }, +static struct blobmsg_policy evr_policy[] = { + [EVREG_PATTERN] = { .name = "pattern", .type = BLOBMSG_TYPE_STRING }, + [EVREG_OBJECT] = { .name = "object", .type = BLOBMSG_TYPE_INT32 }, }; @@ -96,15 +97,15 @@ static int ubusd_alloc_event_pattern(struct ubus_client *cl, struct blob_attr *m { struct event_source *ev; struct ubus_object *obj; - struct blob_attr *attr[EVMSG_LAST]; + struct blob_attr *attr[EVREG_LAST]; const char *pattern; uint32_t id; - blobmsg_parse(ev_policy, EVMSG_LAST, attr, blob_data(msg), blob_len(msg)); - if (!attr[EVMSG_OBJECT]) + blobmsg_parse(evr_policy, EVREG_LAST, attr, blob_data(msg), blob_len(msg)); + if (!attr[EVREG_OBJECT]) return UBUS_STATUS_INVALID_ARGUMENT; - id = blobmsg_get_u32(attr[EVMSG_OBJECT]); + id = blobmsg_get_u32(attr[EVREG_OBJECT]); if (id < UBUS_SYSTEM_OBJECT_MAX) return UBUS_STATUS_PERMISSION_DENIED; @@ -115,10 +116,10 @@ static int ubusd_alloc_event_pattern(struct ubus_client *cl, struct blob_attr *m if (obj->client != cl) return UBUS_STATUS_PERMISSION_DENIED; - if (!attr[EVMSG_PATTERN]) + if (!attr[EVREG_PATTERN]) return ubusd_alloc_catchall(obj); - pattern = blobmsg_data(attr[EVMSG_PATTERN]); + pattern = blobmsg_data(attr[EVREG_PATTERN]); ev = ubusd_alloc_event_source(obj, EVS_PATTERN, strlen(pattern) + 1); ev->pattern.avl.key = (void *) (ev + 1); strcpy(ev->pattern.avl.key, pattern); @@ -127,11 +128,74 @@ static int ubusd_alloc_event_pattern(struct ubus_client *cl, struct blob_attr *m return 0; } +enum { + EVMSG_ID, + EVMSG_DATA, + EVMSG_LAST, +}; + +static struct blobmsg_policy ev_policy[] = { + [EVMSG_ID] = { .name = "id", .type = BLOBMSG_TYPE_STRING }, + [EVMSG_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE }, +}; + +static void ubusd_send_event_msg(struct ubus_msg_buf **ub, struct ubus_object *obj, + const char *id, struct blob_attr *msg) +{ + uint32_t *objid_ptr; + + if (*ub) { + objid_ptr = blob_data(blob_data((*ub)->data)); + *objid_ptr = htonl(obj->id.id); + } else { + blob_buf_init(&b, 0); + blob_put_int32(&b, UBUS_ATTR_OBJID, obj->id.id); + blob_put_string(&b, UBUS_ATTR_METHOD, id); + blob_put(&b, UBUS_ATTR_DATA, blobmsg_data(msg), blobmsg_data_len(msg)); + + *ub = ubus_msg_new(b.head, blob_raw_len(b.head), true); + + (*ub)->hdr.type = UBUS_MSG_INVOKE; + (*ub)->hdr.peer = 0; + } + (*ub)->hdr.seq = ++event_seq; + ubus_msg_send(obj->client, *ub, false); +} + +static int ubusd_send_event(struct ubus_client *cl, struct blob_attr *msg) +{ + struct ubus_msg_buf *ub = NULL; + struct event_source *ev; + struct blob_attr *attr[EVMSG_LAST]; + const char *id; + + blobmsg_parse(ev_policy, EVMSG_LAST, attr, blob_data(msg), blob_len(msg)); + if (!attr[EVMSG_ID] || !attr[EVMSG_DATA]) + return UBUS_STATUS_INVALID_ARGUMENT; + + id = blobmsg_data(attr[EVMSG_ID]); + list_for_each_entry(ev, &catch_all, catchall.list) { + /* do not loop back events */ + if (ev->obj->client == cl) + continue; + + ubusd_send_event_msg(&ub, ev->obj, id, attr[EVMSG_DATA]); + } + + if (ub) + ubus_msg_free(ub); + + return 0; +} + static int ubusd_event_recv(struct ubus_client *cl, const char *method, struct blob_attr *msg) { if (!strcmp(method, "register")) return ubusd_alloc_event_pattern(cl, msg); + if (!strcmp(method, "send")) + return ubusd_send_event(cl, msg); + return UBUS_STATUS_INVALID_COMMAND; } diff --git a/ubusd_proto.c b/ubusd_proto.c index bdb022c..7d6e01a 100644 --- a/ubusd_proto.c +++ b/ubusd_proto.c @@ -1,7 +1,7 @@ #include #include "ubusd.h" -static struct blob_buf b; +struct blob_buf b; static struct ubus_msg_buf *retmsg; static int *retmsg_data; -- 2.11.0