X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fubus.git;a=blobdiff_plain;f=ubusd_event.c;h=3396ebf13c725032ac1011c5652244a5fa0d580c;hp=da0aed80273ec89e505c102de5c098a418cd18da;hb=d2f9e766ffc818610262d44e0cb02b1f73d71a1f;hpb=fa989780bda3ad10fcbb637390d59afe2b32ba81 diff --git a/ubusd_event.c b/ubusd_event.c index da0aed8..3396ebf 100644 --- a/ubusd_event.c +++ b/ubusd_event.c @@ -1,41 +1,140 @@ #include "ubusd.h" static struct avl_tree patterns; +static LIST_HEAD(catch_all); static struct ubus_object *event_obj; -struct event_pattern { - struct avl_node avl; +enum evs_type { + EVS_PATTERN, + EVS_CATCHALL +}; +struct event_source { + struct list_head list; struct ubus_object *obj; + enum evs_type type; + union { + struct { + struct avl_node avl; + } pattern; + struct { + struct list_head list; + } catchall; + }; +}; + +struct event_pattern { + struct event_source evs; struct list_head list; +}; + +struct event_catchall { + struct event_source evs; - const char *path; + struct list_head list; + struct ubus_object *obj; }; -static void ubusd_delete_event_pattern(struct event_pattern *ev) +static void ubusd_delete_event_source(struct event_source *evs) { - list_del(&ev->list); - avl_delete(&patterns, &ev->avl); - free(ev); + list_del(&evs->list); + switch (evs->type) { + case EVS_PATTERN: + avl_delete(&patterns, &evs->pattern.avl); + break; + case EVS_CATCHALL: + list_del(&evs->catchall.list); + break; + } + free(evs); } void ubusd_event_cleanup_object(struct ubus_object *obj) { - struct event_pattern *ev; + struct event_source *ev; - while (!list_empty(&obj->event_patterns)) { - ev = list_first_entry(&obj->event_patterns, - struct event_pattern, list); - ubusd_delete_event_pattern(ev); + while (!list_empty(&obj->events)) { + ev = list_first_entry(&obj->events, struct event_source, list); + ubusd_delete_event_source(ev); } } -static int ubusd_event_recv(struct ubus_client *cl, const char *method, struct blob_attr *msg) +enum { + EVMSG_PATTERN, + EVMSG_OBJECT, + EVMSG_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 event_source *ubusd_alloc_event_source(struct ubus_object *obj, enum evs_type type, int datalen) +{ + struct event_source *evs; + + evs = calloc(1, sizeof(*evs) + datalen); + list_add(&evs->list, &obj->events); + evs->obj = obj; + evs->type = type; + return evs; +} + +static int ubusd_alloc_catchall(struct ubus_object *obj) +{ + struct event_source *evs; + + evs = ubusd_alloc_event_source(obj, EVS_CATCHALL, 0); + list_add(&evs->catchall.list, &catch_all); + + return 0; +} + +static int ubusd_alloc_event_pattern(struct ubus_client *cl, struct blob_attr *msg) { - fprintf(stderr, "event: call to method '%s'\n", method); + struct event_source *ev; + struct ubus_object *obj; + struct blob_attr *attr[EVMSG_LAST]; + const char *pattern; + uint32_t id; + + blobmsg_parse(ev_policy, EVMSG_LAST, attr, blob_data(msg), blob_len(msg)); + if (!attr[EVMSG_OBJECT]) + return UBUS_STATUS_INVALID_ARGUMENT; + + id = blobmsg_get_u32(attr[EVMSG_OBJECT]); + if (id < UBUS_SYSTEM_OBJECT_MAX) + return UBUS_STATUS_PERMISSION_DENIED; + + obj = ubusd_find_object(id); + if (!obj) + return UBUS_STATUS_NOT_FOUND; + + if (obj->client != cl) + return UBUS_STATUS_PERMISSION_DENIED; + + if (!attr[EVMSG_PATTERN]) + return ubusd_alloc_catchall(obj); + + pattern = blobmsg_data(attr[EVMSG_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); + avl_insert(&patterns, &ev->pattern.avl); + 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); + + return UBUS_STATUS_INVALID_COMMAND; +} + void ubusd_event_init(void) { ubus_init_string_tree(&patterns, true);