From: Felix Fietkau Date: Mon, 7 Feb 2011 02:51:00 +0000 (+0100) Subject: implement event pattern matching X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fubus.git;a=commitdiff_plain;h=96e0b8ca42d49aceb9e727a498ee1a951f2ddf75 implement event pattern matching --- diff --git a/ubusd_event.c b/ubusd_event.c index de36879..a5ff09e 100644 --- a/ubusd_event.c +++ b/ubusd_event.c @@ -4,6 +4,7 @@ static struct avl_tree patterns; static LIST_HEAD(catch_all); static struct ubus_object *event_obj; static int event_seq = 0; +static int obj_event_seq = 0; enum evs_type { EVS_PATTERN, @@ -139,11 +140,22 @@ static struct blobmsg_policy ev_policy[] = { [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) +static void ubusd_send_event_msg(struct ubus_msg_buf **ub, struct ubus_client *cl, + struct ubus_object *obj, const char *id, + struct blob_attr *msg) { uint32_t *objid_ptr; + /* do not loop back events */ + if (obj->client == cl) + return; + + /* do not send duplicate events */ + if (obj->event_seen == obj_event_seq) + return; + + obj->event_seen = obj_event_seq; + if (*ub) { objid_ptr = blob_data(blob_data((*ub)->data)); *objid_ptr = htonl(obj->id.id); @@ -162,24 +174,61 @@ static void ubusd_send_event_msg(struct ubus_msg_buf **ub, struct ubus_object *o ubus_msg_send(obj->client, *ub, false); } +bool strmatch_len(const char *s1, const char *s2, int *len) +{ + for (*len = 0; s1[*len] == s2[*len]; (*len)++) + if (!s1[*len]) + return true; + + return 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; + int match_len = 0; + void *data; 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; + data = attr[EVMSG_DATA]; + + list_for_each_entry(ev, &catch_all, catchall.list) + ubusd_send_event_msg(&ub, cl, ev->obj, id, data); + + obj_event_seq++; + + /* + * Since this tree is sorted alphabetically, we can only expect to find + * matching entries as long as the number of matching characters + * between the pattern string and our string is monotonically increasing. + */ + avl_for_each_element(&patterns, ev, pattern.avl) { + const char *key = ev->pattern.avl.key; + int cur_match_len; + bool full_match; + + full_match = strmatch_len(id, key, &cur_match_len); + if (cur_match_len < match_len) + break; + + match_len = cur_match_len; + + if (!full_match) { + if (!ev->pattern.partial) + continue; + + if (match_len != strlen(key)) + continue; + } - ubusd_send_event_msg(&ub, ev->obj, id, attr[EVMSG_DATA]); + ubusd_send_event_msg(&ub, cl, ev->obj, id, data); } if (ub) diff --git a/ubusd_obj.h b/ubusd_obj.h index b268792..3fc4937 100644 --- a/ubusd_obj.h +++ b/ubusd_obj.h @@ -33,6 +33,8 @@ struct ubus_object { struct ubus_client *client; int (*recv_msg)(struct ubus_client *client, const char *method, struct blob_attr *msg); + + int event_seen; }; struct ubus_object *ubusd_create_object(struct ubus_client *cl, struct blob_attr **attr);