[asterisk-commits] russell: branch russell/events r89208 - in /team/russell/events: include/aste...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Nov 12 21:44:37 CST 2007


Author: russell
Date: Mon Nov 12 21:44:36 2007
New Revision: 89208

URL: http://svn.digium.com/view/asterisk?view=rev&rev=89208
Log:
check in my working copy.  This work is still incomplete, but I made some
progress last week on processing events in pbx_dundi to be sent out over
the network ...

Modified:
    team/russell/events/include/asterisk/dundi.h
    team/russell/events/include/asterisk/lock.h
    team/russell/events/pbx/pbx_dundi.c

Modified: team/russell/events/include/asterisk/dundi.h
URL: http://svn.digium.com/view/asterisk/team/russell/events/include/asterisk/dundi.h?view=diff&rev=89208&r1=89207&r2=89208
==============================================================================
--- team/russell/events/include/asterisk/dundi.h (original)
+++ team/russell/events/include/asterisk/dundi.h Mon Nov 12 21:44:36 2007
@@ -50,26 +50,49 @@
 #define DUNDI_FLAG_RETRANS		(1 << 16)	/*!< Applies to dtrans */
 #define DUNDI_FLAG_RESERVED		(1 << 16)	/*!< Applies to strans */
 
-#define DUNDI_PROTO_NONE		0		/*!< No answer yet */
-#define DUNDI_PROTO_IAX			1		/*!< IAX version 2 */
-#define DUNDI_PROTO_SIP			2		/*!< Session Initiation Protocol */
-#define DUNDI_PROTO_H323		3		/*!< ITU H.323 */
-
-#define DUNDI_FLAG_NONEXISTENT		(0)		/*!< Isn't and can't be a valid number */
-#define DUNDI_FLAG_EXISTS		(1 << 0)	/*!< Is a valid number */
-#define DUNDI_FLAG_MATCHMORE		(1 << 1)	/*!< Might be valid if you add more digits */
-#define DUNDI_FLAG_CANMATCH		(1 << 2)	/*!< Might be a match */
-#define DUNDI_FLAG_IGNOREPAT		(1 << 3)	/*!< Keep dialtone */
-#define DUNDI_FLAG_RESIDENTIAL		(1 << 4)	/*!< Destination known to be residential */
-#define DUNDI_FLAG_COMMERCIAL		(1 << 5)	/*!< Destination known to be commercial */
-#define DUNDI_FLAG_MOBILE		(1 << 6)	/*!< Destination known to be cellular/mobile */
-#define DUNDI_FLAG_NOUNSOLICITED	(1 << 7)	/*!< No unsolicited calls of any kind through this route */
-#define DUNDI_FLAG_NOCOMUNSOLICIT	(1 << 8)	/*!< No commercial unsolicited calls through this route */
-
-#define DUNDI_HINT_NONE			(0)
-#define DUNDI_HINT_TTL_EXPIRED		(1 << 0)	/*!< TTL Expired */
-#define DUNDI_HINT_DONT_ASK		(1 << 1)	/*!< Don't ask for anything beginning with data */
-#define DUNDI_HINT_UNAFFECTED		(1 << 2)	/*!< Answer not affected by entity list */
+enum {
+	/*! No answer yet */
+	DUNDI_PROTO_NONE = 0,
+	/*! IAX, version 2 */
+	DUNDI_PROTO_IAX  = 1,
+	/*! SIP - Session Initiation Protocol, RFC 3261 */
+	DUNDI_PROTO_SIP  = 2,
+	/*! ITU H.323 */
+	DUNDI_PROTO_H323 = 3,
+};
+
+enum {
+	/*! Isn't and can't be a valid number */
+	DUNDI_FLAG_NONEXISTENT =    (0),
+	/*! Is a valid number */
+	DUNDI_FLAG_EXISTS =         (1 << 0),
+	/*! Might be valid if you add more digits */
+	DUNDI_FLAG_MATCHMORE =      (1 << 1),
+	/*! Might be a match */
+	DUNDI_FLAG_CANMATCH =       (1 << 2),
+	/*! Keep dialtone */
+	DUNDI_FLAG_IGNOREPAT =      (1 << 3),
+	/*! Destination known to be residential */
+	DUNDI_FLAG_RESIDENTIAL =    (1 << 4),
+	/*! Destination known to be commercial */
+	DUNDI_FLAG_COMMERCIAL =     (1 << 5),
+	/*! Destination known to be cellular/mobile */
+	DUNDI_FLAG_MOBILE =         (1 << 6),
+	/*! No unsolicited calls of any kind through this route */
+	DUNDI_FLAG_NOUNSOLICITED =  (1 << 7),
+	/*! No commercial unsolicited calls through this route */
+	DUNDI_FLAG_NOCOMUNSOLICIT = (1 << 8),
+};
+
+enum {
+	DUNDI_HINT_NONE =        (0),
+	/*! TTL Expired */
+	DUNDI_HINT_TTL_EXPIRED = (1 << 0),
+	/*! Don't ask for anything beginning with data */
+	DUNDI_HINT_DONT_ASK =    (1 << 1),
+	/*! Answer not affected by entity list */
+	DUNDI_HINT_UNAFFECTED =  (1 << 2),
+};
 
 struct dundi_encblock {				/*!< AES-128 encrypted block */
 	unsigned char iv[16];			/*!< Initialization vector of random data */
@@ -89,14 +112,24 @@
 	unsigned char data[0];			/*!< For data for hint */
 } __attribute__ ((__packed__));
 
-#define DUNDI_CAUSE_SUCCESS		0	/*!< Success */
-#define DUNDI_CAUSE_GENERAL		1	/*!< General unspecified failure */
-#define DUNDI_CAUSE_DYNAMIC		2	/*!< Requested entity is dynamic */
-#define DUNDI_CAUSE_NOAUTH		3	/*!< No or improper authorization */
-#define DUNDI_CAUSE_DUPLICATE		4	/*!< Duplicate request */
-#define DUNDI_CAUSE_TTL_EXPIRED		5	/*!< Expired TTL */
-#define DUNDI_CAUSE_NEEDKEY		6	/*!< Need new session key to decode */
-#define DUNDI_CAUSE_BADENCRYPT		7	/*!< Badly encrypted data */
+enum {
+	/*! Success */
+	DUNDI_CAUSE_SUCCESS =     0,
+	/*! General unspecified failure */
+	DUNDI_CAUSE_GENERAL =     1,
+	/*! Requested entity is dynamic */
+	DUNDI_CAUSE_DYNAMIC =     2,
+	/*! No or improper authorization */
+	DUNDI_CAUSE_NOAUTH =      3,
+	/*! Duplicate request */
+	DUNDI_CAUSE_DUPLICATE =   4,
+	/*! Expired TTL */
+	DUNDI_CAUSE_TTL_EXPIRED = 5,
+	/*! Need new session key to decode */
+	DUNDI_CAUSE_NEEDKEY =     6,
+	/*! Badly encrypted data */
+	DUNDI_CAUSE_BADENCRYPT =  7,
+};
 
 struct dundi_cause {			
 	unsigned char causecode;		/*!< Numerical cause (DUNDI_CAUSE_*) */
@@ -110,14 +143,16 @@
 	dundi_eid peereid;
 } __attribute__ ((__packed__));
 
-#define DUNDI_PEER_PRIMARY		(1 << 0)
-#define DUNDI_PEER_SECONDARY		(1 << 1)
-#define DUNDI_PEER_UNAVAILABLE		(1 << 2)
-#define DUNDI_PEER_REGISTERED		(1 << 3)
-#define DUNDI_PEER_MOD_OUTBOUND		(1 << 4)
-#define DUNDI_PEER_MOD_INBOUND		(1 << 5)
-#define DUNDI_PEER_PCMOD_OUTBOUND	(1 << 6)
-#define DUNDI_PEER_PCMOD_INBOUND	(1 << 7)
+enum {
+	DUNDI_PEER_PRIMARY =        (1 << 0),
+	DUNDI_PEER_SECONDARY =      (1 << 1),
+	DUNDI_PEER_UNAVAILABLE =    (1 << 2),
+	DUNDI_PEER_REGISTERED =     (1 << 3),
+	DUNDI_PEER_MOD_OUTBOUND =   (1 << 4),
+	DUNDI_PEER_MOD_INBOUND =    (1 << 5),
+	DUNDI_PEER_PCMOD_OUTBOUND = (1 << 6),
+	DUNDI_PEER_PCMOD_INBOUND =  (1 << 7),
+};
 
 #define DUNDI_COMMAND_FINAL		(0x80)		/*!< Or'd with other flags */
 
@@ -138,6 +173,8 @@
 #define DUNDI_COMMAND_ENCREJ		(14 | 0x40)	/*!< Reject an encrypted message */
 
 #define DUNDI_COMMAND_STATUS		15		/*!< Status command */
+
+#define DUNDI_COMMAND_EVENT			16
 
 /*
  * Remember that some information elements may occur

Modified: team/russell/events/include/asterisk/lock.h
URL: http://svn.digium.com/view/asterisk/team/russell/events/include/asterisk/lock.h?view=diff&rev=89208&r1=89207&r2=89208
==============================================================================
--- team/russell/events/include/asterisk/lock.h (original)
+++ team/russell/events/include/asterisk/lock.h Mon Nov 12 21:44:36 2007
@@ -791,7 +791,7 @@
 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
 #else
-#define AST_RWLOCK_INIT_VALUE NULL
+#define AST_RWLOCK_INIT_VALUE { 0 }
 #endif
 
 #ifdef DEBUG_THREADS

Modified: team/russell/events/pbx/pbx_dundi.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/pbx/pbx_dundi.c?view=diff&rev=89208&r1=89207&r2=89208
==============================================================================
--- team/russell/events/pbx/pbx_dundi.c (original)
+++ team/russell/events/pbx/pbx_dundi.c Mon Nov 12 21:44:36 2007
@@ -140,6 +140,22 @@
 static time_t rotatetime;
 static dundi_eid empty_eid = { { 0, 0, 0, 0, 0, 0 } };
 static int dundi_shutdown = 0;
+
+struct pending_event {
+	struct ast_event *event;
+	struct pub_event_map *pub_event_map;
+	AST_LIST_ENTRY(pending_event) entry;
+};
+
+static struct {
+	pthread_t thread;
+	ast_mutex_t lock;
+	ast_cond_t cond;
+	unsigned int stop:1;
+	AST_LIST_HEAD_NOLOCK(, pending_event) pending_events;
+} event_processor_data = {
+	.thread = AST_PTHREADT_NULL,
+};
 
 struct permission {
 	AST_LIST_ENTRY(permission) list;
@@ -303,6 +319,8 @@
 	struct ast_event_sub *event_sub;
 	/*! This object has been marked to get destroyed */
 	unsigned int delme:1;
+	/*! List of current DUNDi transactions for this event mapping */
+	AST_LIST_HEAD_NOLOCK(, dundi_transaction) transactions;
 };
 
 #define EVENT_MAP_BUCKETS	17
@@ -331,7 +349,7 @@
 	ast_log(LOG_WARNING, "%s", data);
 }
 
-static int has_permission(struct permissionlist *permlist, char *cont)
+static int has_permission(struct permissionlist *permlist, const char *cont)
 {
 	struct permission *perm;
 	int res = 0;
@@ -360,7 +378,7 @@
 	}
 }
 
-static int str2tech(char *str)
+static int str2tech(const char *str)
 {
 	if (!strcasecmp(str, "IAX") || !strcasecmp(str, "IAX2")) 
 		return DUNDI_PROTO_IAX;
@@ -372,13 +390,11 @@
 		return -1;
 }
 
-#if 0
 static struct pub_event_map *ref_pub_event_map(struct pub_event_map *map)
 {
 	ao2_ref(map, +1);
 	return map;
 }
-#endif
 
 static struct pub_event_map *unref_pub_event_map(struct pub_event_map *map)
 {
@@ -502,11 +518,13 @@
 
 	if (!eid)
 		eid = &empty_eid;
-	
+
+	AST_LIST_LOCK(&peers);
 	AST_LIST_TRAVERSE(&peers, cur, list) {
 		if (!dundi_eid_cmp(&cur->eid,eid))
 			break;
 	}
+	AST_LIST_UNLOCK(&peers);
 
 	if (!cur && any_peer)
 		cur = any_peer;
@@ -516,7 +534,6 @@
 
 static void build_iv(unsigned char *iv)
 {
-	/* XXX Would be nice to be more random XXX */
 	unsigned int *fluffy;
 	int x;
 	fluffy = (unsigned int *)(iv);
@@ -2229,8 +2246,151 @@
 	return NULL;
 }
 
+static int check_send_event(struct dundi_peer *peer, struct pub_event_map *pub_event_map,
+	dundi_eid *avoid_eids, size_t avoid_eids_len, int num_eids)
+{
+	int i;
+
+	/* Only send them the event if they are listed as an outbound peer */
+	if (!(peer->model & DUNDI_MODEL_OUTBOUND))
+		return -1;
+
+	/* Make sure this peer is included in the specified DUNDi context */
+	if (!has_permission(&peer->include, pub_event_map->context))
+		return -1;
+
+	/* Not registered ... */
+	if (!peer->addr.sin_addr.s_addr)
+		return -1;
+		
+	/* Check qualify pings */
+	if (peer->maxms && ((peer->lastms < 0) || (peer->lastms >= peer->maxms)))
+		return -1;
+
+	for (i = 0; i < num_eids; i++) {
+		if (!dundi_eid_cmp(avoid_eids + i, &peer->eid))
+			return -1;
+	}
+
+	return 0;
+}
+
+static void build_event_transactions(struct pub_event_map *pub_event_map)
+{
+	struct dundi_peer *peer;
+	dundi_eid avoid_eids[DUNDI_MAX_STACK];
+	int cur_avoid_eid = 0;
+
+	memset(avoid_eids, 0, sizeof(avoid_eids));
+
+	AST_LIST_LOCK(&peers);
+	AST_LIST_TRAVERSE(&peers, peer, list) {
+		struct dundi_transaction *trans;
+		int i;
+
+		/* Make sure we can send an event to this peer for this event mapping */
+		if (check_send_event(peer, pub_event_map, 
+			avoid_eids, ARRAY_LEN(avoid_eids), cur_avoid_eid))
+			continue;
+
+		if (cur_avoid_eid == ARRAY_LEN(avoid_eids)) {
+			ast_log(LOG_ERROR, "Ran out of room for storing which EIDs to ignore\n");
+			break;
+		}
+
+		/* We need to remember which EIDs this event has already been sent to
+		 * and pass that information on with the event to prevent forwarding 
+		 * loops. */
+		avoid_eids[cur_avoid_eid++] = peer->eid;
+
+		trans = create_transaction(peer);
+		if (!trans)
+			continue;
+
+		for (i = 0; i < cur_avoid_eid; i++)
+			trans->eids[i] = avoid_eids[i];
+		trans->eidcount = cur_avoid_eid;
+
+		AST_LIST_INSERT_TAIL(&pub_event_map->transactions, trans, parentlist);
+	}
+	AST_LIST_UNLOCK(&peers);
+}
+
+static void handle_pending_event(struct pending_event *pending_event)
+{
+	build_event_transactions(pending_event->pub_event_map);
+
+	/* XXX \todo  ... */
+}
+
+static struct pending_event *destroy_pending_event(struct pending_event *pending_event)
+{
+	unref_pub_event_map(pending_event->pub_event_map);	
+	free(pending_event);
+	return NULL;
+}
+
+static void *event_processor(void *data)
+{
+	struct pending_event *pending_event;
+
+	while (!event_processor_data.stop) {
+		ast_mutex_lock(&event_processor_data.lock);
+		if (event_processor_data.stop)
+			goto unlock_return;
+		if (!(pending_event = AST_LIST_REMOVE_HEAD(&event_processor_data.pending_events, entry))) {
+			ast_cond_wait(&event_processor_data.cond, &event_processor_data.lock);
+			pending_event = AST_LIST_REMOVE_HEAD(&event_processor_data.pending_events, entry);
+		}
+		ast_mutex_unlock(&event_processor_data.lock);
+
+		if (event_processor_data.stop)
+			break;
+
+		if (!pending_event)
+			continue;
+
+		handle_pending_event(pending_event);
+		pending_event = destroy_pending_event(pending_event);
+	}
+
+	return NULL;
+
+unlock_return:
+	ast_mutex_unlock(&event_processor_data.lock);
+	return NULL;
+}
+
+static void ast_event_cb(const struct ast_event *event, void *data)
+{
+	struct pub_event_map *pub_event_map = data;
+	struct pending_event *pending_event;
+	size_t event_len;
+
+	ast_debug(1, "Got an event to publish to DUNDi context '%s'\n",
+		pub_event_map->context);
+
+	event_len = ast_event_get_size(event);
+
+	if (!(pending_event = ast_calloc(1, sizeof(*pending_event) + event_len)))
+		return;
+	
+	pending_event->event = (struct ast_event *) (pending_event + 1);
+	memcpy(pending_event->event, event, event_len);
+
+	pending_event->pub_event_map = ref_pub_event_map(pub_event_map);
+
+	ast_mutex_lock(&event_processor_data.lock);
+	AST_LIST_INSERT_TAIL(&event_processor_data.pending_events, pending_event, entry);
+	ast_cond_signal(&event_processor_data.cond);
+	ast_mutex_unlock(&event_processor_data.lock);
+}
+
 static int start_network_thread(void)
 {
+	ast_mutex_init(&event_processor_data.lock);
+	ast_cond_init(&event_processor_data.cond, NULL);
+	ast_pthread_create_background(&event_processor_data.thread, NULL, event_processor, NULL);
 	ast_pthread_create_background(&netthreadid, NULL, network_thread, NULL);
 	ast_pthread_create_background(&precachethreadid, NULL, process_precache, NULL);
 	return 0;
@@ -2941,7 +3101,7 @@
 	AST_CLI_DEFINE(dundi_do_precache, "Precache a number in DUNDi"),
 	AST_CLI_DEFINE(dundi_do_lookup, "Lookup a number in DUNDi"),
 	AST_CLI_DEFINE(dundi_do_query, "Query a DUNDi EID"),
-	NEW_CLI(dundi_show_event_mappings, "Show event mappings"),
+	AST_CLI_DEFINE(dundi_show_event_mappings, "Show event mappings"),
 };
 
 static struct dundi_transaction *create_transaction(struct dundi_peer *p)
@@ -2962,14 +3122,21 @@
 		trans->start = ast_tvnow();
 		ast_set_flag(trans, FLAG_STOREHIST);
 	}
+
 	trans->retranstimer = DUNDI_DEFAULT_RETRANS_TIMER;
+
 	trans->autokillid = -1;
+
 	if (p) {
 		apply_peer(trans, p);
 		if (!p->sentfullkey)
 			ast_set_flag(trans, FLAG_SENDFULLKEY);
 	}
+
 	trans->strans = tid;
+
+	trans->ttl = dundi_ttl;
+
 	AST_LIST_INSERT_HEAD(&alltrans, trans, all);
 	
 	return trans;
@@ -4738,8 +4905,14 @@
 
 	i = ao2_iterator_init(pub_event_maps, 0);
 	while ((pub_event_map = ao2_iterator_next(&i))) {
-		if (pub_event_map->delme)
+		if (pub_event_map->delme) {
 			ao2_unlink(pub_event_maps, pub_event_map);
+			if (pub_event_map->event_sub) {
+				pub_event_map->event_sub = ast_event_unsubscribe(pub_event_map->event_sub);
+				unref_pub_event_map(pub_event_map);
+			}
+		}
+
 		pub_event_map = unref_pub_event_map(pub_event_map);
 	}
 }
@@ -4750,34 +4923,7 @@
 
 	ast_variables_destroy(pub_event_map->parameters);
 
-	if (pub_event_map->event_sub)
-		pub_event_map->event_sub = ast_event_unsubscribe(pub_event_map->event_sub);
-
-	ast_string_field_free_all(pub_event_map);
-}
-
-#if 0
-static inline struct pub_event_map *pub_event_map_ref(strut pub_event_map *map)
-{
-	ao2_ref(map, +1);
-	return map;
-}
-#endif
-
-static inline struct pub_event_map *pub_event_map_unref(struct pub_event_map *map)
-{
-	ao2_ref(map, -1);
-	return NULL;
-}
-
-static void ast_event_cb(const struct ast_event *event, void *data)
-{
-	struct pub_event_map *pub_event_map = data;
-
-	ast_debug(1, "Got an event to publish to DUNDi context '%s'\n",
-		pub_event_map->context);
-
-	/*! \todo XXX Send the event out to the network */
+	ast_string_field_free_memory(pub_event_map);
 }
 
 static enum ast_event_type get_event_type(const char *val)
@@ -4901,7 +5047,7 @@
 	pub_event_map->event_type = event_type;
 
 	pub_event_map->event_sub = ast_event_subscribe_new(event_type, ast_event_cb, 
-		pub_event_map);
+		ref_pub_event_map(pub_event_map));
 	if (!pub_event_map->event_sub)
 		goto return_unref;
 
@@ -4938,14 +5084,12 @@
 		goto return_unref;
 	}
 
-	/*! XXX \todo Need to send a SUBSCRIBE out to the network */
-
 	ao2_link(pub_event_maps, pub_event_map);
 
 	return;
 
 return_unref:
-	pub_event_map_unref(pub_event_map);
+	unref_pub_event_map(pub_event_map);
 }
 
 static int set_config(char *config_file, struct sockaddr_in* sin, int reload)
@@ -5066,21 +5210,9 @@
 	}
 	prune_mappings();
 
-	mark_event_mappings();
-	v = ast_variable_browse(cfg, "event_mappings");
-	for (; v; v = v->next) {
-		if (!strcasecmp(v->name, "publish_event"))
-			add_publish_event_mapping(v->value);
-		else {
-			ast_log(LOG_ERROR, "Invalid entry in event_mappings section of dundi.conf: (%s = %s)\n",
-				v->name, v->value);
-		}
-	}
-	prune_event_mappings();
-
 	mark_peers();
-	cat = ast_category_browse(cfg, NULL);
-	while(cat) {
+	cat = NULL;
+	while ((cat = ast_category_browse(cfg, cat))) {
 		if (strcasecmp(cat, "general") && strcasecmp(cat, "mappings") && strcasecmp(cat, "event_mappings")) {
 			/* Entries */
 			if (!dundi_str_to_eid(&testeid, cat))
@@ -5091,9 +5223,20 @@
 			} else
 				ast_log(LOG_NOTICE, "Ignoring invalid EID entry '%s'\n", cat);
 		}
-		cat = ast_category_browse(cfg, cat);
 	}
 	prune_peers();
+
+	mark_event_mappings();
+	v = ast_variable_browse(cfg, "event_mappings");
+	for (; v; v = v->next) {
+		if (!strcasecmp(v->name, "publish_event"))
+			add_publish_event_mapping(v->value);
+		else {
+			ast_log(LOG_ERROR, "Invalid entry in event_mappings section of dundi.conf: (%s = %s)\n",
+				v->name, v->value);
+		}
+	}
+	prune_event_mappings();
 
 	ast_config_destroy(cfg);
 	
@@ -5138,6 +5281,14 @@
 	if (previous_precachethreadid != AST_PTHREADT_NULL) {
 		pthread_kill(previous_precachethreadid, SIGURG);
 		pthread_join(previous_precachethreadid, NULL);
+	}
+
+	if (event_processor_data.thread != AST_PTHREADT_NULL) {
+		ast_mutex_lock(&event_processor_data.lock);
+		event_processor_data.stop = 1;
+		ast_cond_signal(&event_processor_data.cond);
+		ast_mutex_unlock(&event_processor_data.lock);
+		pthread_join(event_processor_data.thread, NULL);
 	}
 
 	ast_cli_unregister_multiple(cli_dundi, ARRAY_LEN(cli_dundi));




More information about the asterisk-commits mailing list