From 73743b77b0644be36f8712d0a94289de0263aaf8 Mon Sep 17 00:00:00 2001 From: "Kevin P. Fleming" Date: Sun, 3 May 2009 14:28:59 +0000 Subject: [PATCH] Add 'bitflags'-style information elements to event framework This patch add a new payload type for information elements, a set of bit flags. The payload is transported as a 32-bit unsigned integer but when matching is performed between events and subscribers, the matching is done by using a bitwise AND instead of numeric value comparison. Review: http://reviewboard.asterisk.org/r/242/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@191919 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- include/asterisk/event.h | 55 ++++++++++++++++- include/asterisk/event_defs.h | 2 + main/event.c | 108 ++++++++++++++++++++++++++++++---- 3 files changed, 152 insertions(+), 13 deletions(-) diff --git a/include/asterisk/event.h b/include/asterisk/event.h index ac42e59427..b9de22dd26 100644 --- a/include/asterisk/event.h +++ b/include/asterisk/event.h @@ -156,6 +156,20 @@ void ast_event_sub_destroy(struct ast_event_sub *sub); int ast_event_sub_append_ie_uint(struct ast_event_sub *sub, enum ast_event_ie_type ie_type, uint32_t uint); +/*! + * \brief Append a bitflags parameter to a subscription + * + * \param sub the dynamic subscription allocated with ast_event_subscribe_new() + * \param ie_type the information element type for the parameter + * \param flags the flags that must be present in the event to match this subscription + * + * \retval 0 success + * \retval non-zero failure + * \since 1.6.3 + */ +int ast_event_sub_append_ie_bitflags(struct ast_event_sub *sub, + enum ast_event_ie_type ie_type, uint32_t flags); + /*! * \brief Append a string parameter to a subscription * @@ -445,6 +459,24 @@ int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_ int ast_event_append_ie_uint(struct ast_event **event, enum ast_event_ie_type ie_type, uint32_t data); +/*! + * \brief Append an information element that has a bitflags payload + * + * \param event the event that the IE will be appended to + * \param ie_type the type of IE to append + * \param flags the flags that are the payload of the IE + * + * \retval 0 success + * \retval -1 failure + * \since 1.6.3 + * + * The pointer to the event will get updated with the new location for the event + * that now contains the appended information element. If the re-allocation of + * the memory for this event fails, it will be set to NULL. + */ +int ast_event_append_ie_bitflags(struct ast_event **event, enum ast_event_ie_type ie_type, + uint32_t bitflags); + /*! * \brief Append an information element that has a raw payload * @@ -475,6 +507,18 @@ int ast_event_append_ie_raw(struct ast_event **event, enum ast_event_ie_type ie_ */ uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type); +/*! + * \brief Get the value of an information element that has a bitflags payload + * + * \param event The event to get the IE from + * \param ie_type the type of information element to retrieve + * + * \return This returns the payload of the information element with the given type. + * However, an IE with a payload of 0, and the case where no IE is found + * yield the same return value. + */ +uint32_t ast_event_get_ie_bitflags(const struct ast_event *event, enum ast_event_ie_type ie_type); + /*! * \brief Get the value of an information element that has a string payload * @@ -614,7 +658,7 @@ int ast_event_iterator_next(struct ast_event_iterator *iterator); enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator *iterator); /*! - * \brief Get the value of the current IE in the ierator as an integer payload + * \brief Get the value of the current IE in the iterator as an integer payload * * \param iterator The iterator instance * @@ -622,6 +666,15 @@ enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator */ uint32_t ast_event_iterator_get_ie_uint(struct ast_event_iterator *iterator); +/*! + * \brief Get the value of the current IE in the iterator as a bitflags payload + * + * \param iterator The iterator instance + * + * \return This returns the payload of the information element as bitflags. + */ +uint32_t ast_event_iterator_get_ie_bitflags(struct ast_event_iterator *iterator); + /*! * \brief Get the value of the current IE in the iterator as a string payload * diff --git a/include/asterisk/event_defs.h b/include/asterisk/event_defs.h index 3f1e3bd157..9bebfb69d2 100644 --- a/include/asterisk/event_defs.h +++ b/include/asterisk/event_defs.h @@ -137,6 +137,8 @@ enum ast_event_ie_pltype { AST_EVENT_IE_PLTYPE_STR, /*! Raw data, compared with memcmp */ AST_EVENT_IE_PLTYPE_RAW, + /*! Bit flags (unsigned integer, compared using boolean logic) */ + AST_EVENT_IE_PLTYPE_BITFLAGS, }; /*! diff --git a/main/event.c b/main/event.c index bc814720d7..483d478324 100644 --- a/main/event.c +++ b/main/event.c @@ -311,6 +311,7 @@ static void ast_event_ie_val_destroy(struct ast_event_ie_val *ie_val) ast_free(ie_val->payload.raw); break; case AST_EVENT_IE_PLTYPE_UINT: + case AST_EVENT_IE_PLTYPE_BITFLAGS: case AST_EVENT_IE_PLTYPE_EXISTS: case AST_EVENT_IE_PLTYPE_UNKNOWN: break; @@ -347,6 +348,9 @@ enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type typ case AST_EVENT_IE_PLTYPE_UINT: ie_value->payload.uint = va_arg(ap, uint32_t); break; + case AST_EVENT_IE_PLTYPE_BITFLAGS: + ie_value->payload.uint = va_arg(ap, uint32_t); + break; case AST_EVENT_IE_PLTYPE_STR: ie_value->payload.str = va_arg(ap, const char *); break; @@ -392,6 +396,12 @@ enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type typ case AST_EVENT_IE_PLTYPE_UINT: break_out = (ie_val->payload.uint != sub_ie_val->payload.uint); break; + case AST_EVENT_IE_PLTYPE_BITFLAGS: + /* if the subscriber has requested *any* of the bitflags we are providing, + * then it's a match + */ + 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; @@ -436,14 +446,26 @@ enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type typ static int match_ie_val(const struct ast_event *event, const struct ast_event_ie_val *ie_val, const struct ast_event *event2) { - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT) { + switch (ie_val->ie_pltype) { + case AST_EVENT_IE_PLTYPE_UINT: + { uint32_t val = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint; - if (val == ast_event_get_ie_uint(event, ie_val->ie_type)) - return 1; - return 0; + + return (val == ast_event_get_ie_uint(event, ie_val->ie_type)) ? 1 : 0; } - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR) { + case AST_EVENT_IE_PLTYPE_BITFLAGS: + { + uint32_t flags = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint; + + /* if the subscriber has requested *any* of the bitflags that this event provides, + * then it's a match + */ + return (flags & ast_event_get_ie_bitflags(event, ie_val->ie_type)) ? 1 : 0; + } + + case AST_EVENT_IE_PLTYPE_STR: + { const char *str; uint32_t hash; @@ -460,16 +482,19 @@ static int match_ie_val(const struct ast_event *event, return 0; } - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) { + case AST_EVENT_IE_PLTYPE_RAW: + { const void *buf = event2 ? ast_event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw; - if (buf && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_val->raw_datalen)) - return 1; - return 0; + + return (buf && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_val->raw_datalen)) ? 1 : 0; } - if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) { - if (ast_event_get_ie_raw(event, ie_val->ie_type)) - return 1; + case AST_EVENT_IE_PLTYPE_EXISTS: + { + return ast_event_get_ie_raw(event, ie_val->ie_type) ? 1 : 0; + } + + case AST_EVENT_IE_PLTYPE_UNKNOWN: return 0; } @@ -527,6 +552,9 @@ static struct ast_event *gen_sub_event(struct ast_event_sub *sub) case AST_EVENT_IE_PLTYPE_UINT: ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint); break; + case AST_EVENT_IE_PLTYPE_BITFLAGS: + ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint); + break; case AST_EVENT_IE_PLTYPE_STR: ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str); break; @@ -625,6 +653,26 @@ int ast_event_sub_append_ie_uint(struct ast_event_sub *sub, return 0; } +int ast_event_sub_append_ie_bitflags(struct ast_event_sub *sub, + enum ast_event_ie_type ie_type, uint32_t flags) +{ + struct ast_event_ie_val *ie_val; + + if (ie_type < 0 || ie_type > AST_EVENT_IE_MAX) + return -1; + + if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) + return -1; + + ie_val->ie_type = ie_type; + ie_val->payload.uint = flags; + ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_BITFLAGS; + + AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry); + + return 0; +} + int ast_event_sub_append_ie_exists(struct ast_event_sub *sub, enum ast_event_ie_type ie_type) { @@ -753,6 +801,12 @@ struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb ast_event_sub_append_ie_uint(sub, ie_type, unsigned_int); break; } + case AST_EVENT_IE_PLTYPE_BITFLAGS: + { + uint32_t unsigned_int = va_arg(ap, uint32_t); + ast_event_sub_append_ie_bitflags(sub, ie_type, unsigned_int); + break; + } case AST_EVENT_IE_PLTYPE_STR: { const char *str = va_arg(ap, const char *); @@ -839,6 +893,11 @@ uint32_t ast_event_iterator_get_ie_uint(struct ast_event_iterator *iterator) return ntohl(get_unaligned_uint32(iterator->ie->ie_payload)); } +uint32_t ast_event_iterator_get_ie_bitflags(struct ast_event_iterator *iterator) +{ + return ntohl(get_unaligned_uint32(iterator->ie->ie_payload)); +} + const char *ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator) { const struct ast_event_ie_str_payload *str_payload; @@ -867,6 +926,15 @@ uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_ return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0; } +uint32_t ast_event_get_ie_bitflags(const struct ast_event *event, enum ast_event_ie_type ie_type) +{ + const uint32_t *ie_val; + + ie_val = ast_event_get_ie_raw(event, ie_type); + + return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0; +} + uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type) { const struct ast_event_ie_str_payload *str_payload; @@ -921,6 +989,13 @@ int ast_event_append_ie_uint(struct ast_event **event, enum ast_event_ie_type ie return ast_event_append_ie_raw(event, ie_type, &data, sizeof(data)); } +int ast_event_append_ie_bitflags(struct ast_event **event, enum ast_event_ie_type ie_type, + uint32_t flags) +{ + flags = htonl(flags); + return ast_event_append_ie_raw(event, ie_type, &flags, sizeof(flags)); +} + int ast_event_append_ie_raw(struct ast_event **event, enum ast_event_ie_type ie_type, const void *data, size_t data_len) { @@ -974,6 +1049,9 @@ struct ast_event *ast_event_new(enum ast_event_type type, ...) case AST_EVENT_IE_PLTYPE_UINT: ie_value->payload.uint = va_arg(ap, uint32_t); break; + case AST_EVENT_IE_PLTYPE_BITFLAGS: + ie_value->payload.uint = va_arg(ap, uint32_t); + break; case AST_EVENT_IE_PLTYPE_STR: ie_value->payload.str = va_arg(ap, const char *); break; @@ -1014,6 +1092,9 @@ struct ast_event *ast_event_new(enum ast_event_type type, ...) case AST_EVENT_IE_PLTYPE_UINT: ast_event_append_ie_uint(&event, ie_val->ie_type, ie_val->payload.uint); break; + case AST_EVENT_IE_PLTYPE_BITFLAGS: + ast_event_append_ie_bitflags(&event, ie_val->ie_type, ie_val->payload.uint); + 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); @@ -1108,6 +1189,9 @@ struct ast_event *ast_event_get_cached(enum ast_event_type type, ...) case AST_EVENT_IE_PLTYPE_UINT: ast_event_append_ie_uint(&cache_arg_event, ie_type, va_arg(ap, uint32_t)); break; + case AST_EVENT_IE_PLTYPE_BITFLAGS: + ast_event_append_ie_bitflags(&cache_arg_event, ie_type, va_arg(ap, uint32_t)); + break; case AST_EVENT_IE_PLTYPE_STR: ast_event_append_ie_str(&cache_arg_event, ie_type, va_arg(ap, const char *)); break;