diff --git a/main/event.c b/main/event.c index c497bd1f7219cb52219c972bfa1c8740d3c6213b..bc814720d75d5038a69f4578d30efd31cd48ce11 100644 --- a/main/event.c +++ b/main/event.c @@ -339,60 +339,95 @@ enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type typ ie_type = va_arg(ap, enum ast_event_type)) { struct ast_event_ie_val *ie_value = alloca(sizeof(*ie_value)); + int insert = 1; memset(ie_value, 0, sizeof(*ie_value)); ie_value->ie_type = ie_type; ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype); - if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_UINT) + switch (ie_value->ie_pltype) { + case AST_EVENT_IE_PLTYPE_UINT: ie_value->payload.uint = va_arg(ap, uint32_t); - else if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_STR) - ie_value->payload.str = ast_strdupa(va_arg(ap, const char *)); - else if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) { + break; + case AST_EVENT_IE_PLTYPE_STR: + ie_value->payload.str = va_arg(ap, const char *); + break; + case AST_EVENT_IE_PLTYPE_RAW: + { void *data = va_arg(ap, void *); size_t datalen = va_arg(ap, size_t); ie_value->payload.raw = alloca(datalen); memcpy(ie_value->payload.raw, data, datalen); ie_value->raw_datalen = datalen; + break; + } + case AST_EVENT_IE_PLTYPE_UNKNOWN: + insert = 0; + case AST_EVENT_IE_PLTYPE_EXISTS: + break; + } + + if (insert) { + AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry); } - AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry); } 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) { + int break_out = 0; + AST_LIST_TRAVERSE(&sub->ie_vals, sub_ie_val, entry) { - if (sub_ie_val->ie_type == ie_val->ie_type) + if (sub_ie_val->ie_type == ie_val->ie_type) { break; + } } + if (!sub_ie_val) { - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) - break; + /* This subscriber doesn't care about this IE, so consider + * it matched. */ 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) + + switch (ie_val->ie_pltype) { + case AST_EVENT_IE_PLTYPE_UINT: + break_out = (ie_val->payload.uint != sub_ie_val->payload.uint); + break; + case AST_EVENT_IE_PLTYPE_STR: + break_out = strcmp(ie_val->payload.str, sub_ie_val->payload.str); + break; + case AST_EVENT_IE_PLTYPE_RAW: + break_out = memcmp(ie_val->payload.raw, + sub_ie_val->payload.raw, ie_val->raw_datalen); break; - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR && - strcmp(ie_val->payload.str, sub_ie_val->payload.str)) + case AST_EVENT_IE_PLTYPE_EXISTS: + /* The subscriber doesn't actually care what the value is */ + break_out = 1; 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)) + case AST_EVENT_IE_PLTYPE_UNKNOWN: break; + } + + if (break_out) { + break; + } } - if (!ie_val) + + if (!ie_val) { + /* Everything matched */ break; + } } AST_RWDLLIST_UNLOCK(&ast_event_subs[type]); - if (sub) /* All parameters were matched */ + 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])) + 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; @@ -529,13 +564,15 @@ void ast_event_report_subs(const struct ast_event_sub *event_sub) AST_RWDLLIST_RDLOCK(&ast_event_subs[event_type]); AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_type], sub, entry) { - if (event_sub == sub) + if (event_sub == sub) { continue; + } event = gen_sub_event(sub); - if (!event) + if (!event) { continue; + } event_sub->cb(event, event_sub->userdata); @@ -544,7 +581,7 @@ void ast_event_report_subs(const struct ast_event_sub *event_sub) AST_RWDLLIST_UNLOCK(&ast_event_subs[event_type]); } -struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type, +struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type, ast_event_cb_t cb, void *userdata) { struct ast_event_sub *sub; @@ -554,8 +591,9 @@ struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type, return NULL; } - if (!(sub = ast_calloc(1, sizeof(*sub)))) + if (!(sub = ast_calloc(1, sizeof(*sub)))) { return NULL; + } sub->type = type; sub->cb = cb; @@ -570,11 +608,13 @@ int ast_event_sub_append_ie_uint(struct ast_event_sub *sub, { struct ast_event_ie_val *ie_val; - if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) + if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) { return -1; + } - if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) + if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) { return -1; + } ie_val->ie_type = ie_type; ie_val->payload.uint = unsigned_int; @@ -590,11 +630,13 @@ int ast_event_sub_append_ie_exists(struct ast_event_sub *sub, { struct ast_event_ie_val *ie_val; - if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) + if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) { return -1; + } - if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) + if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) { return -1; + } ie_val->ie_type = ie_type; ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_EXISTS; @@ -604,16 +646,18 @@ int ast_event_sub_append_ie_exists(struct ast_event_sub *sub, return 0; } -int ast_event_sub_append_ie_str(struct ast_event_sub *sub, +int ast_event_sub_append_ie_str(struct ast_event_sub *sub, enum ast_event_ie_type ie_type, const char *str) { struct ast_event_ie_val *ie_val; - if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) + if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) { return -1; + } - if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) + if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) { return -1; + } ie_val->ie_type = ie_type; ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_STR; @@ -630,16 +674,18 @@ int ast_event_sub_append_ie_str(struct ast_event_sub *sub, return 0; } -int ast_event_sub_append_ie_raw(struct ast_event_sub *sub, +int ast_event_sub_append_ie_raw(struct ast_event_sub *sub, enum ast_event_ie_type ie_type, void *data, size_t raw_datalen) { struct ast_event_ie_val *ie_val; - if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) + if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) { return -1; + } - if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) + if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) { return -1; + } ie_val->ie_type = ie_type; ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_RAW; @@ -666,8 +712,9 @@ int ast_event_sub_activate(struct ast_event_sub *sub) event = gen_sub_event(sub); - if (event) + if (event) { ast_event_queue(event); + } } AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]); @@ -677,15 +724,16 @@ int ast_event_sub_activate(struct ast_event_sub *sub) return 0; } -struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb, +struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb, void *userdata, ...) { va_list ap; enum ast_event_ie_type ie_type; struct ast_event_sub *sub; - if (!(sub = ast_event_subscribe_new(type, cb, userdata))) + if (!(sub = ast_event_subscribe_new(type, cb, userdata))) { return NULL; + } va_start(ap, userdata); for (ie_type = va_arg(ap, enum ast_event_type); @@ -734,8 +782,9 @@ void ast_event_sub_destroy(struct ast_event_sub *sub) { struct ast_event_ie_val *ie_val; - while ((ie_val = AST_LIST_REMOVE_HEAD(&sub->ie_vals, entry))) + while ((ie_val = AST_LIST_REMOVE_HEAD(&sub->ie_vals, entry))) { ast_event_ie_val_destroy(ie_val); + } ast_free(sub); } @@ -751,14 +800,15 @@ struct ast_event_sub *ast_event_unsubscribe(struct ast_event_sub *sub) if (ast_event_check_subscriber(AST_EVENT_UNSUB, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type, AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) { - + event = ast_event_new(AST_EVENT_UNSUB, AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, sub->uniqueid, AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type, AST_EVENT_IE_END); - if (event) + if (event) { ast_event_queue(event); + } } ast_event_sub_destroy(sub); @@ -771,7 +821,6 @@ void ast_event_iterator_init(struct ast_event_iterator *iterator, const struct a iterator->event_len = ntohs(event->event_len); iterator->event = event; iterator->ie = (struct ast_event_ie *) ( ((char *) event) + sizeof(*event) ); - return; } int ast_event_iterator_next(struct ast_event_iterator *iterator) @@ -842,8 +891,9 @@ const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_i int res = 0; for (ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) { - if (ast_event_iterator_get_ie_type(&iterator) == ie_type) + if (ast_event_iterator_get_ie_type(&iterator) == ie_type) { return ast_event_iterator_get_ie_raw(&iterator); + } } return NULL; @@ -881,8 +931,9 @@ int ast_event_append_ie_raw(struct ast_event **event, enum ast_event_ie_type ie_ event_len = ntohs((*event)->event_len); extra_len = sizeof(*ie) + data_len; - if (!(*event = ast_realloc(*event, event_len + extra_len))) + if (!(*event = ast_realloc(*event, event_len + extra_len))) { return -1; + } ie = (struct ast_event_ie *) ( ((char *) *event) + event_len ); ie->ie_type = htons(ie_type); @@ -915,40 +966,70 @@ struct ast_event *ast_event_new(enum ast_event_type type, ...) ie_type = va_arg(ap, enum ast_event_type)) { struct ast_event_ie_val *ie_value = alloca(sizeof(*ie_value)); + int insert = 1; memset(ie_value, 0, sizeof(*ie_value)); ie_value->ie_type = ie_type; ie_value->ie_pltype = va_arg(ap, enum ast_event_ie_pltype); - if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_UINT) + switch (ie_value->ie_pltype) { + case AST_EVENT_IE_PLTYPE_UINT: ie_value->payload.uint = va_arg(ap, uint32_t); - else if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_STR) - ie_value->payload.str = ast_strdupa(va_arg(ap, const char *)); - else if (ie_value->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) { + break; + case AST_EVENT_IE_PLTYPE_STR: + ie_value->payload.str = va_arg(ap, const char *); + break; + case AST_EVENT_IE_PLTYPE_RAW: + { void *data = va_arg(ap, void *); size_t datalen = va_arg(ap, size_t); ie_value->payload.raw = alloca(datalen); memcpy(ie_value->payload.raw, data, datalen); ie_value->raw_datalen = datalen; + break; + } + case AST_EVENT_IE_PLTYPE_UNKNOWN: + insert = 0; + break; + case AST_EVENT_IE_PLTYPE_EXISTS: + break; + } + + if (insert) { + AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry); } - AST_LIST_INSERT_TAIL(&ie_vals, ie_value, entry); } va_end(ap); - if (!(event = ast_calloc(1, sizeof(*event)))) + if (!(event = ast_calloc(1, sizeof(*event)))) { return NULL; + } event->type = htons(type); event->event_len = htons(sizeof(*event)); AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) { - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR) + switch (ie_val->ie_pltype) { + case AST_EVENT_IE_PLTYPE_STR: ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str); - else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT) + break; + case AST_EVENT_IE_PLTYPE_UINT: ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint); - else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) - ast_event_append_ie_raw(&event, ie_val->ie_type, ie_val->payload.raw, ie_val->raw_datalen); + break; + case AST_EVENT_IE_PLTYPE_RAW: + ast_event_append_ie_raw(&event, ie_val->ie_type, + ie_val->payload.raw, ie_val->raw_datalen); + break; + case AST_EVENT_IE_PLTYPE_EXISTS: + ast_log(LOG_WARNING, "PLTYPE_EXISTS unsupported in event_new\n"); + break; + case AST_EVENT_IE_PLTYPE_UNKNOWN: + ast_log(LOG_WARNING, "PLTYPE_UNKNOWN passed as an IE type " + "for a new event\n"); + break; + } - if (!event) + if (!event) { break; + } } if (!ast_event_get_ie_raw(event, AST_EVENT_IE_EID)) {