/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2007, Digium, Inc.
+ * Copyright (C) 2007 - 2008, Digium, Inc.
*
* Russell Bryant <russell@digium.com>
*
struct ast_event_sub *ast_event_subscribe(enum ast_event_type event_type,
ast_event_cb_t cb, void *userdata, ...);
+/*!
+ * \brief Allocate a subscription, but do not activate it
+ *
+ * \arg type the event type to subscribe to
+ * \arg cb the function to call when an event matches this subscription
+ * \arg userdata data to pass to the provided callback
+ *
+ * This function should be used when you want to dynamically build a
+ * subscription.
+ *
+ * \return the allocated subscription, or NULL on failure
+ */
+struct ast_event_sub *ast_event_subscribe_new(enum ast_event_type type,
+ ast_event_cb_t cb, void *userdata);
+
+/*!
+ * \brief Destroy an allocated subscription
+ *
+ * \arg sub the subscription to destroy
+ *
+ * This function should be used when a subscription is allocated with
+ * ast_event_subscribe_new(), but for some reason, you want to destroy it
+ * instead of activating it. This could be because of an error when
+ * reading in the configuration for the dynamically built subscription.
+ */
+void ast_event_sub_destroy(struct ast_event_sub *sub);
+
+/*!
+ * \brief Append a uint parameter to a subscription
+ *
+ * \arg sub the dynamic subscription allocated with ast_event_subscribe_new()
+ * \arg ie_type the information element type for the parameter
+ * \arg uint the value that must be present in the event to match this subscription
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+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 string parameter to a subscription
+ *
+ * \arg sub the dynamic subscription allocated with ast_event_subscribe_new()
+ * \arg ie_type the information element type for the parameter
+ * \arg str the string that must be present in the event to match this subscription
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+int ast_event_sub_append_ie_str(struct ast_event_sub *sub,
+ enum ast_event_ie_type ie_type, const char *str);
+
+/*!
+ * \brief Append a raw parameter to a subscription
+ *
+ * \arg sub the dynamic subscription allocated with ast_event_subscribe_new()
+ * \arg ie_type the information element type for the parameter
+ * \arg raw the data that must be present in the event to match this subscription
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+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);
+
+/*!
+ * \brief Append an 'exists' parameter to a subscription
+ *
+ * \arg sub the dynamic subscription allocated with ast_event_subscribe_new()
+ * \arg ie_type the information element type that must be present in the event
+ * for it to match this subscription.
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+int ast_event_sub_append_ie_exists(struct ast_event_sub *sub,
+ enum ast_event_ie_type ie_type);
+
+/*!
+ * \brief Activate a dynamically built subscription
+ *
+ * \arg sub the subscription to activate that was allocated using
+ * ast_event_subscribe_new()
+ *
+ * Once a dynamically built subscription has had all of the parameters added
+ * to it, it should be activated using this function.
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+int ast_event_sub_activate(struct ast_event_sub *sub);
+
/*!
* \brief Un-subscribe from events
*
* \param event_sub This is the reference to the subscription returned by
* ast_event_subscribe.
- *
- * \return Nothing
+ *
+ * This function will remove a subscription and free the associated data
+ * structures.
+ *
+ * \return NULL for convenience.
*/
-void ast_event_unsubscribe(struct ast_event_sub *event_sub);
+struct ast_event_sub *ast_event_unsubscribe(struct ast_event_sub *event_sub);
/*!
* \brief Check if subscribers exist
*/
void ast_event_report_subs(const struct ast_event_sub *sub);
+/*! \brief Dump the event cache for the subscriber */
+void ast_event_dump_cache(const struct ast_event_sub *event_sub);
+
/*!
* \brief Create a new event
*
*/
const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type);
+/*!
+ * \brief Get the string representation of an information element type
+ *
+ * \arg ie_type the information element type to get the string representation of
+ *
+ * \return the string representation of the information element type
+ */
+const char *ast_event_get_ie_type_name(enum ast_event_ie_type ie_type);
+
+/*!
+ * \brief Get the payload type for a given information element type
+ *
+ * \arg ie_type the information element type to get the payload type of
+ *
+ * \return the payload type for the provided IE type
+ */
+enum ast_event_ie_pltype ast_event_get_ie_pltype(enum ast_event_ie_type ie_type);
+
/*!
* \brief Get the type for an event
*
*/
enum ast_event_type ast_event_get_type(const struct ast_event *event);
+/*!
+ * \brief Get the string representation of the type of the given event
+ *
+ * \arg event the event to get the type of
+ *
+ * \return the string representation of the event type of the provided event
+ */
+const char *ast_event_get_type_name(const struct ast_event *event);
+
+/*!
+ * \brief Convert a string into an event type
+ *
+ * \arg str the string to convert
+ * \arg event_type an output parameter for the event type
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+int ast_event_str_to_event_type(const char *str, enum ast_event_type *event_type);
+
+/*!
+ * \brief Convert a string to an IE type
+ *
+ * \arg str the string to convert
+ * \arg ie_type an output parameter for the IE type
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+int ast_event_str_to_ie_type(const char *str, enum ast_event_ie_type *ie_type);
+
+/*!
+ * \brief Get the size of an event
+ *
+ * \param event the event to get the size of
+ *
+ * \return the number of bytes contained in the event
+ */
+size_t ast_event_get_size(const struct ast_event *event);
+
/*!
* \brief Initialize an event iterator instance
*
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2007, Digium, Inc.
+ * Copyright (C) 2007 - 2008, Digium, Inc.
*
* Russell Bryant <russell@digium.com>
*
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/unaligned.h"
+#include "asterisk/utils.h"
#include "asterisk/taskprocessor.h"
struct ast_taskprocessor *event_dispatcher;
AST_LIST_ENTRY(ast_event_ref) entry;
};
-struct ast_event_iterator {
- uint16_t event_len;
- const struct ast_event *event;
- struct ast_event_ie *ie;
-};
-
struct ast_event_ie_val {
AST_LIST_ENTRY(ast_event_ie_val) entry;
enum ast_event_ie_type ie_type;
union {
uint32_t uint;
const char *str;
+ void *raw;
} payload;
+ size_t raw_datalen;
};
/*! \brief Event subscription */
* needs to know this state, it can get the last known state from the cache. */
static AST_RWLIST_HEAD(ast_event_ref_list, ast_event_ref) ast_event_cache[AST_EVENT_TOTAL];
+/*!
+ * The index of each entry _must_ match the event type number!
+ */
+static struct event_name {
+ enum ast_event_type type;
+ const char *name;
+} event_names[] = {
+ { 0, "" },
+ { AST_EVENT_CUSTOM, "Custom" },
+ { AST_EVENT_MWI, "MWI" },
+ { AST_EVENT_SUB, "Subscription" },
+ { AST_EVENT_UNSUB, "Unsubscription" },
+ { AST_EVENT_DEVICE_STATE, "DeviceState" },
+ { AST_EVENT_DEVICE_STATE_CHANGE, "DeviceStateChange" },
+};
+
+/*!
+ * The index of each entry _must_ match the event ie number!
+ */
+static struct ie_map {
+ enum ast_event_ie_type ie_type;
+ enum ast_event_ie_pltype ie_pltype;
+ const char *name;
+} ie_maps[] = {
+ { 0, 0, "" },
+ { AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, "NewMessages" },
+ { AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, "OldMessages" },
+ { AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, "Mailbox" },
+ { AST_EVENT_IE_UNIQUEID, AST_EVENT_IE_PLTYPE_UINT, "UniqueID" },
+ { AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, "EventType" },
+ { AST_EVENT_IE_EXISTS, AST_EVENT_IE_PLTYPE_UINT, "Exists" },
+ { AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, "Device" },
+ { AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, "State" },
+ { AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, "Context" },
+ { AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, "EntityID" },
+};
+
+const char *ast_event_get_type_name(const struct ast_event *event)
+{
+ enum ast_event_type type;
+
+ type = ast_event_get_type(event);
+
+ if (type >= AST_EVENT_TOTAL || type < 0) {
+ ast_log(LOG_ERROR, "Invalid event type - '%d'\n", type);
+ return "";
+ }
+
+ return event_names[type].name;
+}
+
+int ast_event_str_to_event_type(const char *str, enum ast_event_type *event_type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_LEN(event_names); i++) {
+ if (strcasecmp(event_names[i].name, str))
+ continue;
+
+ *event_type = event_names[i].type;
+ return 0;
+ }
+
+ return -1;
+}
+
+const char *ast_event_get_ie_type_name(enum ast_event_ie_type ie_type)
+{
+ if (ie_type <= 0 || ie_type > AST_EVENT_IE_MAX) {
+ ast_log(LOG_ERROR, "Invalid IE type - '%d'\n", ie_type);
+ return "";
+ }
+
+ return ie_maps[ie_type].name;
+}
+
+enum ast_event_ie_pltype ast_event_get_ie_pltype(enum ast_event_ie_type ie_type)
+{
+ if (ie_type <= 0 || ie_type > AST_EVENT_IE_MAX) {
+ ast_log(LOG_ERROR, "Invalid IE type - '%d'\n", ie_type);
+ return AST_EVENT_IE_PLTYPE_UNKNOWN;
+ }
+
+ return ie_maps[ie_type].ie_pltype;
+}
+
+int ast_event_str_to_ie_type(const char *str, enum ast_event_ie_type *ie_type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_LEN(ie_maps); i++) {
+ if (strcasecmp(ie_maps[i].name, str))
+ continue;
+
+ *ie_type = ie_maps[i].ie_type;
+ return 0;
+ }
+
+ return -1;
+}
+
+size_t ast_event_get_size(const struct ast_event *event)
+{
+ size_t res;
+
+ res = ntohs(event->event_len);
+
+ return res;
+}
+
static void ast_event_ie_val_destroy(struct ast_event_ie_val *ie_val)
{
- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
- ast_free((void *) ie_val->payload.str);
+ switch (ie_val->ie_pltype) {
+ case AST_EVENT_IE_PLTYPE_STR:
+ case AST_EVENT_IE_PLTYPE_RAW:
+ ast_free(ie_val->payload.raw);
+ break;
+ case AST_EVENT_IE_PLTYPE_UINT:
+ case AST_EVENT_IE_PLTYPE_EXISTS:
+ case AST_EVENT_IE_PLTYPE_UNKNOWN:
+ break;
+ }
ast_free(ie_val);
}
ie_val->payload.uint = va_arg(ap, uint32_t);
else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
ie_val->payload.str = ast_strdupa(va_arg(ap, const char *));
+ else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) {
+ void *data = va_arg(ap, void *);
+ size_t datalen = va_arg(ap, size_t);
+ ie_val->payload.raw = alloca(datalen);
+ memcpy(ie_val->payload.raw, data, datalen);
+ ie_val->raw_datalen = datalen;
+ }
AST_LIST_INSERT_TAIL(&ie_vals, ie_val, entry);
}
va_end(ap);
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))
+ break;
}
if (!ie_val)
break;
return res;
}
+static int match_ie_val(struct ast_event *event, struct ast_event_ie_val *ie_val, struct ast_event *event2)
+{
+ if (ie_val->ie_pltype == 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;
+ }
+
+ if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR) {
+ const char *str = event2 ? ast_event_get_ie_str(event2, ie_val->ie_type) : ie_val->payload.str;
+ if (str && !strcmp(str, ast_event_get_ie_str(event, ie_val->ie_type)))
+ return 1;
+ return 0;
+ }
+
+ if (ie_val->ie_pltype == 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;
+ }
+
+ if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) {
+ if (ast_event_get_ie_raw(event, ie_val->ie_type))
+ return 1;
+ return 0;
+ }
+
+ return 0;
+}
+
+/*! \brief Dump the event cache for the subscribed event type */
+void ast_event_dump_cache(const struct ast_event_sub *event_sub)
+{
+ struct ast_event_ref *event_ref;
+ enum ast_event_type type = event_sub->type;
+
+ AST_RWLIST_RDLOCK(&ast_event_cache[type]);
+ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[type], event_ref, entry) {
+ struct ast_event_ie_val *ie_val;
+ AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
+ if (!match_ie_val(event_ref->event, ie_val, NULL))
+ break;
+ }
+ if (!ie_val) {
+ /* All parameters were matched on this cache entry, so dump it */
+ event_sub->cb(event_ref->event, event_sub->userdata);
+ }
+ }
+ AST_RWLIST_TRAVERSE_SAFE_END
+ AST_RWLIST_UNLOCK(&ast_event_cache[type]);
+}
+
+static struct ast_event *gen_sub_event(struct ast_event_sub *sub)
+{
+ struct ast_event_ie_val *ie_val;
+ struct ast_event *event;
+
+ event = ast_event_new(AST_EVENT_SUB,
+ 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)
+ return NULL;
+
+ AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
+ switch (ie_val->ie_pltype) {
+ case AST_EVENT_IE_PLTYPE_UNKNOWN:
+ break;
+ case AST_EVENT_IE_PLTYPE_EXISTS:
+ ast_event_append_ie_uint(&event, AST_EVENT_IE_EXISTS, ie_val->ie_type);
+ break;
+ 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_STR:
+ ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
+ 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;
+ }
+ if (!event)
+ break;
+ }
+
+ return event;
+}
+
/*! \brief Send AST_EVENT_SUB events to this subscriber of ... subscriber events */
void ast_event_report_subs(const struct ast_event_sub *event_sub)
{
if (event_sub == sub)
continue;
- event = ast_event_new(AST_EVENT_SUB,
- 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);
-
- AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
- switch (ie_val->ie_pltype) {
- case AST_EVENT_IE_PLTYPE_EXISTS:
- ast_event_append_ie_uint(&event, AST_EVENT_IE_EXISTS, ie_val->ie_type);
- break;
- 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_STR:
- ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
- break;
- }
- if (!event)
- break;
- }
+ event = gen_sub_event(sub);
if (!event)
continue;
AST_RWDLLIST_UNLOCK(&ast_event_subs[event_type]);
}
-struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb,
- void *userdata, ...)
+struct ast_event_sub *ast_event_subscribe_new(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;
- struct ast_event *event;
- if (type >= AST_EVENT_TOTAL) {
+ if (type < 0 || type >= AST_EVENT_TOTAL) {
ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
return NULL;
}
if (!(sub = ast_calloc(1, sizeof(*sub))))
return NULL;
- va_start(ap, userdata);
- for (ie_type = va_arg(ap, enum ast_event_type);
- ie_type != AST_EVENT_IE_END;
- ie_type = va_arg(ap, enum ast_event_type))
- {
- struct ast_event_ie_val *ie_val;
- if (!(ie_val = ast_calloc(1, sizeof(*ie_val))))
- continue;
- ie_val->ie_type = ie_type;
- ie_val->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT)
- ie_val->payload.uint = va_arg(ap, uint32_t);
- else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR) {
- if (!(ie_val->payload.str = ast_strdup(va_arg(ap, const char *)))) {
- ast_free(ie_val);
- continue;
- }
- }
- AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
- }
- va_end(ap);
-
sub->type = type;
sub->cb = cb;
sub->userdata = userdata;
sub->uniqueid = ast_atomic_fetchadd_int((int *) &sub_uniqueid, 1);
+ return sub;
+}
+
+int ast_event_sub_append_ie_uint(struct ast_event_sub *sub,
+ enum ast_event_ie_type ie_type, uint32_t uint)
+{
+ 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 = uint;
+ ie_val->ie_pltype = AST_EVENT_IE_PLTYPE_UINT;
+
+ 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)
+{
+ 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->ie_pltype = AST_EVENT_IE_PLTYPE_EXISTS;
+
+ AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
+
+ return 0;
+}
+
+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)
+ return -1;
+
+ 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;
+
+ if (!(ie_val->payload.str = ast_strdup(str))) {
+ ast_free(ie_val);
+ return -1;
+ }
+
+ AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
+
+ return 0;
+}
+
+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)
+ return -1;
+
+ 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;
+ ie_val->raw_datalen = raw_datalen;
+
+ if (!(ie_val->payload.raw = ast_malloc(raw_datalen))) {
+ ast_free(ie_val);
+ return -1;
+ }
+
+ memcpy(ie_val->payload.raw, data, raw_datalen);
+
+ AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
+
+ return 0;
+}
+
+int ast_event_sub_activate(struct ast_event_sub *sub)
+{
if (ast_event_check_subscriber(AST_EVENT_SUB,
- AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, type,
+ AST_EVENT_IE_EVENTTYPE, AST_EVENT_IE_PLTYPE_UINT, sub->type,
AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) {
- struct ast_event_ie_val *ie_val;
+ struct ast_event *event;
- event = ast_event_new(AST_EVENT_SUB,
- 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);
-
- AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
- switch (ie_val->ie_pltype) {
- case AST_EVENT_IE_PLTYPE_EXISTS:
- ast_event_append_ie_uint(&event, AST_EVENT_IE_EXISTS, ie_val->ie_type);
- break;
- 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_STR:
- ast_event_append_ie_str(&event, ie_val->ie_type, ie_val->payload.str);
- break;
- }
- if (!event)
- break;
- }
+ event = gen_sub_event(sub);
if (event)
ast_event_queue(event);
}
- AST_RWDLLIST_WRLOCK(&ast_event_subs[type]);
- AST_RWDLLIST_INSERT_TAIL(&ast_event_subs[type], sub, entry);
- AST_RWDLLIST_UNLOCK(&ast_event_subs[type]);
+ AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]);
+ AST_RWDLLIST_INSERT_TAIL(&ast_event_subs[sub->type], sub, entry);
+ AST_RWDLLIST_UNLOCK(&ast_event_subs[sub->type]);
+
+ return 0;
+}
+
+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)))
+ return NULL;
+
+ va_start(ap, userdata);
+ for (ie_type = va_arg(ap, enum ast_event_type);
+ ie_type != AST_EVENT_IE_END;
+ ie_type = va_arg(ap, enum ast_event_type))
+ {
+ enum ast_event_ie_pltype ie_pltype;
+
+ ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
+
+ switch (ie_pltype) {
+ case AST_EVENT_IE_PLTYPE_UNKNOWN:
+ break;
+ case AST_EVENT_IE_PLTYPE_UINT:
+ {
+ uint32_t uint = va_arg(ap, uint32_t);
+ ast_event_sub_append_ie_uint(sub, ie_type, uint);
+ break;
+ }
+ case AST_EVENT_IE_PLTYPE_STR:
+ {
+ const char *str = va_arg(ap, const char *);
+ ast_event_sub_append_ie_str(sub, ie_type, str);
+ break;
+ }
+ case AST_EVENT_IE_PLTYPE_RAW:
+ {
+ void *data = va_arg(ap, void *);
+ size_t data_len = va_arg(ap, size_t);
+ ast_event_sub_append_ie_raw(sub, ie_type, data, data_len);
+ break;
+ }
+ case AST_EVENT_IE_PLTYPE_EXISTS:
+ ast_event_sub_append_ie_exists(sub, ie_type);
+ break;
+ }
+ }
+ va_end(ap);
+
+ ast_event_sub_activate(sub);
return sub;
}
-static void ast_event_sub_destroy(struct ast_event_sub *sub)
+void ast_event_sub_destroy(struct ast_event_sub *sub)
{
struct ast_event_ie_val *ie_val;
ast_free(sub);
}
-void ast_event_unsubscribe(struct ast_event_sub *sub)
+struct ast_event_sub *ast_event_unsubscribe(struct ast_event_sub *sub)
{
struct ast_event *event;
}
ast_event_sub_destroy(sub);
+
+ return NULL;
}
void ast_event_iterator_init(struct ast_event_iterator *iterator, const struct ast_event *event)
ie_val->payload.uint = va_arg(ap, uint32_t);
else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
ie_val->payload.str = ast_strdupa(va_arg(ap, const char *));
+ else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) {
+ void *data = va_arg(ap, void *);
+ size_t datalen = va_arg(ap, size_t);
+ ie_val->payload.raw = alloca(datalen);
+ memcpy(ie_val->payload.raw, data, datalen);
+ ie_val->raw_datalen = datalen;
+ }
AST_LIST_INSERT_TAIL(&ie_vals, ie_val, entry);
}
va_end(ap);
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)
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);
if (!event)
break;
}
+ if (!ast_event_get_ie_raw(event, AST_EVENT_IE_EID)) {
+ /* If the event is originating on this server, add the server's
+ * entity ID to the event. */
+ ast_event_append_ie_raw(&event, AST_EVENT_IE_EID, &g_eid, sizeof(g_eid));
+ }
+
return event;
}
struct ast_event *dup_event;
uint16_t event_len;
- event_len = ntohs(event->event_len);
+ event_len = ast_event_get_size(event);
if (!(dup_event = ast_calloc(1, event_len)))
return NULL;
enum ast_event_ie_type ie_type;
struct ast_event *dup_event = NULL;
struct ast_event_ref *event_ref;
- struct cache_arg {
- AST_LIST_ENTRY(cache_arg) entry;
- enum ast_event_ie_type ie_type;
- enum ast_event_ie_pltype ie_pltype;
- union {
- uint32_t uint;
- const char *str;
- } payload;
- } *cache_arg;
- AST_LIST_HEAD_NOLOCK_STATIC(cache_args, cache_arg);
+ struct ast_event_ie_val *cache_arg;
+ AST_LIST_HEAD_NOLOCK_STATIC(cache_args, ast_event_ie_val);
if (type >= AST_EVENT_TOTAL) {
ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
cache_arg->payload.uint = va_arg(ap, uint32_t);
else if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
cache_arg->payload.str = ast_strdupa(va_arg(ap, const char *));
+ else if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) {
+ void *data = va_arg(ap, void *);
+ size_t datalen = va_arg(ap, size_t);
+ cache_arg->payload.raw = alloca(datalen);
+ memcpy(cache_arg->payload.raw, data, datalen);
+ cache_arg->raw_datalen = datalen;
+ }
AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
}
va_end(ap);
AST_RWLIST_RDLOCK(&ast_event_cache[type]);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[type], event_ref, entry) {
AST_LIST_TRAVERSE(&cache_args, cache_arg, entry) {
- if ( ! ( (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_UINT &&
- (cache_arg->payload.uint ==
- ast_event_get_ie_uint(event_ref->event, cache_arg->ie_type))) ||
-
- (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_STR &&
- (!strcmp(cache_arg->payload.str,
- ast_event_get_ie_str(event_ref->event, cache_arg->ie_type)))) ||
-
- (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS &&
- ast_event_get_ie_raw(event_ref->event, cache_arg->ie_type)) ) )
- {
+ if (!match_ie_val(event_ref->event, cache_arg, NULL))
break;
- }
}
if (!cache_arg) {
/* All parameters were matched on this cache entry, so return it */
uint16_t host_event_type;
struct ast_event_ref *event_ref;
int res;
- struct cache_arg {
- AST_LIST_ENTRY(cache_arg) entry;
- enum ast_event_ie_type ie_type;
- enum ast_event_ie_pltype ie_pltype;
- } *cache_arg;
- AST_LIST_HEAD_NOLOCK_STATIC(cache_args, cache_arg);
+ struct ast_event_ie_val *cache_arg;
+ AST_LIST_HEAD_NOLOCK_STATIC(cache_args, ast_event_ie_val);
host_event_type = ntohs(event->type);
memset(cache_arg, 0, sizeof(*cache_arg));
cache_arg->ie_type = ie_type;
cache_arg->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
+ if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_RAW)
+ cache_arg->raw_datalen = va_arg(ap, size_t);
AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
}
va_end(ap);
AST_RWLIST_WRLOCK(&ast_event_cache[host_event_type]);
AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[host_event_type], event_ref, entry) {
AST_LIST_TRAVERSE(&cache_args, cache_arg, entry) {
- if ( ! ( (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_UINT &&
- (ast_event_get_ie_uint(event, cache_arg->ie_type) ==
- ast_event_get_ie_uint(event_ref->event, cache_arg->ie_type))) ||
-
- (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_STR &&
- (!strcmp(ast_event_get_ie_str(event, cache_arg->ie_type),
- ast_event_get_ie_str(event_ref->event, cache_arg->ie_type)))) ||
-
- (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS &&
- ast_event_get_ie_raw(event_ref->event, cache_arg->ie_type)) ) )
- {
+ if (!match_ie_val(event_ref->event, cache_arg, event))
break;
- }
}
if (!cache_arg) {
/* All parameters were matched on this cache entry, so remove it */
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 (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS &&
- ast_event_get_ie_raw(event_ref->event, ie_val->ie_type)) {
- continue;
- } else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT &&
- ast_event_get_ie_uint(event_ref->event, ie_val->ie_type)
- == ie_val->payload.uint) {
- continue;
- } else if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR &&
- !strcmp(ast_event_get_ie_str(event_ref->event, ie_val->ie_type),
- ie_val->payload.str)) {
- continue;
- }
- break;
+ if (!match_ie_val(event_ref->event, ie_val, NULL))
+ break;
}
if (ie_val)
continue;