[asterisk-commits] russell: branch russell/events r59197 - in /team/russell/events: apps/ channe...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Mar 23 22:10:48 MST 2007


Author: russell
Date: Sat Mar 24 00:10:47 2007
New Revision: 59197

URL: http://svn.digium.com/view/asterisk?view=rev&rev=59197
Log:
Another day of flying ...

First, I have made a lot of changes to the event system core to attempt to
satisfy some of Kevin's design goals along with some of my own after having
another discussion with him about this stuff yesterday.
* Add the ability for modules to be able to tell the core that they are capable
  of publishing certain types of events.  They can also say that they can
  publish certain events that match certain criteria.  For example, voicemail
  can say that it is capable of publishing events for a specific mailbox.
* Add the ability to not only subscribe to an event type, but also be able to
  specify additional event criteria.  For example, chan_sip can subscribe to
  MWI events for a specific mailbox.
* Add the ability for modules to be able to find out if someone has indicated
  that they are able to publish certain events with given criteria, or if
  someone has subscribed to events with given criteria.  For example, voicemail
  can know that it doesn't need to bother generating MWI events for some
  mailboxes if nobody has subscribed to them.
* In all of the places where event criteria may be specified, make it so the
  criteria can be that an information element contains a specific value, or
  just simply that it exists.

chan_sip
* Modify chan_sip to no longer use a polling based system for MWI.  Instead, it
  is now event driven.  It subscribes only to the mailboxes it needs to, and
  only when it needs to.

app_voicemail
* Register exactly which mailboxes voicemail is able to publish events for.
  However, this method will not work for realtime voicemail.  I have not
  decided how to approach this yet.

res_eventtest
* Add minor updates to test some new features.

Modified:
    team/russell/events/apps/app_voicemail.c
    team/russell/events/channels/chan_sip.c
    team/russell/events/include/asterisk/event.h
    team/russell/events/include/asterisk/event_defs.h
    team/russell/events/main/event.c
    team/russell/events/res/res_eventtest.c

Modified: team/russell/events/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/apps/app_voicemail.c?view=diff&rev=59197&r1=59196&r2=59197
==============================================================================
--- team/russell/events/apps/app_voicemail.c (original)
+++ team/russell/events/apps/app_voicemail.c Sat Mar 24 00:10:47 2007
@@ -314,7 +314,8 @@
 	unsigned char iobuf[BASEMAXINLINE];
 };
 
-/*! Structure for linked list of users */
+/*! Structure for linked list of users 
+ * Use ast_vm_user_destroy() to free one of these structures. */
 struct ast_vm_user {
 	char context[AST_MAX_CONTEXT];   /*!< Voicemail context */
 	char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox id, unique within vm context */
@@ -340,6 +341,7 @@
 	char imappassword[80];           /*!< IMAP server password if authpassword not defined */
 #endif
 	double volgain;		         /*!< Volume gain for voicemails sent via email */
+	struct ast_event_pub *event_pub;     /*!< MWI event publisher for this mailbox */
 	AST_LIST_ENTRY(ast_vm_user) list;
 };
 
@@ -2217,6 +2219,10 @@
 
 static void free_user(struct ast_vm_user *vmu)
 {
+	if (vmu->event_pub) {
+		ast_event_unreg_publisher(vmu->event_pub);
+		vmu->event_pub = NULL;
+	}
 	if (ast_test_flag(vmu, VM_ALLOCED))
 		free(vmu);
 }
@@ -3938,7 +3944,12 @@
 static void queue_mwi_event(const char *mailbox, int new, int old)
 {
 	struct ast_event *event;
-	
+
+	if (ast_event_check_subscriber(AST_EVENT_MWI,
+		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+		AST_EVENT_IE_END) == AST_EVENT_SUB_NONE)
+		return;
+
 	if (!(event = ast_event_new(AST_EVENT_MWI)))
 		return;
 	if (ast_event_append_ie_str(&event, AST_EVENT_IE_MAILBOX, mailbox))
@@ -3950,7 +3961,7 @@
 
 	ast_event_queue_and_cache(event,
 		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
-		AST_EVENT_END);
+		AST_EVENT_IE_END);
 }
 
 static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
@@ -6889,20 +6900,34 @@
 static struct ast_vm_user *find_or_create(char *context, char *mbox)
 {
 	struct ast_vm_user *vmu;
+	char *full_mailbox;
+
 	AST_LIST_TRAVERSE(&users, vmu, list) {
 		if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mbox, vmu->mailbox))
 			break;
 		if (context && (!strcasecmp(context, vmu->context)) && (!strcasecmp(mbox, vmu->mailbox)))
 			break;
 	}
+
+	if (vmu)
+		return vmu;
 	
-	if (!vmu) {
-		if ((vmu = ast_calloc(1, sizeof(*vmu)))) {
-			ast_copy_string(vmu->context, context, sizeof(vmu->context));
-			ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
-			AST_LIST_INSERT_TAIL(&users, vmu, list);
-		}
-	}
+	if (!(vmu = ast_calloc(1, sizeof(*vmu))))
+		return NULL;
+	
+	ast_copy_string(vmu->context, context, sizeof(vmu->context));
+	ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
+	full_mailbox = alloca(strlen(context) + strlen(mbox) + 2);
+	strcpy(full_mailbox, mbox);
+	strcat(full_mailbox, "@");
+	strcat(full_mailbox, context);
+	vmu->event_pub = ast_event_reg_publisher(AST_EVENT_MWI,
+		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, full_mailbox,
+		AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+		AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+		AST_EVENT_IE_END);
+	AST_LIST_INSERT_TAIL(&users, vmu, list);
+	
 	return vmu;
 }
 

Modified: team/russell/events/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/channels/chan_sip.c?view=diff&rev=59197&r1=59196&r2=59197
==============================================================================
--- team/russell/events/channels/chan_sip.c (original)
+++ team/russell/events/channels/chan_sip.c Sat Mar 24 00:10:47 2007
@@ -142,6 +142,7 @@
 #include "asterisk/threadstorage.h"
 #include "asterisk/translate.h"
 #include "asterisk/version.h"
+#include "asterisk/event.h"
 
 #ifndef FALSE
 #define FALSE    0
@@ -1031,6 +1032,7 @@
 							before strolling to the Grokyzpå
 							(A bit unsure of this, please correct if
 							you know more) */
+	struct ast_event_sub *mwi_event_sub; /*!< The MWI event subscription */
 };
 
 static struct sip_pvt *dialoglist = NULL;
@@ -1134,7 +1136,6 @@
 	char useragent[256];		/*!<  User agent in SIP request (saved from registration) */
 	struct ast_codec_pref prefs;	/*!<  codec prefs */
 	int lastmsgssent;
-	time_t	lastmsgcheck;		/*!<  Last time we checked for MWI */
 	unsigned int sipoptions;	/*!<  Supported SIP options */
 	struct ast_flags flags[2];	/*!<  SIP_ flags */
 	int expire;			/*!<  When to expire this peer registration */
@@ -1291,8 +1292,7 @@
 static void copy_request(struct sip_request *dst, const struct sip_request *src);
 static void receive_message(struct sip_pvt *p, struct sip_request *req);
 static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req);
-static int sip_send_mwi_to_peer(struct sip_peer *peer);
-static int does_peer_need_mwi(struct sip_peer *peer);
+static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event);
 
 /*--- Dialog management */
 static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *sin,
@@ -1363,20 +1363,20 @@
 static int expire_register(void *data);
 static void *do_monitor(void *data);
 static int restart_monitor(void);
-static int sip_send_mwi_to_peer(struct sip_peer *peer);
 static void sip_destroy(struct sip_pvt *p);
 static int sip_addrcmp(char *name, struct sockaddr_in *sin);	/* Support for peer matching */
 static int sip_refer_allocate(struct sip_pvt *p);
 static void ast_quiet_chan(struct ast_channel *chan);
 static int attempt_transfer(struct sip_dual *transferer, struct sip_dual *target);
 
-/*--- Device monitoring and Device/extension state handling */
+/*--- Device monitoring and Device/extension state/event handling */
 static int cb_extensionstate(char *context, char* exten, int state, void *data);
 static int sip_devicestate(void *data);
 static int sip_poke_noanswer(void *data);
 static int sip_poke_peer(struct sip_peer *peer);
 static void sip_poke_all_peers(void);
 static void sip_peer_hold(struct sip_pvt *p, int hold);
+static void mwi_event_cb(const struct ast_event *);
 
 /*--- Applications, functions, CLI and manager command helpers */
 static const char *sip_nat_mode(const struct sip_pvt *p);
@@ -3194,6 +3194,9 @@
 	/* Remove link from peer to subscription of MWI */
 	if (p->relatedpeer && p->relatedpeer->mwipvt) 
 		p->relatedpeer->mwipvt = NULL;
+
+	if (p->mwi_event_sub)
+		ast_event_unsubscribe(p->mwi_event_sub);
 
 	if (dumphistory)
 		sip_dump_history(p);
@@ -8709,6 +8712,23 @@
 	return;
 }
 
+/*! \brief Receive MWI events that we have subscribed to */
+static void mwi_event_cb(const struct ast_event *event)
+{
+	const char *mailbox;
+
+	mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
+
+	ASTOBJ_CONTAINER_RDLOCK(&peerl);
+	ASTOBJ_CONTAINER_TRAVERSE(&peerl, 1, do {
+		ASTOBJ_RDLOCK(iterator);
+		if (!strcmp(mailbox, iterator->mailbox))
+			sip_send_mwi_to_peer(iterator, event);
+		ASTOBJ_UNLOCK(iterator);
+	} while (0) );
+	ASTOBJ_CONTAINER_UNLOCK(&peerl);
+}
+
 /*! \brief Callback for the devicestate notification (SUBSCRIBE) support subsystem
 \note	If you add an "hint" priority to the extension in the dial plan,
 	you will get notifications on device state changes */
@@ -8836,7 +8856,7 @@
 			if (!(res = check_auth(p, req, peer->name, peer->secret, peer->md5secret, SIP_REGISTER, uri, XMIT_UNRELIABLE, ast_test_flag(req, SIP_PKT_IGNORE)))) {
 				sip_cancel_destroy(p);
 
-				/* We have a succesful registration attemp with proper authentication,
+				/* We have a successful registration attempt with proper authentication,
 				   now, update the peer */
 				switch (parse_register_contact(p, peer, req)) {
 				case PARSE_REGISTER_FAILED:
@@ -15084,6 +15104,9 @@
 		}
 
 		p->subscribed = MWI_NOTIFICATION;
+		p->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb,
+			AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, authpeer->mailbox,
+			AST_EVENT_IE_END);
 		if (authpeer->mwipvt && authpeer->mwipvt != p)	/* Destroy old PVT if this is a new one */
 			/* We only allow one subscription per peer */
 			sip_destroy(authpeer->mwipvt);
@@ -15130,7 +15153,7 @@
 			transmit_response(p, "200 OK", req);
 			if (p->relatedpeer) {	/* Send first notification */
 				ASTOBJ_WRLOCK(p->relatedpeer);
-				sip_send_mwi_to_peer(p->relatedpeer);
+				sip_send_mwi_to_peer(p->relatedpeer, NULL);
 				ASTOBJ_UNLOCK(p->relatedpeer);
 			}
 		} else {
@@ -15541,25 +15564,33 @@
 }
 
 /*! \brief Send message waiting indication to alert peer that they've got voicemail */
-static int sip_send_mwi_to_peer(struct sip_peer *peer)
+static int sip_send_mwi_to_peer(struct sip_peer *peer, const struct ast_event *event)
 {
 	/* Called with peerl lock, but releases it */
 	struct sip_pvt *p;
-	int newmsgs, oldmsgs;
-
-	/* Check for messages */
-	ast_app_inboxcount(peer->mailbox, &newmsgs, &oldmsgs);
+	int newmsgs = 0, oldmsgs = 0;
+	struct ast_event *cache_event;
+
+	if (ast_test_flag((&peer->flags[1]), SIP_PAGE2_SUBSCRIBEMWIONLY) && !peer->mwipvt)
+		return 0;
+
+	if (!event) {
+		/* Check the event cache for the mailbox info */
+		event = cache_event = ast_event_get_cached(AST_EVENT_MWI,
+			AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, peer->mailbox,
+			AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+			AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+			AST_EVENT_IE_END);
+	}
+
+	if (event) {
+		newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
+		oldmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS);
+		if (cache_event)
+			ast_event_destroy(cache_event);
+	} else /* Fall back to manually checking the mailbox */
+		ast_app_inboxcount(peer->mailbox, &newmsgs, &oldmsgs);
 	
-	peer->lastmsgcheck = time(NULL);
-	
-	/* Return now if it's the same thing we told them last time */
-	if (((newmsgs > 0x7fff ? 0x7fff0000 : (newmsgs << 16)) | (oldmsgs > 0xffff ? 0xffff : oldmsgs)) == peer->lastmsgssent) {
-		return 0;
-	}
-	
-	
-	peer->lastmsgssent = ((newmsgs > 0x7fff ? 0x7fff0000 : (newmsgs << 16)) | (oldmsgs > 0xffff ? 0xffff : oldmsgs));
-
 	if (peer->mwipvt) {
 		/* Base message on subscription */
 		p = peer->mwipvt;
@@ -15580,29 +15611,13 @@
 		/* Destroy this session after 32 secs */
 		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 	}
+
 	/* Send MWI */
 	ast_set_flag(&p->flags[0], SIP_OUTGOING);
 	transmit_notify_with_mwi(p, newmsgs, oldmsgs, peer->vmexten);
+
 	return 0;
 }
-
-/*! \brief Check whether peer needs a new MWI notification check */
-static int does_peer_need_mwi(struct sip_peer *peer)
-{
-	time_t t = time(NULL);
-
-	if (ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) &&
-	    !peer->mwipvt) {	/* We don't have a subscription */
-		peer->lastmsgcheck = t;	/* Reset timer */
-		return FALSE;
-	}
-
-	if (!ast_strlen_zero(peer->mailbox) && (t - peer->lastmsgcheck) > global_mwitime)
-		return TRUE;
-
-	return FALSE;
-}
-
 
 /*! \brief helper function for the monitoring thread */
 static void check_rtp_timeout(struct sip_pvt *dialog, time_t t)
@@ -15679,11 +15694,7 @@
 {
 	int res;
 	struct sip_pvt *dialog;
-	struct sip_peer *peer = NULL;
 	time_t t;
-	int fastrestart = FALSE;
-	int lastpeernum = -1;
-	int curpeernum;
 	int reloading;
 
 	/* Add an I/O event to our SIP UDP socket */
@@ -15715,7 +15726,7 @@
 		   of time since the last time we did it (when MWI is being sent, we can
 		   get back to this point every millisecond or less)
 		*/
-		for (dialog = dialoglist; !fastrestart && dialog; dialog = dialog->next) {
+		for (dialog = dialoglist; dialog; dialog = dialog->next) {
 			sip_pvt_lock(dialog);
 			/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
 			check_rtp_timeout(dialog, t);
@@ -15737,10 +15748,6 @@
 		res = ast_sched_wait(sched);
 		if ((res < 0) || (res > 1000))
 			res = 1000;
-
-		/* If we might need to send more mailbox notifications, don't wait long at all.*/
-		if (fastrestart)
-			res = 1;
 		res = ast_io_wait(io, res);
 		if (option_debug && res > 20)
 			ast_log(LOG_DEBUG, "chan_sip: ast_io_wait ran %d all at once\n", res);
@@ -15750,37 +15757,11 @@
 			if (option_debug && res >= 20)
 				ast_log(LOG_DEBUG, "chan_sip: ast_sched_runq ran %d all at once\n", res);
 		}
-
-		/* Send MWI notifications to peers - static and cached realtime peers */
-		t = time(NULL);
-		fastrestart = FALSE;
-		curpeernum = 0;
-		peer = NULL;
-		/* Find next peer that needs mwi */
-		ASTOBJ_CONTAINER_TRAVERSE(&peerl, !peer, do {
-			if ((curpeernum > lastpeernum) && does_peer_need_mwi(iterator)) {
-				fastrestart = TRUE;
-				lastpeernum = curpeernum;
-				peer = ASTOBJ_REF(iterator);
-			};
-			curpeernum++;
-		} while (0)
-		);
-		/* Send MWI to the peer */
-		if (peer) {
-			ASTOBJ_WRLOCK(peer);
-			sip_send_mwi_to_peer(peer);
-			ASTOBJ_UNLOCK(peer);
-			unref_peer(peer);
-		} else {
-			/* Reset where we come from */
-			lastpeernum = -1;
-		}
 		ast_mutex_unlock(&monlock);
 	}
+
 	/* Never reached */
 	return NULL;
-	
 }
 
 /*! \brief Start the channel monitor thread */

Modified: team/russell/events/include/asterisk/event.h
URL: http://svn.digium.com/view/asterisk/team/russell/events/include/asterisk/event.h?view=diff&rev=59197&r1=59196&r2=59197
==============================================================================
--- team/russell/events/include/asterisk/event.h (original)
+++ team/russell/events/include/asterisk/event.h Sat Mar 24 00:10:47 2007
@@ -27,11 +27,21 @@
 
 #include "asterisk/event_defs.h"
 
+/*! \brief Check for an event publisher
+ */
+enum ast_event_publisher_res ast_event_check_publisher(enum ast_event_type, ...);
+
+void ast_event_unreg_publisher(struct ast_event_pub *pub);
+
+struct ast_event_pub *ast_event_reg_publisher(enum ast_event_type type, ...);
+
 typedef void (*ast_event_cb_t)(const struct ast_event *);
 
-int ast_event_subscribe(enum ast_event_type, ast_event_cb_t);
+struct ast_event_sub *ast_event_subscribe(enum ast_event_type, ast_event_cb_t, ...);
 
-void ast_event_unsubscribe(enum ast_event_type, ast_event_cb_t);
+void ast_event_unsubscribe(struct ast_event_sub *);
+
+enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type, ...);
 
 struct ast_event *ast_event_new(enum ast_event_type);
 
@@ -58,4 +68,6 @@
 
 const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type);
 
+enum ast_event_type ast_event_get_type(const struct ast_event *event);
+
 #endif /* AST_EVENT_H */

Modified: team/russell/events/include/asterisk/event_defs.h
URL: http://svn.digium.com/view/asterisk/team/russell/events/include/asterisk/event_defs.h?view=diff&rev=59197&r1=59196&r2=59197
==============================================================================
--- team/russell/events/include/asterisk/event_defs.h (original)
+++ team/russell/events/include/asterisk/event_defs.h Sat Mar 24 00:10:47 2007
@@ -28,8 +28,6 @@
 /*! \brief Event types
  * \note These values can *never* change. */
 enum ast_event_type {
-	/*! Used to terminate the arguments to caching functions */
-	AST_EVENT_END = -1,
 	/*! Reserved to provide the ability to subscribe to all events.  A specific
 	    event should never have a payload of 0. */
 	AST_EVENT_ALL    = 0x00,
@@ -46,31 +44,36 @@
 
 /*! \brief Event Information Element types */
 enum ast_event_ie_type {
+	/*! Used to terminate the arguments to caching functions */
+	AST_EVENT_IE_END = -1,
 	/*! Used with AST_EVENT_MWI */
-	AST_EVENT_IE_NEWMSGS,
+	AST_EVENT_IE_NEWMSGS = 0x01,
 	/*! Used with AST_EVENT_MWI */
-	AST_EVENT_IE_OLDMSGS,
+	AST_EVENT_IE_OLDMSGS = 0x02,
 	/*! Used with AST_EVENT_MWI */
-	AST_EVENT_IE_MAILBOX,
+	AST_EVENT_IE_MAILBOX = 0x03,
 };
 
 enum ast_event_ie_pltype {
+	/*! Just check if it exists, not the value */
+	AST_EVENT_IE_PLTYPE_EXISTS,
 	AST_EVENT_IE_PLTYPE_UINT,
 	AST_EVENT_IE_PLTYPE_STR,
 };
 
-struct ast_event_ie {
-	enum ast_event_ie_type ie_type:16;
-	/*! Total length of the IE payload */
-	uint16_t ie_payload_len;
-	unsigned char ie_payload[0];
-} __attribute__ ((packed));
+enum ast_event_subscriber_res {
+	AST_EVENT_SUB_NONE,
+	AST_EVENT_SUB_EXISTS,
+};
 
-struct ast_event {
-	enum ast_event_type type:16;
-	/*! Total length of the event */
-	uint16_t event_len:16;
-	unsigned char payload[0];
-} __attribute__ ((packed));
+enum ast_event_publisher_res {
+	AST_EVENT_PUB_NONE,
+	AST_EVENT_PUB_EXISTS,
+};
+
+struct ast_event;
+struct ast_event_ie;
+struct ast_event_sub;
+struct ast_event_pub;
 
 #endif /* AST_EVENT_DEFS_H */

Modified: team/russell/events/main/event.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/main/event.c?view=diff&rev=59197&r1=59196&r2=59197
==============================================================================
--- team/russell/events/main/event.c (original)
+++ team/russell/events/main/event.c Sat Mar 24 00:10:47 2007
@@ -18,7 +18,7 @@
 
 /*! \file
  *
- * \brief Internal event system
+ * \brief Internal generic event system
  *
  * \author Russell Bryant <russell at digium.com>
  */
@@ -36,6 +36,20 @@
 #include "asterisk/utils.h"
 
 #define NUM_EVENT_THREADS 5
+
+struct ast_event_ie {
+	enum ast_event_ie_type ie_type:16;
+	/*! Total length of the IE payload */
+	uint16_t ie_payload_len;
+	unsigned char ie_payload[0];
+} __attribute__ ((packed));
+
+struct ast_event {
+	enum ast_event_type type:16;
+	/*! Total length of the event */
+	uint16_t event_len:16;
+	unsigned char payload[0];
+} __attribute__ ((packed));
 
 struct ast_event_ref {
 	struct ast_event *event;
@@ -51,15 +65,40 @@
 	.lock = AST_MUTEX_INIT_VALUE,
 };
 
+struct ast_event_ie_val {
+	AST_LIST_ENTRY(ast_event_ie_val) entry;
+	enum ast_event_ie_type ie_type;
+	enum ast_event_ie_pltype ie_pltype;
+	union {
+		uint32_t uint;
+		const char *str;
+	} payload;
+};
+
 /*! \brief Event subscription */
 struct ast_event_sub {
+	enum ast_event_type type;
 	ast_event_cb_t cb;
+	AST_LIST_HEAD_NOLOCK(, ast_event_ie_val) ie_vals;
 	AST_RWLIST_ENTRY(ast_event_sub) entry;
 };
 
 /*! \brief Event subscriptions
  * The event subscribers are indexed by which event they are subscribed to */
 static AST_RWLIST_HEAD(ast_event_sub_list, ast_event_sub) ast_event_subs[AST_EVENT_TOTAL];
+
+/*! \brief Event publisher */
+struct ast_event_pub {
+	enum ast_event_type type;
+	AST_LIST_HEAD_NOLOCK(, ast_event_ie_val) ie_vals;
+	AST_RWLIST_ENTRY(ast_event_pub) entry;
+};
+
+/*! \brief List of event publishers
+ * This is used to be able to know if there is even a chance for a certain
+ * event to occur, with optionally specified parameters to be even more
+ * specific when appropriate. */
+static AST_RWLIST_HEAD(ast_event_pub_list, ast_event_pub) ast_event_pubs[AST_EVENT_TOTAL];
 
 /*! \brief Cached events
  * The event cache is indexed on the event type.  The purpose of this is 
@@ -67,39 +106,280 @@
  * 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];
 
-int ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb)
-{
+enum ast_event_publisher_res ast_event_check_publisher(enum ast_event_type type, ...)
+{
+	va_list ap;
+	enum ast_event_ie_type ie_type;
+	enum ast_event_publisher_res res = AST_EVENT_PUB_NONE;
+	struct ast_event_ie_val *ie_val, *pub_ie_val;
+	struct ast_event_pub *pub;
+	AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val);
+
+	if (type >= AST_EVENT_TOTAL) {
+		ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
+		return res;
+	}
+
+	va_start(ap, type);
+	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 = alloca(sizeof(*ie_val));
+		memset(ie_val, 0, sizeof(*ie_val));
+		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)
+			ie_val->payload.str = ast_strdupa(va_arg(ap, const char *));
+		AST_LIST_INSERT_TAIL(&ie_vals, ie_val, entry);
+	}
+	va_end(ap);
+
+	AST_RWLIST_RDLOCK(&ast_event_pubs[type]);
+	AST_RWLIST_TRAVERSE(&ast_event_pubs[type], pub, entry) {
+		AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) {
+			AST_LIST_TRAVERSE(&pub->ie_vals, pub_ie_val, entry) {
+				if (pub_ie_val->ie_type == ie_val->ie_type)
+					break;
+			}
+			if (!pub_ie_val) {
+				if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS)
+					break;
+				continue;
+			}
+			if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT &&
+				ie_val->payload.uint != pub_ie_val->payload.uint) {
+				break;
+			}
+			if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR &&
+				strcmp(ie_val->payload.str, pub_ie_val->payload.str)) {
+				break;
+			}
+		}
+		if (!ie_val)
+			break;
+	}
+	AST_RWLIST_UNLOCK(&ast_event_pubs[type]);
+
+	if (pub) /* All parameters were matched */
+		return AST_EVENT_PUB_EXISTS;
+
+	AST_RWLIST_RDLOCK(&ast_event_pubs[AST_EVENT_ALL]);
+	if (!AST_RWLIST_EMPTY(&ast_event_pubs[AST_EVENT_ALL]))
+		res = AST_EVENT_PUB_EXISTS;
+	AST_RWLIST_UNLOCK(&ast_event_pubs[AST_EVENT_ALL]);
+
+	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)
+		free((void *) ie_val->payload.str);
+
+	free(ie_val);
+}
+
+static void ast_event_pub_destroy(struct ast_event_pub *pub)
+{
+	struct ast_event_ie_val *ie_val;
+
+	while ((ie_val = AST_LIST_REMOVE_HEAD(&pub->ie_vals, entry)))
+		ast_event_ie_val_destroy(ie_val);
+
+	free(pub);
+}
+
+void ast_event_unreg_publisher(struct ast_event_pub *pub)
+{
+	AST_RWLIST_WRLOCK(&ast_event_pubs[pub->type]);
+	AST_RWLIST_REMOVE(&ast_event_pubs[pub->type], pub, entry);
+	AST_RWLIST_UNLOCK(&ast_event_pubs[pub->type]);
+
+	ast_event_pub_destroy(pub);
+}
+
+struct ast_event_pub *ast_event_reg_publisher(enum ast_event_type type, ...)
+{
+	struct ast_event_pub *pub;
+	va_list ap;
+	enum ast_event_ie_type ie_type;
+
+	if (type >= AST_EVENT_TOTAL) {
+		ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
+		return NULL;
+	}
+
+	if (!(pub = ast_calloc(1, sizeof(*pub))))
+		return NULL;
+
+	pub->type = type;
+
+	va_start(ap, type);
+	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 *)))) {
+				free(ie_val);
+				continue;
+			}
+		}
+		AST_LIST_INSERT_TAIL(&pub->ie_vals, ie_val, entry);
+	}
+	va_end(ap);
+
+	AST_RWLIST_WRLOCK(&ast_event_pubs[type]);
+	AST_LIST_INSERT_TAIL(&ast_event_pubs[type], pub, entry);
+	AST_RWLIST_UNLOCK(&ast_event_pubs[type]);
+
+	return pub;
+}
+
+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_sub *sub;
-
-	if (type >= AST_EVENT_TOTAL)
-		return -1;
+	AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val);
+
+	if (type >= AST_EVENT_TOTAL) {
+		ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
+		return res;
+	}
+
+	va_start(ap, type);
+	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 = alloca(sizeof(*ie_val));
+		memset(ie_val, 0, sizeof(*ie_val));
+		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)
+			ie_val->payload.str = ast_strdupa(va_arg(ap, const char *));
+		AST_LIST_INSERT_TAIL(&ie_vals, ie_val, entry);
+	}
+	va_end(ap);
+
+	AST_RWLIST_RDLOCK(&ast_event_subs[type]);
+	AST_RWLIST_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)
+					break;
+			}
+			if (!sub_ie_val) {
+				if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS)
+					break;
+				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)
+			break;
+	}
+	AST_RWLIST_UNLOCK(&ast_event_subs[type]);
+
+	if (sub) /* All parameters were matched */
+		return AST_EVENT_SUB_EXISTS;
+
+	AST_RWLIST_RDLOCK(&ast_event_subs[AST_EVENT_ALL]);
+	if (!AST_LIST_EMPTY(&ast_event_subs[AST_EVENT_ALL]))
+		res = AST_EVENT_SUB_EXISTS;
+	AST_RWLIST_UNLOCK(&ast_event_subs[AST_EVENT_ALL]);
+
+	return res;
+}
+
+struct ast_event_sub *ast_event_subscribe(enum ast_event_type type, ast_event_cb_t cb, ...)
+{
+	va_list ap;
+	enum ast_event_ie_type ie_type;
+	struct ast_event_sub *sub;
+
+	if (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 -1;
-
+		return NULL;
+
+	va_start(ap, cb);
+	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 *)))) {
+				free(ie_val);
+				continue;
+			}
+		}
+		AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
+	}
+	va_end(ap);
+
+	sub->type = type;
 	sub->cb = cb;
 
 	AST_RWLIST_WRLOCK(&ast_event_subs[type]);
 	AST_RWLIST_INSERT_TAIL(&ast_event_subs[type], sub, entry);
 	AST_RWLIST_UNLOCK(&ast_event_subs[type]);
 
-	return 0;
-}
-
-void ast_event_unsubscribe(enum ast_event_type type, ast_event_cb_t cb)
-{
-	struct ast_event_sub *sub;
-
-	AST_RWLIST_WRLOCK(&ast_event_subs[type]);
-	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_subs[type], sub, entry) {
-		if (sub->cb == cb) {
-			AST_LIST_REMOVE_CURRENT(&ast_event_subs[type], entry);
-			free(sub);
-			break;
-		}
-	}
-	AST_RWLIST_TRAVERSE_SAFE_END
-	AST_RWLIST_UNLOCK(&ast_event_subs[type]);
+	return sub;
+}
+
+static 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);
+
+	free(sub);
+}
+
+void ast_event_unsubscribe(struct ast_event_sub *sub)
+{
+	AST_RWLIST_WRLOCK(&ast_event_subs[sub->type]);
+	AST_LIST_REMOVE(&ast_event_subs[sub->type], sub, entry);
+	AST_RWLIST_UNLOCK(&ast_event_subs[sub->type]);
+
+	ast_event_sub_destroy(sub);
+}
+
+enum ast_event_type ast_event_get_type(const struct ast_event *event)
+{
+	return event->type;
 }
 
 uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
@@ -217,7 +497,7 @@
 	struct cache_arg {
 		AST_LIST_ENTRY(cache_arg) entry;
 		enum ast_event_ie_type ie_type;
-		enum ast_event_ie_pltype pltype;
+		enum ast_event_ie_pltype ie_pltype;
 		union {
 			uint32_t uint;
 			const char *str;
@@ -225,17 +505,23 @@
 	} *cache_arg;
 	AST_LIST_HEAD_NOLOCK_STATIC(cache_args, cache_arg);
 
+	if (type >= AST_EVENT_TOTAL) {
+		ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
+		return NULL;
+	}
+
 	va_start(ap, type);
 	for (ie_type = va_arg(ap, enum ast_event_type);
-		ie_type != AST_EVENT_END;
+		ie_type != AST_EVENT_IE_END;
 		ie_type = va_arg(ap, enum ast_event_type))
 	{
 		cache_arg = alloca(sizeof(*cache_arg));
+		memset(cache_arg, 0, sizeof(*cache_arg));
 		cache_arg->ie_type = ie_type;
-		cache_arg->pltype = va_arg(ap, enum ast_event_ie_pltype);
-		if (cache_arg->pltype == AST_EVENT_IE_PLTYPE_UINT)
+		cache_arg->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
+		if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_UINT)
 			cache_arg->payload.uint = va_arg(ap, uint32_t);
-		else if (cache_arg->pltype == AST_EVENT_IE_PLTYPE_STR)
+		else if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
 			cache_arg->payload.str = ast_strdupa(va_arg(ap, const char *));
 		AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
 	}
@@ -250,13 +536,16 @@
 	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->pltype == AST_EVENT_IE_PLTYPE_UINT &&
+			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->pltype == AST_EVENT_IE_PLTYPE_STR &&
+			   (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)))) ) ) 
+			     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)) ) ) 
 			{
 				break;	
 			}
@@ -301,7 +590,7 @@
 	struct cache_arg {
 		AST_LIST_ENTRY(cache_arg) entry;
 		enum ast_event_ie_type ie_type;
-		enum ast_event_ie_pltype pltype;
+		enum ast_event_ie_pltype ie_pltype;
 	} *cache_arg;
 	AST_LIST_HEAD_NOLOCK_STATIC(cache_args, cache_arg);
 
@@ -314,12 +603,13 @@
 
 	va_start(ap, event);
 	for (ie_type = va_arg(ap, enum ast_event_type);
-		ie_type != AST_EVENT_END;
+		ie_type != AST_EVENT_IE_END;
 		ie_type = va_arg(ap, enum ast_event_type))
 	{
 		cache_arg = alloca(sizeof(*cache_arg));
+		memset(cache_arg, 0, sizeof(*cache_arg));
 		cache_arg->ie_type = ie_type;
-		cache_arg->pltype = va_arg(ap, enum ast_event_ie_pltype);
+		cache_arg->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
 		AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
 	}
 	va_end(ap);
@@ -333,13 +623,16 @@
 	AST_RWLIST_WRLOCK(&ast_event_cache[event->type]);
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[event->type], event_ref, entry) {
 		AST_LIST_TRAVERSE(&cache_args, cache_arg, entry) {
-			if ( ! ( (cache_arg->pltype == AST_EVENT_IE_PLTYPE_UINT &&
+			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->pltype == AST_EVENT_IE_PLTYPE_STR &&
+			   (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)))) ) ) 
+			     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)) ) )
 			{
 				break;	
 			}
@@ -368,6 +661,13 @@
 		return -1;
 	}
 
+	/* If nobody has subscribed to this event type, throw it away now */
+	if (ast_event_check_subscriber(event->type, AST_EVENT_IE_END) 
+		== AST_EVENT_SUB_NONE) {
+		ast_event_destroy(event);
+		return 0;
+	}
+
 	if (!(event_ref = ast_calloc(1, sizeof(*event_ref))))
 		return -1;
 

Modified: team/russell/events/res/res_eventtest.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/res/res_eventtest.c?view=diff&rev=59197&r1=59196&r2=59197
==============================================================================
--- team/russell/events/res/res_eventtest.c (original)
+++ team/russell/events/res/res_eventtest.c Sat Mar 24 00:10:47 2007
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "asterisk/module.h"
 #include "asterisk/event.h"
@@ -42,7 +43,7 @@
 
 static void process_event_generic(const struct ast_event *event)
 {
-	ast_log(LOG_DEBUG, "Event type: %u\n", event->type);
+	ast_log(LOG_DEBUG, "Event type: %u\n", ast_event_get_type(event));
 }
 
 static void process_event_mwi(const struct ast_event *event)
@@ -61,7 +62,7 @@
 
 static void ast_event_process(const struct ast_event *event)
 {
-	switch (event->type) {
+	switch (ast_event_get_type(event)) {
 	case AST_EVENT_MWI:
 		process_event_mwi(event);
 		break;
@@ -73,9 +74,10 @@
 static char *event_gen(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ast_event *event;
-	const char *mailbox = "1234";
+	const char *mailbox = "1234 at fakecontext";
 	unsigned int new = 5;
 	unsigned int old = 12;
+	struct ast_event_sub *event_sub;
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -91,6 +93,9 @@
 	if (a->argc != e->args)
 		return CLI_SHOWUSAGE;
 
+	if (!(event_sub = ast_event_subscribe(AST_EVENT_ALL, ast_event_process, AST_EVENT_IE_END)))
+		return CLI_FAILURE;
+
 	if (!(event = ast_event_new(AST_EVENT_MWI)))
 		return CLI_FAILURE;
 	if (ast_event_append_ie_str(&event, AST_EVENT_IE_MAILBOX, mailbox))
@@ -102,15 +107,75 @@
 
 	ast_event_queue_and_cache(event,
 		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
-		AST_EVENT_END);
+		AST_EVENT_IE_END);
+
+	/* XXX This is a hack.  I should use a timed thread condition instead. */
+	usleep(1000000);
+
+	ast_event_unsubscribe(event_sub);
 
 	return CLI_SUCCESS;
 }
 
+static char *event_test_publisher(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	struct ast_event_pub *pub;
+	const char *mailbox = "1234 at fakecontext";
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "event test publisher";
+		e->usage =
+			"Usage: event test publisher\n"
+			"       Test registering and checking for an event publisher.\n";
+		return NULL;
+
+	case CLI_GENERATE:
+		return NULL;	/* no completion */
+	}
+	if (a->argc != e->args)
+		return CLI_SHOWUSAGE;
+
+	ast_cli(a->fd, "Checking for a publisher that should not exist ...");
+	if (ast_event_check_publisher(AST_EVENT_MWI,
+		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+		AST_EVENT_IE_END) == AST_EVENT_PUB_NONE)
+		ast_cli(a->fd, "Passed!\n");
+	else {
+		ast_cli(a->fd, "Failed!\n");
+		return CLI_FAILURE;
+	}
+
+	if (!(pub = ast_event_reg_publisher(AST_EVENT_MWI,
+		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+		AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+		AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+		AST_EVENT_IE_END))) {
+		ast_cli(a->fd, "Failed to register publisher!\n");
+		return CLI_FAILURE;
+	}
+
+	ast_cli(a->fd, "Checking for a publisher that should exist ...");
+	if (ast_event_check_publisher(AST_EVENT_MWI,
+		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+		AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+		AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+		AST_EVENT_IE_END) == AST_EVENT_PUB_EXISTS)
+		ast_cli(a->fd, "Passed!\n");
+	else {
+		ast_cli(a->fd, "Failed!\n");
+		return CLI_FAILURE;
+	}
+
+	ast_event_unreg_publisher(pub);
+
+	return CLI_SUCCESS;
+}
+
 static char *event_get_cached(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ast_event *event;
-	const char *mailbox = "1234";
+	const char *mailbox = "1234 at fakecontext";
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -128,7 +193,7 @@
 
 	event = ast_event_get_cached(AST_EVENT_MWI,
 		AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
-		AST_EVENT_END);
+		AST_EVENT_IE_END);
 
 	if (!event) {
 		ast_cli(a->fd, "No event retrieved!\n");
@@ -147,24 +212,21 @@
 static struct ast_cli_entry cli_commands[] = {
 	NEW_CLI(event_gen, "Generate a test event"),
 	NEW_CLI(event_get_cached, "Get an event from the cache"),
+	NEW_CLI(event_test_publisher, "Test registering and checking a publisher"),
 };
 
 static int load_module(void)
 {
 	ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
 
-	ast_event_subscribe(AST_EVENT_ALL, ast_event_process);
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+	ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
 
 	return 0;
 }
 
-static int unload_module(void)
-{
-	ast_event_unsubscribe(AST_EVENT_ALL, ast_event_process);
-
-	ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
-
-	return 0;
-}
-
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Test code for the internal event system");



More information about the asterisk-commits mailing list