[asterisk-commits] trunk r24422 - /trunk/channels/chan_iax2.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed May 3 09:07:04 MST 2006


Author: file
Date: Wed May  3 11:07:03 2006
New Revision: 24422

URL: http://svn.digium.com/view/asterisk?rev=24422&view=rev
Log:
Update chan_iax2 to use linkedlists.h for users and peers. Modify the way get_from_jb and expire_registry works to get rid of certain crash scenarios. Finally - change the way expire_registry works when realtime autoclear is enabled to be a bit more efficient.

Modified:
    trunk/channels/chan_iax2.c

Modified: trunk/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_iax2.c?rev=24422&r1=24421&r2=24422&view=diff
==============================================================================
--- trunk/channels/chan_iax2.c (original)
+++ trunk/channels/chan_iax2.c Wed May  3 11:07:03 2006
@@ -308,8 +308,8 @@
 	struct ast_codec_pref prefs;
 	struct ast_ha *ha;
 	struct iax2_context *contexts;
-	struct iax2_user *next;
 	struct ast_variable *vars;
+	AST_LIST_ENTRY(iax2_user) entry;
 };
 
 struct iax2_peer {
@@ -357,7 +357,7 @@
 	int smoothing;					/*!< Sample over how many units to determine historic ms */
 	
 	struct ast_ha *ha;
-	struct iax2_peer *next;
+	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))
@@ -628,15 +628,9 @@
 	ast_mutex_t lock;
 } iaxq;
 
-static struct ast_user_list {
-	struct iax2_user *users;
-	ast_mutex_t lock;
-} userl;
-
-static struct ast_peer_list {
-	struct iax2_peer *peers;
-	ast_mutex_t lock;
-} peerl;
+static AST_LIST_HEAD_STATIC(users, iax2_user);
+
+static AST_LIST_HEAD_STATIC(peers, iax2_peer);
 
 static struct ast_firmware_list {
 	struct iax_firmware *wares;
@@ -1009,14 +1003,18 @@
 
 static struct iax2_peer *find_peer(const char *name, int realtime) 
 {
-	struct iax2_peer *peer;
-	ast_mutex_lock(&peerl.lock);
-	for(peer = peerl.peers; peer; peer = peer->next) {
+	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)) {
 			break;
 		}
 	}
-	ast_mutex_unlock(&peerl.lock);
+	AST_LIST_UNLOCK(&peers);
+
+	/* Now go for realtime if applicable */
 	if(!peer && realtime)
 		peer = realtime_peer(name, NULL);
 	return peer;
@@ -1024,23 +1022,21 @@
 
 static int iax2_getpeername(struct sockaddr_in sin, char *host, int len, int lockpeer)
 {
-	struct iax2_peer *peer;
+	struct iax2_peer *peer = NULL;
 	int res = 0;
 
 	if (lockpeer)
-		ast_mutex_lock(&peerl.lock);
-	peer = peerl.peers;
-	while (peer) {
+		AST_LIST_LOCK(&peers);
+	AST_LIST_TRAVERSE(&peers, peer, entry) {
 		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);
-					res = 1;
-					break;
-		}
-		peer = peer->next;
+		    (peer->addr.sin_port == sin.sin_port)) {
+			ast_copy_string(host, peer->name, len);
+			res = 1;
+			break;
+		}
 	}
 	if (lockpeer)
-		ast_mutex_unlock(&peerl.lock);
+		AST_LIST_UNLOCK(&peers);
 	if (!peer) {
 		peer = realtime_peer(NULL, &sin);
 		if (peer) {
@@ -2134,20 +2130,20 @@
 static char *complete_iax2_show_peer(const char *line, const char *word, int pos, int state)
 {
 	int which = 0;
-	struct iax2_peer *p;
+	struct iax2_peer *p = NULL;
 	char *res = NULL;
 	int wordlen = strlen(word);
 
 	/* 0 - iax2; 1 - show; 2 - peer; 3 - <peername> */
 	if (pos == 3) {
-		ast_mutex_lock(&peerl.lock);
-		for (p = peerl.peers ; p ; p = p->next) {
+		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_mutex_unlock(&peerl.lock);
+		AST_LIST_UNLOCK(&peers);
 	}
 
 	return res;
@@ -2304,66 +2300,75 @@
 #ifdef NEWJB
 static int get_from_jb(void *p);
 
-static void update_jbsched(struct chan_iax2_pvt *pvt) {
-    int when;
-
-    when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
-
-    /*    fprintf(stderr, "now = %d, next=%d\n", when, jb_next(pvt->jb)); */
-
-    when = jb_next(pvt->jb) - when;
-    /*   fprintf(stderr, "when = %d\n", when); */
-
-    if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
-
-    if(when <= 0) {
-      /* XXX should really just empty until when > 0.. */
-      when = 1;
-    }
-
-    pvt->jbid = ast_sched_add(sched, when, get_from_jb, (void *)pvt);
-
-    /* Signal scheduler thread */
-    signal_condition(&sched_lock, &sched_cond);
+static void update_jbsched(struct chan_iax2_pvt *pvt)
+{
+	int when;
+	
+	when = ast_tvdiff_ms(ast_tvnow(), pvt->rxcore);
+	
+	/*    fprintf(stderr, "now = %d, next=%d\n", when, jb_next(pvt->jb)); */
+	
+	when = jb_next(pvt->jb) - when;
+	/*   fprintf(stderr, "when = %d\n", when); */
+	
+	if(pvt->jbid > -1) ast_sched_del(sched, pvt->jbid);
+	
+	if(when <= 0) {
+		/* XXX should really just empty until when > 0.. */
+		when = 1;
+	}
+	
+	pvt->jbid = ast_sched_add(sched, when, get_from_jb, CALLNO_TO_PTR(pvt->callno));
+	
+	/* Signal scheduler thread */
+	signal_condition(&sched_lock, &sched_cond);
 }
 
 static void __get_from_jb(void *p) 
 {
-	/* make sure pvt is valid! */	
-    struct chan_iax2_pvt *pvt = p;
-    struct iax_frame *fr;
-    jb_frame frame;
-    int ret;
-    long now;
-    long next;
-    struct timeval tv;
-
-    ast_mutex_lock(&iaxsl[pvt->callno]);
-    /*  fprintf(stderr, "get_from_jb called\n"); */
-    pvt->jbid = -1;
-
-    gettimeofday(&tv,NULL);
-    /* round up a millisecond since ast_sched_runq does; */
-    /* prevents us from spinning while waiting for our now */
-    /* to catch up with runq's now */
-    tv.tv_usec += 1000;
-
-    now = ast_tvdiff_ms(tv, pvt->rxcore);
-
-    if(now >= (next = jb_next(pvt->jb))) {
+	int callno = PTR_TO_CALLNO(p);
+	struct chan_iax2_pvt *pvt = iaxs[callno];
+	struct iax_frame *fr;
+	jb_frame frame;
+	int ret;
+	long now;
+	long next;
+	struct timeval tv;
+	
+	/* Make sure we have a valid private structure before going on */
+	ast_mutex_lock(&iaxsl[callno]);
+	pvt = iaxs[callno];
+	if (!pvt) {
+		/* No go! */
+		ast_mutex_unlock(&iaxsl[callno]);
+		return;
+	}
+
+	/*  fprintf(stderr, "get_from_jb called\n"); */
+	pvt->jbid = -1;
+	
+	gettimeofday(&tv,NULL);
+	/* round up a millisecond since ast_sched_runq does; */
+	/* prevents us from spinning while waiting for our now */
+	/* to catch up with runq's now */
+	tv.tv_usec += 1000;
+	
+	now = ast_tvdiff_ms(tv, pvt->rxcore);
+	
+	if(now >= (next = jb_next(pvt->jb))) {
 		ret = jb_get(pvt->jb,&frame,now,ast_codec_interp_len(pvt->voiceformat));
 		switch(ret) {
 		case JB_OK:
 			/*if(frame.type == JB_TYPE_VOICE && next + 20 != jb_next(pvt->jb)) fprintf(stderr, "NEXT %ld is not %ld+20!\n", jb_next(pvt->jb), next); */
 			fr = frame.data;
 			__do_deliver(fr);
-		    break;
+			break;
 		case JB_INTERP:
-		    {
+		{
 			struct ast_frame af;
-	
+			
 			/*if(next + 20 != jb_next(pvt->jb)) fprintf(stderr, "NEXT %ld is not %ld+20!\n", jb_next(pvt->jb), next); */
-	
+			
 			/* create an interpolation frame */
 			/*fprintf(stderr, "Making Interpolation frame\n"); */
 			af.frametype = AST_FRAME_VOICE;
@@ -2375,28 +2380,28 @@
 			af.data  = NULL;
 			af.delivery = ast_tvadd(pvt->rxcore, ast_samp2tv(next, 1000));
 			af.offset=AST_FRIENDLY_OFFSET;
-	
+			
 			/* queue the frame:  For consistency, we would call __do_deliver here, but __do_deliver wants an iax_frame,
 			 * which we'd need to malloc, and then it would free it.  That seems like a drag */
-			if (iaxs[pvt->callno] && !ast_test_flag(iaxs[pvt->callno], IAX_ALREADYGONE))
-				iax2_queue_frame(pvt->callno, &af);
-		    }
-		    break;
+			if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
+				iax2_queue_frame(callno, &af);
+		}
+		break;
 		case JB_DROP:
 			/*if(next != jb_next(pvt->jb)) fprintf(stderr, "NEXT %ld is not next %ld!\n", jb_next(pvt->jb), next); */
 			iax2_frame_free(frame.data);
-		    break;
+			break;
 		case JB_NOFRAME:
 		case JB_EMPTY:
 			/* do nothing */
-		    break;
+			break;
 		default:
 			/* shouldn't happen */
-		    break;
-		}
-    }
-    update_jbsched(pvt);
-    ast_mutex_unlock(&iaxsl[pvt->callno]);
+			break;
+		}
+	}
+	update_jbsched(pvt);
+	ast_mutex_unlock(&iaxsl[callno]);
 }
 
 static int get_from_jb(void *data)
@@ -2803,10 +2808,9 @@
 				ast_sched_del(sched, peer->expire);
 			peer->expire = ast_sched_add(sched, (global_rtautoclear) * 1000, expire_registry, peer);
 		}
-		ast_mutex_lock(&peerl.lock);
-		peer->next = peerl.peers;
-		peerl.peers = peer;
-		ast_mutex_unlock(&peerl.lock);
+		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);
 	} else {
@@ -2861,10 +2865,9 @@
 
 	if (ast_test_flag((&globalflags), IAX_RTCACHEFRIENDS)) {
 		ast_set_flag(user, IAX_RTCACHEFRIENDS);
-		ast_mutex_lock(&userl.lock);
- 		user->next = userl.users;
-		userl.users = user;
-		ast_mutex_unlock(&userl.lock);
+		AST_LIST_LOCK(&users);
+		AST_LIST_INSERT_HEAD(&users, user, entry);
+		AST_LIST_UNLOCK(&users);
 	} else {
 		ast_set_flag(user, IAX_TEMPONLY);	
 	}
@@ -3520,19 +3523,19 @@
 
 static int iax2_getpeertrunk(struct sockaddr_in sin)
 {
-	struct iax2_peer *peer;
+	struct iax2_peer *peer = NULL;
 	int res = 0;
-	ast_mutex_lock(&peerl.lock);
-	peer = peerl.peers;
-	while(peer) {
+
+	AST_LIST_LOCK(&peers);
+	AST_LIST_TRAVERSE(&peers, peer, entry) {
 		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);
-					break;
-		}
-		peer = peer->next;
-	}
-	ast_mutex_unlock(&peerl.lock);
+		    (peer->addr.sin_port == sin.sin_port)) {
+			res = ast_test_flag(peer, IAX_TRUNK);
+			break;
+		}
+	}
+	AST_LIST_UNLOCK(&peers);
+
 	return res;
 }
 
@@ -4270,7 +4273,7 @@
 #define FORMAT "%-15.15s  %-20.20s  %-15.15s  %-15.15s  %-5.5s  %-5.10s\n"
 #define FORMAT2 "%-15.15s  %-20.20s  %-15.15d  %-15.15s  %-5.5s  %-5.10s\n"
 
-	struct iax2_user *user;
+	struct iax2_user *user = NULL;
 	char auth[90];
 	char *pstr = "";
 
@@ -4288,32 +4291,32 @@
 		return RESULT_SHOWUSAGE;
 	}
 
-	ast_mutex_lock(&userl.lock);
 	ast_cli(fd, FORMAT, "Username", "Secret", "Authen", "Def.Context", "A/C","Codec Pref");
-	for(user=userl.users;user;user=user->next) {
+	AST_LIST_LOCK(&users);
+	AST_LIST_TRAVERSE(&users, user, entry) {
 		if (havepattern && regexec(&regexbuf, user->name, 0, NULL, 0))
 			continue;
-
+		
 		if (!ast_strlen_zero(user->secret)) {
   			ast_copy_string(auth,user->secret,sizeof(auth));
 		} else if (!ast_strlen_zero(user->inkeys)) {
   			snprintf(auth, sizeof(auth), "Key: %-15.15s ", user->inkeys);
  		} else
 			ast_copy_string(auth, "-no secret-", sizeof(auth));
-
+		
 		if(ast_test_flag(user,IAX_CODEC_NOCAP))
 			pstr = "REQ Only";
 		else if(ast_test_flag(user,IAX_CODEC_NOPREFS))
 			pstr = "Disabled";
 		else
 			pstr = ast_test_flag(user,IAX_CODEC_USER_FIRST) ? "Caller" : "Host";
-
+		
 		ast_cli(fd, FORMAT2, user->name, auth, user->authmethods, 
-				user->contexts ? user->contexts->context : context,
-				user->ha ? "Yes" : "No", pstr);
-
-	}
-	ast_mutex_unlock(&userl.lock);
+			user->contexts ? user->contexts->context : context,
+			user->ha ? "Yes" : "No", pstr);
+		
+	}
+	AST_LIST_UNLOCK(&users);
 
 	if (havepattern)
 		regfree(&regexbuf);
@@ -4335,7 +4338,7 @@
 #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"
 
-	struct iax2_peer *peer;
+	struct iax2_peer *peer = NULL;
 	char name[256];
 	char iabuf[INET_ADDRSTRLEN];
 	int registeredonly=0;
@@ -4374,12 +4377,14 @@
 		return RESULT_SHOWUSAGE;
 	}
 
-	ast_mutex_lock(&peerl.lock);
+
 	if (s)
 		astman_append(s, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
 	else
 		ast_cli(fd, FORMAT2, "Name/Username", "Host", "   ", "Mask", "Port", "   ", "Status", term);
-	for (peer = peerl.peers;peer;peer = peer->next) {
+
+	AST_LIST_LOCK(&peers);
+	AST_LIST_TRAVERSE(&peers, peer, entry) {
 		char nm[20];
 		char status[20];
 		char srch[2000];
@@ -4404,31 +4409,31 @@
 			unmonitored_peers++;
 		
 		ast_copy_string(nm, ast_inet_ntoa(iabuf, sizeof(iabuf), peer->mask), sizeof(nm));
-
+		
 		snprintf(srch, sizeof(srch), FORMAT, name, 
-					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
-					ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
-					nm,
-					ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
-					peer->encmethods ? "(E)" : "   ", status, term);
-
+			 peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
+			 ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
+			 nm,
+			 ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
+			 peer->encmethods ? "(E)" : "   ", status, term);
+		
 		if (s)
 			astman_append(s, FORMAT, name, 
-					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
-					ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
-					nm,
-					ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
-					peer->encmethods ? "(E)" : "   ", status, term);
+				      peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
+				      ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
+				      nm,
+				      ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
+				      peer->encmethods ? "(E)" : "   ", status, term);
 		else
 			ast_cli(fd, FORMAT, name, 
-					peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
-					ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
-					nm,
-					ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
-					peer->encmethods ? "(E)" : "   ", status, term);
+				peer->addr.sin_addr.s_addr ? ast_inet_ntoa(iabuf, sizeof(iabuf), peer->addr.sin_addr) : "(Unspecified)",
+				ast_test_flag(peer, IAX_DYNAMIC) ? "(D)" : "(S)",
+				nm,
+				ntohs(peer->addr.sin_port), ast_test_flag(peer, IAX_TRUNK) ? "(T)" : "   ",
+				peer->encmethods ? "(E)" : "   ", status, term);
 		total_peers++;
 	}
-	ast_mutex_unlock(&peerl.lock);
+	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);
@@ -4578,13 +4583,14 @@
 {
 #define FORMAT2 "%-20.20s  %-10.10s  %-20.20s %8.8s  %s\n"
 #define FORMAT "%-20.20s  %-10.10s  %-20.20s %8d  %s\n"
-	struct iax2_registry *reg;
+	struct iax2_registry *reg = NULL;
+
 	char host[80];
 	char perceived[80];
 	char iabuf[INET_ADDRSTRLEN];
 	if (argc != 3)
 		return RESULT_SHOWUSAGE;
-	ast_mutex_lock(&peerl.lock);
+	AST_LIST_LOCK(&peers);
 	ast_cli(fd, FORMAT2, "Host", "Username", "Perceived", "Refresh", "State");
 	for (reg = registrations;reg;reg = reg->next) {
 		snprintf(host, sizeof(host), "%s:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), reg->addr.sin_addr), ntohs(reg->addr.sin_port));
@@ -4595,7 +4601,7 @@
 		ast_cli(fd, FORMAT, host, 
 					reg->username, perceived, reg->refresh, regstate2str(reg->regstate));
 	}
-	ast_mutex_unlock(&peerl.lock);
+	AST_LIST_UNLOCK(&peers);
 	return RESULT_SUCCESS;
 #undef FORMAT
 #undef FORMAT2
@@ -4959,7 +4965,7 @@
 	/* Start pessimistic */
 	int res = -1;
 	int version = 2;
-	struct iax2_user *user, *best = NULL;
+	struct iax2_user *user = NULL, *best = NULL;
 	int bestscore = 0;
 	int gotcapability=0;
 	char iabuf[INET_ADDRSTRLEN];
@@ -5014,10 +5020,9 @@
 			ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), version);
 		return res;
 	}
-	ast_mutex_lock(&userl.lock);
 	/* Search the userlist for a compatible entry, and fill in the rest */
-	user = userl.users;
-	while(user) {
+	AST_LIST_LOCK(&users);
+	AST_LIST_TRAVERSE(&users, user, entry) {
 		if ((ast_strlen_zero(iaxs[callno]->username) ||				/* No username specified */
 			!strcmp(iaxs[callno]->username, user->name))	/* Or this username specified */
 			&& ast_apply_ha(user->ha, sin) 	/* Access is permitted from this IP */
@@ -5058,9 +5063,8 @@
 				}
 			}
 		}
-		user = user->next;	
-	}
-	ast_mutex_unlock(&userl.lock);
+	}
+	AST_LIST_UNLOCK(&users);
 	user = best;
 	if (!user && !ast_strlen_zero(iaxs[callno]->username)) {
 		user = realtime_user(iaxs[callno]->username);
@@ -5473,7 +5477,7 @@
 
 static int authenticate_reply(struct chan_iax2_pvt *p, struct sockaddr_in *sin, struct iax_ies *ies, char *override, char *okey)
 {
-	struct iax2_peer *peer;
+	struct iax2_peer *peer = NULL;
 	/* Start pessimistic */
 	int res = -1;
 	int authmethods = 0;
@@ -5497,23 +5501,21 @@
 		/* Normal password authentication */
 		res = authenticate(p->challenge, override, okey, authmethods, &ied, sin, &p->ecx, &p->dcx);
 	} else {
-		ast_mutex_lock(&peerl.lock);
-		peer = peerl.peers;
-		while(peer) {
+		AST_LIST_LOCK(&peers);
+		AST_LIST_TRAVERSE(&peers, peer, entry) {
 			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)))
-			 					/* No username specified in peer rule, or this is the right username */
-			 && (!peer->addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer->addr.sin_addr.s_addr & peer->mask.s_addr)))
-			 					/* No specified host, or this is our host */
-			) {
+			    /* No peer specified at our end, or this is the peer */
+			    && (ast_strlen_zero(peer->username) || (!strcmp(peer->username, p->username)))
+			    /* No username specified in peer rule, or this is the right username */
+			    && (!peer->addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer->addr.sin_addr.s_addr & peer->mask.s_addr)))
+			    /* No specified host, or this is our host */
+				) {
 				res = authenticate(p->challenge, peer->secret, peer->outkey, authmethods, &ied, sin, &p->ecx, &p->dcx);
 				if (!res)
 					break;	
 			}
-			peer = peer->next;
-		}
-		ast_mutex_unlock(&peerl.lock);
+		}
+		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 */
@@ -5830,7 +5832,25 @@
 
 static void __expire_registry(void *data)
 {
-	struct iax2_peer *p = 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)) {
+			/* If we are set to auto clear then remove ourselves */
+			if (ast_test_flag(p, IAX_RTAUTOCLEAR))
+				AST_LIST_REMOVE_CURRENT(&peers, entry);
+			break;
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END
+	AST_LIST_UNLOCK(&peers);
+
+	/* Peer is already gone for whatever reason */
+	if (!p)
+		return;
 
 	ast_log(LOG_DEBUG, "Expiring registration for peer '%s'\n", p->name);
 	manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: IAX2/%s\r\nPeerStatus: Unregistered\r\nCause: Expired\r\n", p->name);
@@ -5846,8 +5866,8 @@
 		iax2_regfunk(p->name, 0);
 
 	if (ast_test_flag(p, IAX_RTAUTOCLEAR)) {
-		ast_set_flag(p, IAX_DELME);
-		prune_peers();
+		/* We are already gone from the list, so we can just destroy ourselves */
+		destroy_peer(p);
 	}
 }
 
@@ -5893,7 +5913,7 @@
 					if (p->expire > -1)
 						ast_sched_del(sched, p->expire);
 					ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
-					p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p);
+					p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
 					if (iax2_regfunk)
 						iax2_regfunk(p->name, 1);
 					register_peer_exten(p, 1);
@@ -5971,7 +5991,7 @@
 		p->expiry = refresh;
 	}
 	if (p->expiry && sin->sin_addr.s_addr)
-		p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p);
+		p->expire = ast_sched_add(sched, (p->expiry + 10) * 1000, expire_registry, (void *)p->name);
 	iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
 	iax_ie_append_int(&ied, IAX_IE_DATETIME, iax2_datetime(p->zonetag));
 	if (sin->sin_addr.s_addr) {
@@ -6289,7 +6309,6 @@
 		res = read(fd, buf, sizeof(buf));
 		if (res < 1) {
 			ast_log(LOG_WARNING, "Unable to read from timing fd\n");
-			ast_mutex_unlock(&peerl.lock);
 			return 1;
 		}
 	}
@@ -6553,7 +6572,7 @@
 		thread->iofd = fd;
 		thread->iores = recvfrom(fd, thread->buf, sizeof(thread->buf), 0,(struct sockaddr *) &thread->iosin, &len);
 		if (thread->iores < 0) {
-			if (errno != ECONNREFUSED)
+			if (errno != ECONNREFUSED && errno != EAGAIN)
 				ast_log(LOG_WARNING, "Error: %s\n", strerror(errno));
 			handle_error();
 			AST_LIST_LOCK(&idle_list);
@@ -8554,21 +8573,17 @@
 /*! \brief Create peer structure based on configuration */
 static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, int temponly)
 {
-	struct iax2_peer *peer;
-	struct iax2_peer *prev;
+	struct iax2_peer *peer = NULL;
 	struct ast_ha *oldha = NULL;
 	int maskfound=0;
 	int found=0;
-	prev = NULL;
-	ast_mutex_lock(&peerl.lock);
+
+	AST_LIST_LOCK(&peers);
 	if (!temponly) {
-		peer = peerl.peers;
-		while(peer) {
+		AST_LIST_TRAVERSE(&peers, peer, entry) {
 			if (!strcmp(peer->name, name)) {	
 				break;
 			}
-			prev = peer;
-			peer = peer->next;
 		}
 	} else
 		peer = NULL;	
@@ -8576,15 +8591,10 @@
 		found++;
 		oldha = peer->ha;
 		peer->ha = NULL;
-		/* Already in the list, remove it and it will be added back (or FREE'd) */
-		if (prev) {
-			prev->next = peer->next;
-		} else {
-			peerl.peers = peer->next;
-		}
-		ast_mutex_unlock(&peerl.lock);
+		AST_LIST_REMOVE(&peers, peer, entry);
+		AST_LIST_UNLOCK(&peers);
  	} else {
-		ast_mutex_unlock(&peerl.lock);
+		AST_LIST_UNLOCK(&peers);
 		if ((peer = ast_calloc(1, sizeof(*peer)))) {
 			peer->expire = -1;
 			peer->pokeexpire = -1;
@@ -8744,7 +8754,7 @@
 /*! \brief Create in-memory user structure from configuration */
 static struct iax2_user *build_user(const char *name, struct ast_variable *v, int temponly)
 {
-	struct iax2_user *prev, *user;
+	struct iax2_user *user = NULL;
 	struct iax2_context *con, *conl = NULL;
 	struct ast_ha *oldha = NULL;
 	struct iax2_context *oldcon = NULL;
@@ -8752,16 +8762,12 @@
 	char *varname = NULL, *varval = NULL;
 	struct ast_variable *tmpvar = NULL;
 	
-	prev = NULL;
-	ast_mutex_lock(&userl.lock);
+	AST_LIST_LOCK(&users);
 	if (!temponly) {
-		user = userl.users;
-		while(user) {
+		AST_LIST_TRAVERSE(&users, user, entry) {
 			if (!strcmp(user->name, name)) {	
 				break;
 			}
-			prev = user;
-			user = user->next;
 		}
 	} else
 		user = NULL;
@@ -8772,14 +8778,10 @@
 		user->ha = NULL;
 		user->contexts = NULL;
 		/* Already in the list, remove it and it will be added back (or FREE'd) */
-		if (prev) {
-			prev->next = user->next;
-		} else {
-			userl.users = user->next;
-		}
-		ast_mutex_unlock(&userl.lock);
+		AST_LIST_REMOVE(&users, user, entry);
+		AST_LIST_UNLOCK(&users);
  	} else {
-		ast_mutex_unlock(&userl.lock);
+		AST_LIST_UNLOCK(&users);
 		/* This is going to memset'd to 0 in the next block */
 		user = ast_malloc(sizeof(*user));
 	}
@@ -8894,16 +8896,15 @@
 
 static void delete_users(void)
 {
-	struct iax2_user *user;
-	struct iax2_peer *peer;
+	struct iax2_user *user = NULL;
+	struct iax2_peer *peer = NULL;
 	struct iax2_registry *reg, *regl;
 
-	ast_mutex_lock(&userl.lock);
-	for (user=userl.users;user;) {
+	AST_LIST_LOCK(&users);
+	AST_LIST_TRAVERSE(&users, user, entry)
 		ast_set_flag(user, IAX_DELME);
-		user = user->next;
-	}
-	ast_mutex_unlock(&userl.lock);
+	AST_LIST_UNLOCK(&users);
+
 	for (reg = registrations;reg;) {
 		regl = reg;
 		reg = reg->next;
@@ -8922,13 +8923,12 @@
 		free(regl);
 	}
 	registrations = NULL;
-	ast_mutex_lock(&peerl.lock);
-	for (peer=peerl.peers;peer;) {
-		/* Assume all will be deleted, and we'll find out for sure later */
+
+	AST_LIST_LOCK(&peers);
+	AST_LIST_TRAVERSE(&peers, peer, entry)
 		ast_set_flag(peer, IAX_DELME);
-		peer = peer->next;
-	}
-	ast_mutex_unlock(&peerl.lock);
+	AST_LIST_UNLOCK(&peers);
+
 }
 
 static void destroy_user(struct iax2_user *user)
@@ -8944,21 +8944,18 @@
 
 static void prune_users(void)
 {
-	struct iax2_user *user, *usernext, *userlast = NULL;
-	ast_mutex_lock(&userl.lock);
-	for (user=userl.users;user;) {
-		usernext = user->next;
+	struct iax2_user *user = NULL;
+
+	AST_LIST_LOCK(&users);
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&users, user, entry) {
 		if (ast_test_flag(user, IAX_DELME)) {
 			destroy_user(user);
-			if (userlast)
-				userlast->next = usernext;
-			else
-				userl.users = usernext;
-		} else
-			userlast = user;
-		user = usernext;
-	}
-	ast_mutex_unlock(&userl.lock);
+			AST_LIST_REMOVE_CURRENT(&users, entry);
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END
+	AST_LIST_UNLOCK(&users);
+
 }
 
 static void destroy_peer(struct iax2_peer *peer)
@@ -8987,22 +8984,17 @@
 
 static void prune_peers(void){
 	/* Prune peers who still are supposed to be deleted */
-	struct iax2_peer *peer, *peerlast, *peernext;
-	ast_mutex_lock(&peerl.lock);
-	peerlast = NULL;
-	for (peer=peerl.peers;peer;) {
-		peernext = peer->next;
+	struct iax2_peer *peer = NULL;
+
+	AST_LIST_LOCK(&peers);
+	AST_LIST_TRAVERSE_SAFE_BEGIN(&peers, peer, entry) {
 		if (ast_test_flag(peer, IAX_DELME)) {
 			destroy_peer(peer);
-			if (peerlast)
-				peerlast->next = peernext;
-			else
-				peerl.peers = peernext;
-		} else
-			peerlast = peer;
-		peer=peernext;
-	}
-	ast_mutex_unlock(&peerl.lock);
+			AST_LIST_REMOVE_CURRENT(&peers, entry);
+		}
+	}
+	AST_LIST_TRAVERSE_SAFE_END
+	AST_LIST_UNLOCK(&peers);
 }
 
 static void set_timing(void)
@@ -9274,19 +9266,17 @@
 				if (!strcasecmp(utype, "user") || !strcasecmp(utype, "friend")) {
 					user = build_user(cat, ast_variable_browse(cfg, cat), 0);
 					if (user) {
-						ast_mutex_lock(&userl.lock);
-						user->next = userl.users;
-						userl.users = user;
-						ast_mutex_unlock(&userl.lock);
+						AST_LIST_LOCK(&users);
+						AST_LIST_INSERT_HEAD(&users, user, entry);
+						AST_LIST_UNLOCK(&users);
 					}
 				}
 				if (!strcasecmp(utype, "peer") || !strcasecmp(utype, "friend")) {
 					peer = build_peer(cat, ast_variable_browse(cfg, cat), 0);
 					if (peer) {
-						ast_mutex_lock(&peerl.lock);
-						peer->next = peerl.peers;
-						peerl.peers = peer;
-						ast_mutex_unlock(&peerl.lock);
+						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);
 					}
@@ -9307,7 +9297,8 @@
 {
 	char *config = "iax.conf";
 	struct iax2_registry *reg;
-	struct iax2_peer *peer;
+	struct iax2_peer *peer = NULL;
+
 	ast_copy_string(accountcode, "", sizeof(accountcode));
 	ast_copy_string(language, "", sizeof(language));
 	amaflags = 0;
@@ -9322,12 +9313,13 @@
 	for (reg = registrations; reg; reg = reg->next)
 		iax2_do_register(reg);
 	/* Qualify hosts, too */
-	ast_mutex_lock(&peerl.lock);
-	for (peer = peerl.peers; peer; peer = peer->next)
+	AST_LIST_LOCK(&peers);
+	AST_LIST_TRAVERSE(&peers, peer, entry)
 		iax2_poke_peer(peer, 0);
-	ast_mutex_unlock(&peerl.lock);
+	AST_LIST_UNLOCK(&peers);
 	reload_firmware();
 	iax_provision_reload();
+
 	return 0;
 }
 
@@ -10035,8 +10027,6 @@
 static int unload_module(void *mod)
 {
 	ast_mutex_destroy(&iaxq.lock);
-	ast_mutex_destroy(&userl.lock);
-	ast_mutex_destroy(&peerl.lock);
 	ast_mutex_destroy(&waresl.lock);
 	ast_custom_function_unregister(&iaxpeer_function);
 	return __unload_module();
@@ -10049,8 +10039,8 @@
 	char *config = "iax.conf";
 	int res = 0;
 	int x;
-	struct iax2_registry *reg;
-	struct iax2_peer *peer;
+	struct iax2_registry *reg = NULL;
+	struct iax2_peer *peer = NULL;
 	
 	ast_custom_function_register(&iaxpeer_function);
 
@@ -10091,8 +10081,6 @@
 	ast_netsock_init(netsock);
 
 	ast_mutex_init(&iaxq.lock);
-	ast_mutex_init(&userl.lock);
-	ast_mutex_init(&peerl.lock);
 	ast_mutex_init(&waresl.lock);
 	
 	ast_cli_register_multiple(iax2_cli, sizeof(iax2_cli) / sizeof(iax2_cli[0]));
@@ -10124,13 +10112,13 @@
 
 	for (reg = registrations; reg; reg = reg->next)
 		iax2_do_register(reg);
-	ast_mutex_lock(&peerl.lock);
-	for (peer = peerl.peers; peer; peer = peer->next) {
+	AST_LIST_LOCK(&peers);
+	AST_LIST_TRAVERSE(&peers, peer, entry) {
 		if (peer->sockfd < 0)
 			peer->sockfd = defaultsockfd;
 		iax2_poke_peer(peer, 0);
 	}
-	ast_mutex_unlock(&peerl.lock);
+	AST_LIST_UNLOCK(&peers);
 	reload_firmware();
 	iax_provision_reload();
 	return res;



More information about the asterisk-commits mailing list