[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