[asterisk-commits] russell: branch russell/iax_refcount r79626 - in /team/russell/iax_refcount: ...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Aug 15 16:45:55 CDT 2007


Author: russell
Date: Wed Aug 15 16:45:54 2007
New Revision: 79626

URL: http://svn.digium.com/view/asterisk?view=rev&rev=79626
Log:
Convert iax2_peer handling to astobj2

Modified:
    team/russell/iax_refcount/channels/chan_iax2.c
    team/russell/iax_refcount/include/asterisk/strings.h

Modified: team/russell/iax_refcount/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/team/russell/iax_refcount/channels/chan_iax2.c?view=diff&rev=79626&r1=79625&r2=79626
==============================================================================
--- team/russell/iax_refcount/channels/chan_iax2.c (original)
+++ team/russell/iax_refcount/channels/chan_iax2.c Wed Aug 15 16:45:54 2007
@@ -94,6 +94,7 @@
 #include "asterisk/netsock.h"
 #include "asterisk/stringfields.h"
 #include "asterisk/linkedlists.h"
+#include "asterisk/astobj2.h"
 
 #include "iax2.h"
 #include "iax2-parser.h"
@@ -358,10 +359,6 @@
 	int smoothing;					/*!< Sample over how many units to determine historic ms */
 	
 	struct ast_ha *ha;
-
-	unsigned int ref_count;
-
-	AST_LIST_ENTRY(iax2_peer) entry;
 };
 
 #define IAX2_TRUNK_PREFACE (sizeof(struct iax_frame) + sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr))
@@ -637,7 +634,12 @@
 
 static AST_LIST_HEAD_STATIC(users, iax2_user);
 
-static AST_LIST_HEAD_STATIC(peers, iax2_peer);
+#ifdef LOW_MEMORY
+#define MAX_PEER_BUCKETS 17
+#else
+#define MAX_PEER_BUCKETS 563
+#endif
+static ao2_container *peers;
 
 static struct ast_firmware_list {
 	struct iax_firmware *wares;
@@ -678,7 +680,6 @@
 static void reg_source_db(struct iax2_peer *p);
 static struct iax2_peer *realtime_peer(const char *peername, struct sockaddr_in *sin);
 
-static void destroy_peer(struct iax2_peer *peer);
 static int ast_cli_netstats(struct mansession *s, int fd, int limit_fmt);
 
 #define IAX_IOSTATE_IDLE		0
@@ -1045,35 +1046,19 @@
 		return csub;
 }
 
-static void ref_peer(struct iax2_peer *peer)
-{
-	ast_atomic_fetchadd_int((int *) &peer->ref_count, +1);
-}
-
-static struct iax2_peer *unref_peer(struct iax2_peer *peer)
-{
-	unsigned int destroy = 0;
-
-	/* "Realtime" peers marked with the TEMPONLY flag are objects with only a 
-	 * single reference.  Once the reference gets released, destroy it. */
-	if (ast_test_flag(peer, IAX_TEMPONLY)) {
-		destroy_peer(peer);
-		return NULL;
-	}
-
-	AST_LIST_LOCK(&peers);
-	/* If we hold the last reference to this peer and it has been marked for deletion,
-	 * then ensure it has been removed from the peer list and then destroy it. */
-	if (ast_atomic_dec_and_test((int *) &peer->ref_count) && ast_test_flag(peer, IAX_DELME)) {
-		AST_LIST_REMOVE(&peers, peer, entry);
-		destroy = 1;
-	}
-	AST_LIST_UNLOCK(&peers);
-
-	if (destroy)
-		destroy_peer(peer);
-
-	return NULL;
+static int peer_hash_cb(const void *obj, const int flags)
+{
+	const struct iax2_peer *peer = obj;
+
+	return ast_str_hash(peer->name);
+}
+
+static int peer_cmp_cb(void *obj, void *arg, int flags)
+{
+	struct iax2_peer *peer = obj;
+	const char *name = arg;
+
+	return strcasecmp(peer->name, name);
 }
 
 /*!
@@ -1084,19 +1069,12 @@
 {
 	struct iax2_peer *peer = NULL;
 
-	/* Grab peer from linked list */
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE(&peers, peer, entry) {
-		if (!strcasecmp(peer->name, name)) {
-			ref_peer(peer);
-			break;
-		}
-	}
-	AST_LIST_UNLOCK(&peers);
+	peer = ao2_find(peers, (void *) name, OBJ_NODATA);
 
 	/* Now go for realtime if applicable */
 	if(!peer && realtime)
 		peer = realtime_peer(name, NULL);
+
 	return peer;
 }
 
@@ -1104,22 +1082,25 @@
 {
 	struct iax2_peer *peer = NULL;
 	int res = 0;
-
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE(&peers, peer, entry) {
+	ao2_iterator i;
+
+	i = ao2_iterator_init(peers, 0);
+	while ((peer = ao2_iterator_next(&i))) {
 		if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
 		    (peer->addr.sin_port == sin.sin_port)) {
 			ast_copy_string(host, peer->name, len);
+			ao2_ref(peer, -1);
 			res = 1;
 			break;
 		}
-	}
-	AST_LIST_UNLOCK(&peers);
+		ao2_ref(peer, -1);
+	}
+
 	if (!peer) {
 		peer = realtime_peer(NULL, &sin);
 		if (peer) {
 			ast_copy_string(host, peer->name, len);
-			unref_peer(peer);
+			ao2_ref(peer, -1);
 			res = 1;
 		}
 	}
@@ -2017,7 +1998,7 @@
 		} else {
 			ast_cli(fd, "SORRY peer %s is not eligible for this operation.\n", argv[3]);
 		}
-		unref_peer(peer);
+		ao2_ref(peer, -1);
 	} else {
 		ast_cli(fd, "SORRY peer %s was not found in the cache.\n", argv[3]);
 	}
@@ -2144,7 +2125,7 @@
 		ast_cli(fd, "%s\n",status);
 		ast_cli(fd, "  Qualify      : every %dms when OK, every %dms when UNREACHABLE (sample smoothing %s)\n", peer->pokefreqok, peer->pokefreqnotok, peer->smoothing ? "On" : "Off");
 		ast_cli(fd,"\n");
-		unref_peer(peer);
+		ao2_ref(peer, -1);
 	} else {
 		ast_cli(fd,"Peer %s not found.\n", argv[3]);
 		ast_cli(fd,"\n");
@@ -2156,20 +2137,23 @@
 static char *complete_iax2_show_peer(const char *line, const char *word, int pos, int state)
 {
 	int which = 0;
-	struct iax2_peer *p = NULL;
+	struct iax2_peer *peer;
 	char *res = NULL;
 	int wordlen = strlen(word);
+	ao2_iterator i;
 
 	/* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
-	if (pos == 3) {
-		AST_LIST_LOCK(&peers);
-		AST_LIST_TRAVERSE(&peers, p, entry) {
-			if (!strncasecmp(p->name, word, wordlen) && ++which > state) {
-				res = ast_strdup(p->name);
-				break;
-			}
-		}
-		AST_LIST_UNLOCK(&peers);
+	if (pos != 3)
+		return NULL;
+
+	i = ao2_iterator_init(peers, 0);
+	while ((peer = ao2_iterator_next(&i))) {
+		if (!strncasecmp(peer->name, word, wordlen) && ++which > state) {
+			res = ast_strdup(peer->name);
+			ao2_ref(peer, -1);
+			break;
+		}
+		ao2_ref(peer, -1);
 	}
 
 	return res;
@@ -2583,7 +2567,7 @@
 			if (strcasecmp(tmp->value, "friend") &&
 			    strcasecmp(tmp->value, "peer")) {
 				/* Whoops, we weren't supposed to exist! */
-				destroy_peer(peer);
+				ao2_ref(peer, -1);
 				peer = NULL;
 				break;
 			} 
@@ -2611,10 +2595,7 @@
 				ast_sched_del(sched, peer->expire);
 			peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, (void*)peer->name);
 		}
-		peer->ref_count = 1;
-		AST_LIST_LOCK(&peers);
-		AST_LIST_INSERT_HEAD(&peers, peer, entry);
-		AST_LIST_UNLOCK(&peers);
+		ao2_link(peers, peer);
 		if (ast_test_flag(peer, IAX_DYNAMIC))
 			reg_source_db(peer);
 	} else {
@@ -2791,7 +2772,7 @@
 	res = 0;
 
 return_unref:
-	unref_peer(peer);
+	ao2_ref(peer, -1);
 
 	return res;
 }
@@ -3364,18 +3345,20 @@
 	
 static int iax2_getpeertrunk(struct sockaddr_in sin)
 {
-	struct iax2_peer *peer = NULL;
+	struct iax2_peer *peer;
 	int res = 0;
-
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE(&peers, peer, entry) {
+	ao2_iterator i;
+
+	i = ao2_iterator_init(peers, 0);
+	while ((peer = ao2_iterator_next(&i))) {
 		if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
 		    (peer->addr.sin_port == sin.sin_port)) {
 			res = ast_test_flag(peer, IAX_TRUNK);
+			ao2_ref(peer, -1);
 			break;
 		}
-	}
-	AST_LIST_UNLOCK(&peers);
+		ao2_ref(peer, -1);
+	}
 
 	return res;
 }
@@ -4151,6 +4134,7 @@
 	int online_peers = 0;
 	int offline_peers = 0;
 	int unmonitored_peers = 0;
+	ao2_iterator i;
 
 #define FORMAT2 "%-15.15s  %-15.15s %s  %-15.15s  %-8s  %s %-10s%s"
 #define FORMAT "%-15.15s  %-15.15s %s  %-15.15s  %-5d%s  %s %-10s%s"
@@ -4199,8 +4183,9 @@
 	else
 		ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
 
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE(&peers, peer, entry) {
+	i = ao2_iterator_init(peers, 0);
+	for (peer = ao2_iterator_next(&i); peer; 
+		ao2_ref(peer, -1), peer = ao2_iterator_next(&i)) {
 		char nm[20];
 		char status[20];
 		char srch[2000];
@@ -4249,7 +4234,6 @@
 				peer->encmethods ? "(E)" : "   ", status, term);
 		total_peers++;
 	}
-	AST_LIST_UNLOCK(&peers);
 
 	if (s)
 		astman_append(s,"%d iax2 peers [%d online, %d offline, %d unmonitored]%s", total_peers, online_peers, offline_peers, unmonitored_peers, term);
@@ -5190,7 +5174,7 @@
 	res = 0;
 
 return_unref:
-	unref_peer(p);
+	ao2_ref(p, -1);
 
 	return res;
 }
@@ -5279,8 +5263,8 @@
 		/* Normal password authentication */
 		res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
 	} else {
-		AST_LIST_LOCK(&peers);
-		AST_LIST_TRAVERSE(&peers, peer, entry) {
+		ao2_iterator i = ao2_iterator_init(peers, 0);
+		while ((peer = ao2_iterator_next(&i))) {
 			if ((ast_strlen_zero(p->peer) || !strcmp(p->peer, peer->name)) 
 			    /* No peer specified at our end, or this is the peer */
 			    && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
@@ -5289,11 +5273,11 @@
 			    /* No specified host, or this is our host */
 				) {
 				res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
+				ao2_ref(peer, -1);
 				if (!res)
 					break;	
 			}
 		}
-		AST_LIST_UNLOCK(&peers);
 		if (!peer) {
 			/* We checked our list and didn't find one.  It's unlikely, but possible, 
 			   that we're trying to authenticate *to* a realtime peer */
@@ -5302,11 +5286,11 @@
 			if ((peer = realtime_peer(peer_name, NULL))) {
 				ast_mutex_lock(&iaxsl[callno]);
 				if (!(p = iaxs[callno])) {
-					unref_peer(peer);
+					ao2_ref(peer, -1);
 					return -1;
 				}
 				res = authenticate(p->challenge, peer->secret,peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
-				unref_peer(peer);
+				ao2_ref(peer, -1);
 			}
 			if (!peer) {
 				ast_mutex_lock(&iaxsl[callno]);
@@ -5610,43 +5594,33 @@
 static void __expire_registry(void *data)
 {
 	char *name = data;
-	struct iax2_peer *p = NULL;
-
-	/* Go through and grab this peer... and if it needs to be removed... then do it */
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, p, entry) {
-		if (!strcasecmp(p->name, name)) {
-			ref_peer(p);
-			p->expire = -1;
-			break;
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END
-	AST_LIST_UNLOCK(&peers);
-
-	/* Peer is already gone for whatever reason */
-	if (!p)
+	struct iax2_peer *peer = NULL;
+
+	peer = ao2_find(peers, name, OBJ_NODATA);
+	if (!peer)
 		return;
 
-	ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", p->name);
-	if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(p, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
-		realtime_update_peer(p->name, &p->addr, 0);
-	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", p->name);
+	peer->expire = -1;
+
+	ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", peer->name);
+	if (ast_test_flag((&globalflags), IAX_RTUPDATE) && (ast_test_flag(peer, IAX_TEMPONLY|IAX_RTCACHEFRIENDS)))
+		realtime_update_peer(peer->name, &peer->addr, 0);
+	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", peer->name);
 	/* Reset the address */
-	memset(&p->addr, 0, sizeof(p->addr));
+	memset(&peer->addr, 0, sizeof(peer->addr));
 	/* Reset expiry value */
-	p->expiry = min_reg_expire;
-	if (!ast_test_flag(p, IAX_TEMPONLY))
-		ast_db_del("IAX/Registry", p->name);
-	register_peer_exten(p, 0);
-	ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
+	peer->expiry = min_reg_expire;
+	if (!ast_test_flag(peer, IAX_TEMPONLY))
+		ast_db_del("IAX/Registry", peer->name);
+	register_peer_exten(peer, 0);
+	ast_device_state_changed("IAX2/%s", peer->name); /* Activate notification */
 	if (iax2_regfunk)
-		iax2_regfunk(p->name, 0);
-
-	if (ast_test_flag(p, IAX_RTAUTOCLEAR))
-		ast_set_flag(p, IAX_DELME);
+		iax2_regfunk(peer->name, 0);
+
+	if (ast_test_flag(peer, IAX_RTAUTOCLEAR))
+		ao2_unlink(peers, peer);
 	
-	unref_peer(p);
+	ao2_ref(peer, -1);
 }
 
 static int expire_registry(void *data)
@@ -5815,7 +5789,7 @@
 	res = 0;
 
 return_unref:
-	unref_peer(p);
+	ao2_ref(p, -1);
 
 	return res ? res : send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);
 }
@@ -5852,7 +5826,7 @@
 	iax_ie_append_str(&ied, IAX_IE_USERNAME, peer_name);
 
 return_unref:
-	unref_peer(p);
+	ao2_ref(p, -1);
 
 	return res ? res : send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
 }
@@ -8276,6 +8250,15 @@
 	return 0;
 }
 
+static int iax2_poke_peer_cb(void *obj, void *arg, int flags)
+{
+	struct iax2_peer *peer = obj;
+
+	iax2_poke_peer(peer, 0);
+
+	return 0;
+}
+
 static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
 {
 	if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
@@ -8666,7 +8649,31 @@
 	}
 }
 
-		
+static void peer_destructor(void *obj)
+{
+	struct iax2_peer *peer = obj;
+
+	ast_free_ha(peer->ha);
+
+	/* Delete it, it needs to disappear */
+	if (peer->expire > -1)
+		ast_sched_del(sched, peer->expire);
+	if (peer->pokeexpire > -1)
+		ast_sched_del(sched, peer->pokeexpire);
+	if (peer->callno > 0) {
+		ast_mutex_lock(&iaxsl[peer->callno]);
+		iax2_destroy(peer->callno);
+		ast_mutex_unlock(&iaxsl[peer->callno]);
+	}
+
+	register_peer_exten(peer, 0);
+
+	if (peer->dnsmgr)
+		ast_dnsmgr_release(peer->dnsmgr);
+
+	ast_string_field_free_pools(peer);
+}
+
 /*! \brief Create peer structure based on configuration */
 static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int temponly)
 {
@@ -8676,37 +8683,29 @@
 	int found=0;
 	int firstpass=1;
 
-	AST_LIST_LOCK(&peers);
 	if (!temponly) {
-		AST_LIST_TRAVERSE(&peers, peer, entry) {
-			if (!strcmp(peer->name, name)) {	
-				if (!ast_test_flag(peer, IAX_DELME))
-					firstpass = 0;
-				break;
-			}
-		}
-	} else
-		peer = NULL;	
+		peer = ao2_find(peers, (void *) name, OBJ_NODATA);
+		if (!ast_test_flag(peer, IAX_DELME))
+			firstpass = 0;
+	}
+
 	if (peer) {
 		found++;
 		if (firstpass) {
 			oldha = peer->ha;
 			peer->ha = NULL;
 		}
-		AST_LIST_REMOVE(&peers, peer, entry);
-		AST_LIST_UNLOCK(&peers);
- 	} else {
-		AST_LIST_UNLOCK(&peers);
-		if ((peer = ast_calloc(1, sizeof(*peer)))) {
-			peer->expire = -1;
-			peer->pokeexpire = -1;
-			peer->sockfd = defaultsockfd;
-			if (ast_string_field_init(peer, 32)) {
-				free(peer);
-				peer = NULL;
-			}
-		}
-	}
+		ao2_unlink(peers, peer);
+	} else if ((peer = ao2_alloc(sizeof(*peer), peer_destructor))) {
+		peer->expire = -1;
+		peer->pokeexpire = -1;
+		peer->sockfd = defaultsockfd;
+		if (ast_string_field_init(peer, 32)) {
+			ao2_ref(peer, -1);
+			peer = NULL;
+		}
+	}
+
 	if (peer) {
 		if (firstpass) {
 			ast_copy_flags(peer, &globalflags, IAX_USEJITTERBUF | IAX_FORCEJITTERBUF);
@@ -8792,7 +8791,7 @@
 					ast_clear_flag(peer, IAX_DYNAMIC);
 					if (ast_dnsmgr_lookup(v->value, &peer->addr.sin_addr, &peer->dnsmgr)) {
 						ast_string_field_free_pools(peer);
-						free(peer);
+						ao2_ref(peer, -1);
 						return NULL;
 					}
 					if (!peer->addr.sin_port)
@@ -8803,7 +8802,7 @@
 			} else if (!strcasecmp(v->name, "defaultip")) {
 				if (ast_get_ip(&peer->defaddr, v->value)) {
 					ast_string_field_free_pools(peer);
-					free(peer);
+					ao2_ref(peer, -1);
 					return NULL;
 				}
 			} else if (!strcasecmp(v->name, "sourceaddress")) {
@@ -9129,10 +9128,18 @@
 	return user;
 }
 
+static int peer_delme_cb(void *obj, void *arg, int flags)
+{
+	struct iax2_peer *peer = obj;
+
+	ast_set_flag(peer, IAX_DELME);
+
+	return 0;
+}
+
 static void delete_users(void)
 {
 	struct iax2_user *user;
-	struct iax2_peer *peer;
 	struct iax2_registry *reg;
 
 	AST_LIST_LOCK(&users);
@@ -9158,10 +9165,7 @@
 	}
 	AST_LIST_UNLOCK(&registrations);
 
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE(&peers, peer, entry)
-		ast_set_flag(peer, IAX_DELME);
-	AST_LIST_UNLOCK(&peers);
+	ao2_callback(peers, 0, peer_delme_cb, NULL);
 }
 
 static void destroy_user(struct iax2_user *user)
@@ -9192,46 +9196,18 @@
 
 }
 
-static void destroy_peer(struct iax2_peer *peer)
-{
-	ast_free_ha(peer->ha);
-
-	/* Delete it, it needs to disappear */
-	if (peer->expire > -1)
-		ast_sched_del(sched, peer->expire);
-	if (peer->pokeexpire > -1)
-		ast_sched_del(sched, peer->pokeexpire);
-	if (peer->callno > 0) {
-		ast_mutex_lock(&iaxsl[peer->callno]);
-		iax2_destroy(peer->callno);
-		ast_mutex_unlock(&iaxsl[peer->callno]);
-	}
-
-	register_peer_exten(peer, 0);
-
-	if (peer->dnsmgr)
-		ast_dnsmgr_release(peer->dnsmgr);
-
-	ast_string_field_free_pools(peer);
-
-	free(peer);
-}
-
+/* Prune peers who still are supposed to be deleted */
 static void prune_peers(void)
 {
-	/* Prune peers who still are supposed to be deleted */
-	struct iax2_peer *peer = NULL;
-
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, entry) {
-		/* Just remove the peer from the list.  If it is still in the list, then
-		 * someone still has a reference to it.  When they release the reference,
-		 * the peer will get destroyed. */
+	struct iax2_peer *peer;
+	ao2_iterator i;
+
+	i = ao2_iterator_init(peers, 0);
+	while ((peer = ao2_iterator_next(&i))) {
 		if (ast_test_flag(peer, IAX_DELME))
-			AST_LIST_REMOVE_CURRENT(&peers, entry);
-	}
-	AST_LIST_TRAVERSE_SAFE_END
-	AST_LIST_UNLOCK(&peers);
+			ao2_unlink(peers, peer);
+		ao2_ref(peer, -1);
+	}
 }
 
 static void set_timing(void)
@@ -9541,11 +9517,9 @@
 					}
 					peer = build_peer(cat, gen, ast_variable_browse(ucfg, cat), 0);
 					if (peer) {
-						AST_LIST_LOCK(&peers);
-						AST_LIST_INSERT_HEAD(&peers, peer, entry);
-						AST_LIST_UNLOCK(&peers);
 						if (ast_test_flag(peer, IAX_DYNAMIC))
 							reg_source_db(peer);
+						ao2_link(peers, peer);
 					}
 				}
 				if (ast_true(registeriax) || (!registeriax && genregisteriax)) {
@@ -9589,11 +9563,9 @@
 				if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
 					peer = build_peer(cat, ast_variable_browse(cfg, cat), NULL, 0);
 					if (peer) {
-						AST_LIST_LOCK(&peers);
-						AST_LIST_INSERT_HEAD(&peers, peer, entry);
-						AST_LIST_UNLOCK(&peers);
 						if (ast_test_flag(peer, IAX_DYNAMIC))
 							reg_source_db(peer);
+						ao2_link(peers, peer);
 					}
 				} else if (strcasecmp(utype, "user")) {
 					ast_log(LOG_WARNING, "Unknown type '%s' for '%s' in %s\n", utype, cat, config_file);
@@ -9612,7 +9584,6 @@
 {
 	char *config = "iax.conf";
 	struct iax2_registry *reg;
-	struct iax2_peer *peer;
 
 	strcpy(accountcode, "");
 	strcpy(language, "");
@@ -9633,10 +9604,7 @@
 		iax2_do_register(reg);
 	AST_LIST_UNLOCK(&registrations);
 	/* Qualify hosts, too */
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE(&peers, peer, entry)
-		iax2_poke_peer(peer, 0);
-	AST_LIST_UNLOCK(&peers);
+	ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
 	reload_firmware();
 	iax_provision_reload();
 
@@ -10051,7 +10019,7 @@
 		}
 	}
 
-	unref_peer(peer);
+	ao2_ref(peer, -1);
 
 	return 0;
 }
@@ -10112,7 +10080,7 @@
 			res = AST_DEVICE_UNKNOWN;	
 	}
 
-	unref_peer(p);
+	ao2_ref(p, -1);
 
 	return res;
 }
@@ -10425,6 +10393,8 @@
 	for (x = 0; x < IAX_MAX_CALLS; x++)
 		ast_mutex_destroy(&iaxsl[x]);
 
+	ao2_ref(peers, -1);
+
 	return 0;
 }
 
@@ -10434,6 +10404,15 @@
 	return __unload_module();
 }
 
+static int peer_set_sock_cb(void *obj, void *arg, int flags)
+{
+	struct iax2_peer *peer = obj;
+
+	if (peer->sockfd < 0)
+		peer->sockfd = defaultsockfd;
+
+	return 0;
+}
 
 /*! \brief Load IAX2 module, load configuraiton ---*/
 static int load_module(void)
@@ -10442,8 +10421,11 @@
 	int res = 0;
 	int x;
 	struct iax2_registry *reg = NULL;
-	struct iax2_peer *peer = NULL;
-	
+
+	peers = ao2_container_alloc(MAX_PEER_BUCKETS, peer_hash_cb, peer_cmp_cb);
+	if (!peers)
+		return AST_MODULE_LOAD_FAILURE;
+
 	ast_custom_function_register(&iaxpeer_function);
 
 	iax_set_output(iax_debug_output);
@@ -10527,13 +10509,9 @@
 		iax2_do_register(reg);
 	AST_LIST_UNLOCK(&registrations);	
 
-	AST_LIST_LOCK(&peers);
-	AST_LIST_TRAVERSE(&peers, peer, entry) {
-		if (peer->sockfd < 0)
-			peer->sockfd = defaultsockfd;
-		iax2_poke_peer(peer, 0);
-	}
-	AST_LIST_UNLOCK(&peers);
+	ao2_callback(peers, 0, peer_set_sock_cb, NULL);
+	ao2_callback(peers, 0, iax2_poke_peer_cb, NULL);
+
 	reload_firmware();
 	iax_provision_reload();
 	return res;

Modified: team/russell/iax_refcount/include/asterisk/strings.h
URL: http://svn.digium.com/view/asterisk/team/russell/iax_refcount/include/asterisk/strings.h?view=diff&rev=79626&r1=79625&r2=79626
==============================================================================
--- team/russell/iax_refcount/include/asterisk/strings.h (original)
+++ team/russell/iax_refcount/include/asterisk/strings.h Wed Aug 15 16:45:54 2007
@@ -256,4 +256,22 @@
 		(ra)->ptr; \
 	})
 
+/*!
+ * \brief Compute a hash value on a string
+ *
+ * This famous hash algorithm was written by Dan Bernstein and is
+ * commonly used.
+ *
+ * http://www.cse.yorku.ca/~oz/hash.html
+ */
+static force_inline int ast_str_hash(const char *str)
+{
+	int hash = 0;
+
+	while (*str)
+		hash = hash * 33 ^ *str++;
+
+	return hash;
+}
+
 #endif /* _ASTERISK_STRINGS_H */




More information about the asterisk-commits mailing list