add code for sending events and fix the code for receiving events
authorFelix Fietkau <nbd@openwrt.org>
Mon, 7 Feb 2011 00:25:28 +0000 (01:25 +0100)
committerFelix Fietkau <nbd@openwrt.org>
Mon, 7 Feb 2011 00:25:28 +0000 (01:25 +0100)
cli.c
libubus.c
libubus.h
ubusd.h
ubusd_event.c
ubusd_proto.c

diff --git a/cli.c b/cli.c
index 2d30fc527712b8c99a96db737ae5724ee98dbc9f..6084a719aee310f1c5906f8e503c163b09605e25 100644 (file)
--- 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 [<path>]                       List objects\n"
                " - call <path> <method> [<message>]    Call an object method\n"
                " - listen [<path>...]                  Listen for events\n"
+               " - send <type> [<message>]             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);
        }
index 3b100f111f16b5d4d6841c2d70326e8899c1c323..cc590061d59e4ab10f9178fad868238d3c63a30e 100644 (file)
--- 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)
 {
index e0f8ab24abaef190c512716cacd4ffbce1a1d7ee..9f21647d80feea40690447a5a2381eaaa4fdd57c 100644 (file)
--- 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 00ffd0463e7b0fdb539bda80a8369ab2e9c63777..e3a8e49e123ca79ff1ef412dbc2b3d15c017c98e 100644 (file)
--- 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;
index 3396ebf13c725032ac1011c5652244a5fa0d580c..dfffdeeadd051394da7da1e99d21b0adece98a40 100644 (file)
@@ -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;
 }
 
index bdb022c5091b620462a4f2774b6afbd717402d94..7d6e01a95beadb7ff1bd55d7b99d4a70782bb0e4 100644 (file)
@@ -1,7 +1,7 @@
 #include <arpa/inet.h>
 #include "ubusd.h"
 
-static struct blob_buf b;
+struct blob_buf b;
 static struct ubus_msg_buf *retmsg;
 static int *retmsg_data;