diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-22 21:58:06 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-04-22 21:58:06 +0000 |
commit | f0c8afa9aea9761fe34d6370080a17727497fd21 (patch) | |
tree | b9e53b32da7ffbedd077b170cab30ed6c46a6c7a /main | |
parent | b17e278b84fefd9952acec255843fa6ed75233fd (diff) |
Merged revisions 258632 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
For 1.6.2, only merge the bug fixes, not the unit test.
........
r258632 | russell | 2010-04-22 16:06:53 -0500 (Thu, 22 Apr 2010) | 22 lines
Add ast_event subscription unit test and fix some ast_event API bugs.
This patch introduces another test in test_event.c that exercises most of the
subscription related ast_event API calls. I made some minor additions to the
existing event allocation test to increase API coverage by the test code.
Finally, I made a list in a comment of API calls not yet touched by the test
module as a to-do list for future test development.
During the development of this test code, I discovered a number of bugs in
the event API.
1) subscriptions to AST_EVENT_ALL were not handled appropriately in a couple
of different places. The API allows a subscription to all event types,
but with IE parameters, just as if it was a subscription to a specific
event type. However, the parameters were being ignored. This affected
ast_event_check_subscriber() and event distribution to subscribers.
2) Some of the logic in ast_event_check_subscriber() for checking subscriptions
against query parameters was wrong.
Review: https://reviewboard.asterisk.org/r/617/
........
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@258672 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main')
-rw-r--r-- | main/event.c | 149 |
1 files changed, 94 insertions, 55 deletions
diff --git a/main/event.c b/main/event.c index dd3cff1f7..60dde3bb2 100644 --- a/main/event.c +++ b/main/event.c @@ -319,14 +319,62 @@ static void ast_event_ie_val_destroy(struct ast_event_ie_val *ie_val) ast_free(ie_val); } +/*! + * \internal + * \brief Check if an ie_val matches a subscription + * + * \param sub subscription to check against + * \param ie_val IE value to check + * + * \retval 0 not matched + * \retval non-zero matched + */ +static int match_ie_val_to_sub(const struct ast_event_sub *sub, const struct ast_event_ie_val *ie_val) +{ + const struct ast_event_ie_val *sub_ie_val; + int res = 1; + + AST_LIST_TRAVERSE(&sub->ie_vals, sub_ie_val, entry) { + if (sub_ie_val->ie_type == ie_val->ie_type) { + break; + } + } + + if (!sub_ie_val) { + /* This subscriber doesn't care about this IE, so consider + * it matched. */ + return 1; + } + + switch (ie_val->ie_pltype) { + case AST_EVENT_IE_PLTYPE_UINT: + res = (ie_val->payload.uint != sub_ie_val->payload.uint); + break; + case AST_EVENT_IE_PLTYPE_STR: + res = strcmp(ie_val->payload.str, sub_ie_val->payload.str); + break; + case AST_EVENT_IE_PLTYPE_RAW: + res = memcmp(ie_val->payload.raw, + sub_ie_val->payload.raw, ie_val->raw_datalen); + break; + case AST_EVENT_IE_PLTYPE_EXISTS: + case AST_EVENT_IE_PLTYPE_UNKNOWN: + break; + } + + return res; +} + enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type type, ...) { va_list ap; enum ast_event_ie_type ie_type; enum ast_event_subscriber_res res = AST_EVENT_SUB_NONE; - struct ast_event_ie_val *ie_val, *sub_ie_val; + struct ast_event_ie_val *ie_val; struct ast_event_sub *sub; AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val); + const enum ast_event_type event_types[] = { type, AST_EVENT_ALL }; + int i; if (type >= AST_EVENT_TOTAL) { ast_log(LOG_ERROR, "%u is an invalid type!\n", type); @@ -357,47 +405,42 @@ enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type typ } va_end(ap); - AST_RWDLLIST_RDLOCK(&ast_event_subs[type]); - AST_RWDLLIST_TRAVERSE(&ast_event_subs[type], sub, entry) { - AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) { - AST_LIST_TRAVERSE(&sub->ie_vals, sub_ie_val, entry) { - if (sub_ie_val->ie_type == ie_val->ie_type) + for (i = 0; i < ARRAY_LEN(event_types); i++) { + AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]); + AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) { + AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) { + if (match_ie_val_to_sub(sub, ie_val)) { break; + } } - if (!sub_ie_val) { - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) - break; - continue; - } - /* The subscriber doesn't actually care what the value is */ - if (sub_ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) - continue; - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT && - ie_val->payload.uint != sub_ie_val->payload.uint) - break; - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR && - strcmp(ie_val->payload.str, sub_ie_val->payload.str)) - break; - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW && - memcmp(ie_val->payload.raw, sub_ie_val->payload.raw, ie_val->raw_datalen)) + + if (!ie_val) { + /* Everything matched. */ break; + } } - if (!ie_val) + AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]); + if (sub) { break; + } } - AST_RWDLLIST_UNLOCK(&ast_event_subs[type]); - - if (sub) /* All parameters were matched */ - return AST_EVENT_SUB_EXISTS; - AST_RWDLLIST_RDLOCK(&ast_event_subs[AST_EVENT_ALL]); - if (!AST_DLLIST_EMPTY(&ast_event_subs[AST_EVENT_ALL])) - res = AST_EVENT_SUB_EXISTS; - AST_RWDLLIST_UNLOCK(&ast_event_subs[AST_EVENT_ALL]); - - return res; + return sub ? AST_EVENT_SUB_EXISTS : AST_EVENT_SUB_NONE; } +/*! + * \internal + * \brief Check if an ie_val matches an event + * + * \param event event to check against + * \param ie_val IE value to check + * \param event2 optional event, if specified, the value to compare against will be pulled + * from this event instead of from the ie_val structure. In this case, only the IE + * type and payload type will be pulled from ie_val. + * + * \retval 0 not matched + * \retval non-zero matched + */ static int match_ie_val(const struct ast_event *event, const struct ast_event_ie_val *ie_val, const struct ast_event *event2) { @@ -1118,32 +1161,28 @@ static int handle_event(void *data) { struct ast_event_ref *event_ref = data; struct ast_event_sub *sub; - uint16_t host_event_type; - - host_event_type = ntohs(event_ref->event->type); + const enum ast_event_type event_types[] = { + ntohs(event_ref->event->type), + AST_EVENT_ALL + }; + int i; - /* Subscribers to this specific event first */ - AST_RWDLLIST_RDLOCK(&ast_event_subs[host_event_type]); - AST_RWDLLIST_TRAVERSE(&ast_event_subs[host_event_type], sub, entry) { - struct ast_event_ie_val *ie_val; - AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) { - if (!match_ie_val(event_ref->event, ie_val, NULL)) { - break; + for (i = 0; i < ARRAY_LEN(event_types); i++) { + AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]); + AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) { + struct ast_event_ie_val *ie_val; + AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) { + if (!match_ie_val(event_ref->event, ie_val, NULL)) { + break; + } } + if (ie_val) { + continue; + } + sub->cb(event_ref->event, sub->userdata); } - if (ie_val) { - continue; - } - sub->cb(event_ref->event, sub->userdata); - } - AST_RWDLLIST_UNLOCK(&ast_event_subs[host_event_type]); - - /* Now to subscribers to all event types */ - AST_RWDLLIST_RDLOCK(&ast_event_subs[AST_EVENT_ALL]); - AST_RWDLLIST_TRAVERSE(&ast_event_subs[AST_EVENT_ALL], sub, entry) { - sub->cb(event_ref->event, sub->userdata); + AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]); } - AST_RWDLLIST_UNLOCK(&ast_event_subs[AST_EVENT_ALL]); ao2_ref(event_ref, -1); |