[asterisk-commits] irroot: branch irroot/t38gateway-trunk r321985 - in /team/irroot/t38gateway-t...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Jun 4 03:31:38 CDT 2011


Author: irroot
Date: Sat Jun  4 03:31:31 2011
New Revision: 321985

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=321985
Log:
Fixup Merge

Modified:
    team/irroot/t38gateway-trunk/   (props changed)
    team/irroot/t38gateway-trunk/cdr/cdr_radius.c
    team/irroot/t38gateway-trunk/cel/cel_odbc.c   (props changed)
    team/irroot/t38gateway-trunk/cel/cel_radius.c
    team/irroot/t38gateway-trunk/channels/chan_iax2.c
    team/irroot/t38gateway-trunk/channels/chan_sip.c
    team/irroot/t38gateway-trunk/configs/cel_odbc.conf.sample   (props changed)
    team/irroot/t38gateway-trunk/configs/queues.conf.sample
    team/irroot/t38gateway-trunk/configure
    team/irroot/t38gateway-trunk/include/asterisk/event.h
    team/irroot/t38gateway-trunk/main/astobj2.c
    team/irroot/t38gateway-trunk/main/ccss.c
    team/irroot/t38gateway-trunk/main/event.c
    team/irroot/t38gateway-trunk/sounds/Makefile   (props changed)
    team/irroot/t38gateway-trunk/tests/test_astobj2.c
    team/irroot/t38gateway-trunk/tests/test_event.c

Propchange: team/irroot/t38gateway-trunk/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/irroot/t38gateway-trunk/
------------------------------------------------------------------------------
--- branch-1.8-blocked (original)
+++ branch-1.8-blocked Sat Jun  4 03:31:31 2011
@@ -1,1 +1,1 @@
-/branches/1.8:299531,313436,317858,317861,321335
+/branches/1.8:299531,313436,317858,317861,321335,321753

Propchange: team/irroot/t38gateway-trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Propchange: team/irroot/t38gateway-trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Jun  4 03:31:31 2011
@@ -1,3 +1,3 @@
 /team/irroot/distrotech-customers-1.8:319062
 /team/irroot/distrotech-customers-trunk:320771
-/trunk:318974-321617
+/trunk:318974-321980

Modified: team/irroot/t38gateway-trunk/cdr/cdr_radius.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/cdr/cdr_radius.c?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/cdr/cdr_radius.c (original)
+++ team/irroot/t38gateway-trunk/cdr/cdr_radius.c Sat Jun  4 03:31:31 2011
@@ -224,6 +224,10 @@
 static int unload_module(void)
 {
 	ast_cdr_unregister(name);
+	if (rh) {
+		rc_destroy(rh);
+		rh = NULL;
+	}
 	return 0;
 }
 
@@ -243,8 +247,17 @@
 	} else
 		return AST_MODULE_LOAD_DECLINE;
 
-	/* start logging */
-	rc_openlog("asterisk");
+	/*
+	 * start logging
+	 *
+	 * NOTE: Yes this causes a slight memory leak if the module is
+	 * unloaded.  However, it is better than a crash if cdr_radius
+	 * and cel_radius are both loaded.
+	 */
+	tmp = ast_strdup("asterisk");
+	if (tmp) {
+		rc_openlog((char *) tmp);
+	}
 
 	/* read radiusclient-ng config file */
 	if (!(rh = rc_read_config(radiuscfg))) {
@@ -255,11 +268,18 @@
 	/* read radiusclient-ng dictionaries */
 	if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary"))) {
 		ast_log(LOG_NOTICE, "Cannot load radiusclient-ng dictionary file.\n");
-		return AST_MODULE_LOAD_DECLINE;
-	}
-
-	ast_cdr_register(name, desc, radius_log);
-	return AST_MODULE_LOAD_SUCCESS;
+		rc_destroy(rh);
+		rh = NULL;
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
+	if (ast_cdr_register(name, desc, radius_log)) {
+		rc_destroy(rh);
+		rh = NULL;
+		return AST_MODULE_LOAD_DECLINE;
+	} else {
+		return AST_MODULE_LOAD_SUCCESS;
+	}
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "RADIUS CDR Backend",

Propchange: team/irroot/t38gateway-trunk/cel/cel_odbc.c
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Jun  4 03:31:31 2011
@@ -1,4 +1,4 @@
 /be/branches/C.3/cel/cel_adaptive_odbc.c:256426
 /team/irroot/distrotech-customers-1.8/cel/cel_odbc.c:319062
 /team/irroot/distrotech-customers-trunk/cel/cel_odbc.c:320771
-/trunk/cel/cel_odbc.c:318974-321617
+/trunk/cel/cel_odbc.c:318974-321980

Modified: team/irroot/t38gateway-trunk/cel/cel_radius.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/cel/cel_radius.c?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/cel/cel_radius.c (original)
+++ team/irroot/t38gateway-trunk/cel/cel_radius.c Sat Jun  4 03:31:31 2011
@@ -206,6 +206,10 @@
 	if (event_sub) {
 		event_sub = ast_event_unsubscribe(event_sub);
 	}
+	if (rh) {
+		rc_destroy(rh);
+		rh = NULL;
+	}
 	return AST_MODULE_LOAD_SUCCESS;
 }
 
@@ -225,8 +229,17 @@
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
-	/* start logging */
-	rc_openlog("asterisk");
+	/*
+	 * start logging
+	 *
+	 * NOTE: Yes this causes a slight memory leak if the module is
+	 * unloaded.  However, it is better than a crash if cdr_radius
+	 * and cel_radius are both loaded.
+	 */
+	tmp = ast_strdup("asterisk");
+	if (tmp) {
+		rc_openlog((char *) tmp);
+	}
 
 	/* read radiusclient-ng config file */
 	if (!(rh = rc_read_config(radiuscfg))) {
@@ -237,12 +250,15 @@
 	/* read radiusclient-ng dictionaries */
 	if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary"))) {
 		ast_log(LOG_NOTICE, "Cannot load radiusclient-ng dictionary file.\n");
+		rc_destroy(rh);
+		rh = NULL;
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
 	event_sub = ast_event_subscribe(AST_EVENT_CEL, radius_log, "CEL Radius Logging", NULL, AST_EVENT_IE_END);
-
 	if (!event_sub) {
+		rc_destroy(rh);
+		rh = NULL;
 		return AST_MODULE_LOAD_DECLINE;
 	} else {
 		return AST_MODULE_LOAD_SUCCESS;

Modified: team/irroot/t38gateway-trunk/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/channels/chan_iax2.c?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/channels/chan_iax2.c (original)
+++ team/irroot/t38gateway-trunk/channels/chan_iax2.c Sat Jun  4 03:31:31 2011
@@ -1282,10 +1282,7 @@
 {
 	if (!network_change_event_subscription) {
 		network_change_event_subscription = ast_event_subscribe(AST_EVENT_NETWORK_CHANGE,
-			network_change_event_cb,
-			"SIP Network Change ",
-			NULL,
-			AST_EVENT_IE_END);
+			network_change_event_cb, "IAX2 Network Change", NULL, AST_EVENT_IE_END);
 	}
 }
 

Modified: team/irroot/t38gateway-trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/channels/chan_sip.c?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/channels/chan_sip.c (original)
+++ team/irroot/t38gateway-trunk/channels/chan_sip.c Sat Jun  4 03:31:31 2011
@@ -14248,9 +14248,7 @@
 {
 	if (!network_change_event_subscription) {
 		network_change_event_subscription = ast_event_subscribe(AST_EVENT_NETWORK_CHANGE,
-			network_change_event_cb,
-			"SIP Network Change ",
-			NULL, AST_EVENT_IE_END);
+			network_change_event_cb, "SIP Network Change", NULL, AST_EVENT_IE_END);
 	}
 }
 

Propchange: team/irroot/t38gateway-trunk/configs/cel_odbc.conf.sample
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Sat Jun  4 03:31:31 2011
@@ -1,4 +1,4 @@
 /be/branches/C.3/configs/cel_adaptive_odbc.conf.sample:256426
 /team/irroot/distrotech-customers-1.8/configs/cel_odbc.conf.sample:319062
 /team/irroot/distrotech-customers-trunk/configs/cel_odbc.conf.sample:320771
-/trunk/configs/cel_odbc.conf.sample:318974-321617
+/trunk/configs/cel_odbc.conf.sample:318974-321980

Modified: team/irroot/t38gateway-trunk/configs/queues.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/configs/queues.conf.sample?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/configs/queues.conf.sample (original)
+++ team/irroot/t38gateway-trunk/configs/queues.conf.sample Sat Jun  4 03:31:31 2011
@@ -318,6 +318,8 @@
 ;queue-callswaiting = queue-callswaiting
 			;	("The current est. holdtime is")
 ;queue-holdtime = queue-holdtime
+			;	("minute.")
+;queue-minute = queue-minute
 			;	("minutes.")
 ;queue-minutes = queue-minutes
 			;	("seconds.")

Modified: team/irroot/t38gateway-trunk/include/asterisk/event.h
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/include/asterisk/event.h?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/include/asterisk/event.h (original)
+++ team/irroot/t38gateway-trunk/include/asterisk/event.h Sat Jun  4 03:31:31 2011
@@ -114,7 +114,7 @@
  * \note A NULL description will cause this function to crash, so watch out!
  */
 struct ast_event_sub *ast_event_subscribe(enum ast_event_type event_type,
-       ast_event_cb_t cb, char *description, void *userdata, ...);
+       ast_event_cb_t cb, const char *description, void *userdata, ...);
 
 /*!
  * \brief Allocate a subscription, but do not activate it
@@ -397,8 +397,7 @@
  * The event API already knows which events can be cached and how to cache them.
  *
  * \retval 0 success
- * \retval non-zero failure.  If failure is returned, the event must be destroyed
- *         by the caller of this function.
+ * \retval non-zero failure.
  */
 int ast_event_queue_and_cache(struct ast_event *event);
 

Modified: team/irroot/t38gateway-trunk/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/main/astobj2.c?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/main/astobj2.c (original)
+++ team/irroot/t38gateway-trunk/main/astobj2.c Sat Jun  4 03:31:31 2011
@@ -734,10 +734,6 @@
 				}
 				ast_free(cur);	/* free the link record */
 			}
-			if ((match) && (!(flags & OBJ_UNLINK))) {
-				AST_LIST_REMOVE_CURRENT(entry);
-				AST_LIST_INSERT_HEAD(&c->buckets[i], cur, entry);
-			}
 
 			if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
 				/* We found our only (or last) match, so force an exit from

Modified: team/irroot/t38gateway-trunk/main/ccss.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/main/ccss.c?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/main/ccss.c (original)
+++ team/irroot/t38gateway-trunk/main/ccss.c Sat Jun  4 03:31:31 2011
@@ -1241,9 +1241,11 @@
 		return NULL;
 	}
 
-	if (!(generic_list->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, generic_monitor_devstate_cb,
-				"Requesting CC", NULL, AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR,
-				monitor->interface->device_name, AST_EVENT_IE_END))) {
+	if (!(generic_list->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE,
+		generic_monitor_devstate_cb, "Requesting CC", NULL,
+		AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, monitor->interface->device_name,
+		AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_EXISTS,
+		AST_EVENT_IE_END))) {
 		cc_unref(generic_list, "Failed to subscribe to device state");
 		return NULL;
 	}
@@ -2629,10 +2631,11 @@
 	ast_str_set(&str, 0, "Agent monitoring %s device state since it is busy\n",
 		agent->device_name);
 
-	if (!(generic_pvt->sub = ast_event_subscribe(
-			AST_EVENT_DEVICE_STATE, generic_agent_devstate_cb, ast_str_buffer(str), agent,
-			AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->device_name,
-			AST_EVENT_IE_END))) {
+	if (!(generic_pvt->sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE,
+		generic_agent_devstate_cb, ast_str_buffer(str), agent,
+		AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, agent->device_name,
+		AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_EXISTS,
+		AST_EVENT_IE_END))) {
 		return -1;
 	}
 	return 0;

Modified: team/irroot/t38gateway-trunk/main/event.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/main/event.c?view=diff&rev=321985&r1=321984&r2=321985
==============================================================================
--- team/irroot/t38gateway-trunk/main/event.c (original)
+++ team/irroot/t38gateway-trunk/main/event.c Sat Jun  4 03:31:31 2011
@@ -194,6 +194,7 @@
  * \brief Event Names
  */
 static const char * const event_names[AST_EVENT_TOTAL] = {
+	[AST_EVENT_ALL]                 = "All",
 	[AST_EVENT_CUSTOM]              = "Custom",
 	[AST_EVENT_MWI]                 = "MWI",
 	[AST_EVENT_SUB]                 = "Subscription",
@@ -359,53 +360,72 @@
 	ast_free(ie_val);
 }
 
+/*! \brief Subscription event check list. */
+struct ast_ev_check_list {
+	AST_LIST_HEAD_NOLOCK(, ast_event_ie_val) ie_vals;
+};
+
 /*!
  * \internal
- * \brief Check if an ie_val matches a subscription
- *
- * \param sub subscription to check against
- * \param ie_val IE value to check
+ * \brief Check if a subscription ie_val matches an event.
+ *
+ * \param sub_ie_val Subscripton IE value to check
+ * \param check_ie_vals event list to check against
  *
  * \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) {
+static int match_sub_ie_val_to_event(const struct ast_event_ie_val *sub_ie_val, const struct ast_ev_check_list *check_ie_vals)
+{
+	const struct ast_event_ie_val *event_ie_val;
+	int res = 0;
+
+	AST_LIST_TRAVERSE(&check_ie_vals->ie_vals, event_ie_val, entry) {
+		if (event_ie_val->ie_type == sub_ie_val->ie_type) {
+			break;
+		}
+	}
+	if (!event_ie_val) {
+		/* The did not find the event ie the subscriber cares about. */
+		return 0;
+	}
+
+	if (sub_ie_val->ie_pltype != event_ie_val->ie_pltype) {
+		if (sub_ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS) {
+			/* The subscription only cares that this ie exists. */
+			return 1;
+		}
+		/* Payload types do not match. */
+		return 0;
+	}
+
+	switch (sub_ie_val->ie_pltype) {
 	case AST_EVENT_IE_PLTYPE_UINT:
-		res = (ie_val->payload.uint != sub_ie_val->payload.uint);
+		res = (sub_ie_val->payload.uint == event_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.
 		 */
-		res = !(ie_val->payload.uint & sub_ie_val->payload.uint);
+		res = (sub_ie_val->payload.uint & event_ie_val->payload.uint);
 		break;
 	case AST_EVENT_IE_PLTYPE_STR:
-		res = strcmp(ie_val->payload.str, sub_ie_val->payload.str);
+		res = !strcmp(sub_ie_val->payload.str, event_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);
+		res = (sub_ie_val->raw_datalen == event_ie_val->raw_datalen
+			&& !memcmp(sub_ie_val->payload.raw, event_ie_val->payload.raw,
+				sub_ie_val->raw_datalen));
 		break;
 	case AST_EVENT_IE_PLTYPE_EXISTS:
+		/* Should never get here since check_ie_vals cannot have this type. */
+		break;
 	case AST_EVENT_IE_PLTYPE_UNKNOWN:
+		/*
+		 * Should never be in a subscription event ie val list and
+		 * check_ie_vals cannot have this type either.
+		 */
 		break;
 	}
 
@@ -419,7 +439,9 @@
 	enum ast_event_subscriber_res res = AST_EVENT_SUB_NONE;
 	struct ast_event_ie_val *ie_val;
 	struct ast_event_sub *sub;
-	AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val);
+	struct ast_ev_check_list check_ie_vals = {
+		.ie_vals = AST_LIST_HEAD_NOLOCK_INIT_VALUE
+	};
 	const enum ast_event_type event_types[] = { type, AST_EVENT_ALL };
 	int i;
 
@@ -434,19 +456,740 @@
 		ie_type = va_arg(ap, enum ast_event_ie_type))
 	{
 		struct ast_event_ie_val *ie_value = alloca(sizeof(*ie_value));
-		int insert = 1;
+		int insert = 0;
+
 		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);
 		switch (ie_value->ie_pltype) {
 		case AST_EVENT_IE_PLTYPE_UINT:
 			ie_value->payload.uint = va_arg(ap, uint32_t);
+			insert = 1;
 			break;
 		case AST_EVENT_IE_PLTYPE_BITFLAGS:
 			ie_value->payload.uint = va_arg(ap, uint32_t);
+			insert = 1;
 			break;
 		case AST_EVENT_IE_PLTYPE_STR:
 			ie_value->payload.str = va_arg(ap, const char *);
+			insert = 1;
+			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;
+			insert = 1;
+			break;
+		}
+		case AST_EVENT_IE_PLTYPE_UNKNOWN:
+		case AST_EVENT_IE_PLTYPE_EXISTS:
+			/* Unsupported payload type. */
+			break;
+		}
+
+		if (insert) {
+			AST_LIST_INSERT_TAIL(&check_ie_vals.ie_vals, ie_value, entry);
+		} else {
+			ast_log(LOG_WARNING, "Unsupported PLTYPE(%d)\n", ie_value->ie_pltype);
+		}
+	}
+	va_end(ap);
+
+	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(&sub->ie_vals, ie_val, entry) {
+				if (!match_sub_ie_val_to_event(ie_val, &check_ie_vals)) {
+					/* The current subscription ie did not match an event ie. */
+					break;
+				}
+			}
+			if (!ie_val) {
+				/* Everything matched.  A subscriber is looking for this event. */
+				break;
+			}
+		}
+		AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
+		if (sub) {
+			break;
+		}
+	}
+
+	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)
+{
+	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;
+
+		return (val == ast_event_get_ie_uint(event, ie_val->ie_type)) ? 1 : 0;
+	}
+
+	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;
+
+		hash = event2 ? ast_event_get_ie_str_hash(event2, ie_val->ie_type) : ie_val->payload.hash;
+		if (hash != ast_event_get_ie_str_hash(event, ie_val->ie_type)) {
+			return 0;
+		}
+
+		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;
+	}
+
+	case AST_EVENT_IE_PLTYPE_RAW:
+	{
+		const void *buf = event2 ? ast_event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw;
+		uint16_t ie_payload_len = event2 ? ast_event_get_ie_raw_payload_len(event2, ie_val->ie_type) : ie_val->raw_datalen;
+
+		return (buf
+			&& ie_payload_len == ast_event_get_ie_raw_payload_len(event, ie_val->ie_type)
+			&& !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_payload_len)) ? 1 : 0;
+	}
+
+	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;
+	}
+
+	return 0;
+}
+
+static int dump_cache_cb(void *obj, void *arg, int flags)
+{
+	const struct ast_event_ref *event_ref = obj;
+	const struct ast_event *event = event_ref->event;
+	const struct ast_event_sub *event_sub = arg;
+	struct ast_event_ie_val *ie_val = NULL;
+
+	AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
+		if (!match_ie_val(event, ie_val, NULL)) {
+			break;
+		}
+	}
+
+	if (!ie_val) {
+		/* All parameters were matched on this cache entry, so dump it */
+		event_sub->cb(event, event_sub->userdata);
+	}
+
+	return 0;
+}
+
+/*! \brief Dump the event cache for the subscribed event type */
+void ast_event_dump_cache(const struct ast_event_sub *event_sub)
+{
+	ao2_callback(ast_event_cache[event_sub->type].container, OBJ_NODATA,
+			dump_cache_cb, (void *) event_sub);
+}
+
+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_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, sub->description,
+		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_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;
+		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)
+{
+	struct ast_event *event;
+	struct ast_event_sub *sub;
+	enum ast_event_type event_type = -1;
+	struct ast_event_ie_val *ie_val;
+
+	if (event_sub->type != AST_EVENT_SUB)
+		return;
+
+	AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
+		if (ie_val->ie_type == AST_EVENT_IE_EVENTTYPE) {
+			event_type = ie_val->payload.uint;
+			break;
+		}
+	}
+
+	if (event_type == -1)
+		return;
+
+	AST_RWDLLIST_RDLOCK(&ast_event_subs[event_type]);
+	AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_type], sub, entry) {
+		if (event_sub == sub) {
+			continue;
+		}
+
+		event = gen_sub_event(sub);
+		if (!event) {
+			continue;
+		}
+
+		event_sub->cb(event, event_sub->userdata);
+
+		ast_event_destroy(event);
+	}
+	AST_RWDLLIST_UNLOCK(&ast_event_subs[event_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;
+
+	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;
+	}
+
+	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 unsigned_int)
+{
+	struct ast_event_ie_val *ie_val;
+
+	if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
+		return -1;
+	}
+
+	if (!(ie_val = ast_calloc(1, sizeof(*ie_val)))) {
+		return -1;
+	}
+
+	ie_val->ie_type = ie_type;
+	ie_val->payload.uint = unsigned_int;
+	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_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_TOTAL) {
+		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)
+{
+	struct ast_event_ie_val *ie_val;
+
+	if (ie_type <= 0 || ie_type >= AST_EVENT_IE_TOTAL) {
+		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_TOTAL) {
+		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;
+	}
+
+	ie_val->payload.hash = ast_str_hash(str);
+
+	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_TOTAL) {
+		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, sub->type,
+		AST_EVENT_IE_END) != AST_EVENT_SUB_NONE) {
+		struct ast_event *event;
+
+		event = gen_sub_event(sub);
+		if (event && ast_event_queue(event)) {
+			ast_event_destroy(event);
+		}
+	}
+
+	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,
+	const char *description, 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;
+	}
+
+	ast_copy_string(sub->description, description, sizeof(sub->description));
+
+	va_start(ap, userdata);
+	for (ie_type = va_arg(ap, enum ast_event_ie_type);
+		ie_type != AST_EVENT_IE_END;
+		ie_type = va_arg(ap, enum ast_event_ie_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 unsigned_int = va_arg(ap, uint32_t);
+			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 *);
+			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;
+}
+
+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))) {
+		ast_event_ie_val_destroy(ie_val);
+	}
+
+	ast_free(sub);
+}
+
+const char *ast_event_subscriber_get_description(struct ast_event_sub *sub)
+{
+	return sub ? sub->description : NULL;
+}
+
+struct ast_event_sub *ast_event_unsubscribe(struct ast_event_sub *sub)
+{
+	struct ast_event *event;
+
+	AST_RWDLLIST_WRLOCK(&ast_event_subs[sub->type]);
+	AST_DLLIST_REMOVE(&ast_event_subs[sub->type], sub, entry);
+	AST_RWDLLIST_UNLOCK(&ast_event_subs[sub->type]);
+
+	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_DESCRIPTION, AST_EVENT_IE_PLTYPE_STR, sub->description,
+			AST_EVENT_IE_END);
+		if (event && ast_event_queue(event)) {
+			ast_event_destroy(event);
+		}
+	}
+
+	ast_event_sub_destroy(sub);
+
+	return NULL;
+}
+
+int ast_event_iterator_init(struct ast_event_iterator *iterator, const struct ast_event *event)
+{
+	int res = 0;
+
+	iterator->event_len = ast_event_get_size(event);
+	iterator->event = event;
+	if (iterator->event_len >= sizeof(*event) + sizeof(struct ast_event_ie)) {
+		iterator->ie = (struct ast_event_ie *) ( ((char *) event) + sizeof(*event) );
+	} else {
+		iterator->ie = NULL;
+		res = -1;
+	}
+
+	return res;
+}
+
+int ast_event_iterator_next(struct ast_event_iterator *iterator)
+{
+	iterator->ie = (struct ast_event_ie *) ( ((char *) iterator->ie) + sizeof(*iterator->ie) + ntohs(iterator->ie->ie_payload_len));
+	return ((iterator->event_len <= (((char *) iterator->ie) - ((char *) iterator->event))) ? -1 : 0);
+}
+
+enum ast_event_ie_type ast_event_iterator_get_ie_type(struct ast_event_iterator *iterator)
+{
+	return ntohs(iterator->ie->ie_type);
+}
+
+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;
+
+	str_payload = (struct ast_event_ie_str_payload *) iterator->ie->ie_payload;
+
+	return str_payload ? str_payload->str : NULL;
+}
+
+void *ast_event_iterator_get_ie_raw(struct ast_event_iterator *iterator)
+{
+	return iterator->ie->ie_payload;
+}
+
+uint16_t ast_event_iterator_get_ie_raw_payload_len(struct ast_event_iterator *iterator)
+{
+	return ntohs(iterator->ie->ie_payload_len);
+}
+
+enum ast_event_type ast_event_get_type(const struct ast_event *event)
+{
+	return ntohs(event->type);
+}
+
+uint32_t ast_event_get_ie_uint(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_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;
+
+	str_payload = ast_event_get_ie_raw(event, ie_type);
+
+	return str_payload ? str_payload->hash : 0;
+}
+
+const char *ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
+{
+	const struct ast_event_ie_str_payload *str_payload;
+
+	str_payload = ast_event_get_ie_raw(event, ie_type);
+
+	return str_payload ? str_payload->str : NULL;
+}
+
+const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type)
+{
+	struct ast_event_iterator iterator;
+	int res;
+
+	for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
+		if (ast_event_iterator_get_ie_type(&iterator) == ie_type) {
+			return ast_event_iterator_get_ie_raw(&iterator);
+		}
+	}
+
+	return NULL;
+}
+
+uint16_t ast_event_get_ie_raw_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type)
+{
+	struct ast_event_iterator iterator;
+	int res;
+
+	for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) {
+		if (ast_event_iterator_get_ie_type(&iterator) == ie_type) {
+			return ast_event_iterator_get_ie_raw_payload_len(&iterator);
+		}
+	}
+
+	return 0;
+}
+
+int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type,
+	const char *str)
+{
+	struct ast_event_ie_str_payload *str_payload;
+	size_t payload_len;
+
+	payload_len = sizeof(*str_payload) + strlen(str);
+	str_payload = alloca(payload_len);
+
+	strcpy(str_payload->str, str);
+	str_payload->hash = ast_str_hash(str);
+
+	return ast_event_append_ie_raw(event, ie_type, str_payload, payload_len);
+}
+
+int ast_event_append_ie_uint(struct ast_event **event, enum ast_event_ie_type ie_type,
+	uint32_t data)
+{
+	data = htonl(data);
+	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)
+{
+	struct ast_event_ie *ie;
+	unsigned int extra_len;
+	uint16_t event_len;
+
+	event_len = ntohs((*event)->event_len);
+	extra_len = sizeof(*ie) + data_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);
+	ie->ie_payload_len = htons(data_len);
+	memcpy(ie->ie_payload, data, data_len);
+
+	(*event)->event_len = htons(event_len + extra_len);
+
+	return 0;
+}
+
+struct ast_event *ast_event_new(enum ast_event_type type, ...)
+{
+	va_list ap;
+	struct ast_event *event;
+	enum ast_event_ie_type ie_type;
+	struct ast_event_ie_val *ie_val;
+	int has_ie = 0;
+	AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val);
+
+	/* Invalid type */
+	if (type >= AST_EVENT_TOTAL) {
+		ast_log(LOG_WARNING, "Someone tried to create an event of invalid "
+			"type '%d'!\n", type);
+		return NULL;
+	}
+
+	va_start(ap, type);
+	for (ie_type = va_arg(ap, enum ast_event_ie_type);
+		ie_type != AST_EVENT_IE_END;
+		ie_type = va_arg(ap, enum ast_event_ie_type))
+	{
+		struct ast_event_ie_val *ie_value = alloca(sizeof(*ie_value));
+		int insert = 0;
+
+		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);
+		switch (ie_value->ie_pltype) {
+		case AST_EVENT_IE_PLTYPE_UINT:
+			ie_value->payload.uint = va_arg(ap, uint32_t);
+			insert = 1;
+			break;
+		case AST_EVENT_IE_PLTYPE_BITFLAGS:
+			ie_value->payload.uint = va_arg(ap, uint32_t);
+			insert = 1;
+			break;
+		case AST_EVENT_IE_PLTYPE_STR:
+			ie_value->payload.str = va_arg(ap, const char *);
+			insert = 1;
 			break;
 		case AST_EVENT_IE_PLTYPE_RAW:
 		{
@@ -455,722 +1198,10 @@
 			ie_value->payload.raw = alloca(datalen);
 			memcpy(ie_value->payload.raw, data, datalen);
 			ie_value->raw_datalen = datalen;
+			insert = 1;
 			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);
-		}
-	}
-	va_end(ap);
-
-	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 (!ie_val) {
-				/* Everything matched. */
-				break;
-			}
-		}
-		AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
-		if (sub) {
-			break;
-		}
-	}
-
-	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)
-{
-	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;
-
-		return (val == ast_event_get_ie_uint(event, ie_val->ie_type)) ? 1 : 0;
-	}
-
-	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;
-
-		hash = event2 ? ast_event_get_ie_str_hash(event2, ie_val->ie_type) : ie_val->payload.hash;
-		if (hash != ast_event_get_ie_str_hash(event, ie_val->ie_type)) {
-			return 0;
-		}
-
-		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;
-	}
-
-	case AST_EVENT_IE_PLTYPE_RAW:
-	{
-		const void *buf = event2 ? ast_event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw;
-		uint16_t ie_payload_len = event2 ? ast_event_get_ie_raw_payload_len(event2, ie_val->ie_type) : ie_val->raw_datalen;
-
-		return (buf && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_payload_len)) ? 1 : 0;
-	}
-
-	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;
-	}
-
-	return 0;
-}
-
-static int dump_cache_cb(void *obj, void *arg, int flags)
-{
-	const struct ast_event_ref *event_ref = obj;
-	const struct ast_event *event = event_ref->event;
-	const struct ast_event_sub *event_sub = arg;
-	struct ast_event_ie_val *ie_val = NULL;
-
-	AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
-		if (!match_ie_val(event, ie_val, NULL)) {
-			break;
-		}
-	}
-
-	if (!ie_val) {
-		/* All parameters were matched on this cache entry, so dump it */
-		event_sub->cb(event, event_sub->userdata);
-	}
-
-	return 0;
-}
-
-/*! \brief Dump the event cache for the subscribed event type */
-void ast_event_dump_cache(const struct ast_event_sub *event_sub)
-{

[... 1702 lines stripped ...]



More information about the asterisk-commits mailing list