[asterisk-commits] murf: branch murf/bug11210 r90797 - in /team/murf/bug11210: channels/ configs/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Dec 3 22:38:23 CST 2007


Author: murf
Date: Mon Dec  3 22:38:23 2007
New Revision: 90797

URL: http://svn.digium.com/view/asterisk?view=rev&rev=90797
Log:
Another pass over the code. Finishing up the config file additions for hash tab sizes. Tons of debug. A Start at getting the ref counts right.

Modified:
    team/murf/bug11210/channels/chan_sip.c
    team/murf/bug11210/configs/sip.conf.sample

Modified: team/murf/bug11210/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_sip.c?view=diff&rev=90797&r1=90796&r2=90797
==============================================================================
--- team/murf/bug11210/channels/chan_sip.c (original)
+++ team/murf/bug11210/channels/chan_sip.c Mon Dec  3 22:38:23 2007
@@ -1204,11 +1204,13 @@
  */
 static struct sip_pvt *dialog_ref(struct sip_pvt *p)
 {
+	ao2_ref(p,1);
 	return p;
 }
 
 static struct sip_pvt *dialog_unref(struct sip_pvt *p)
 {
+	ao2_ref(p,-1);
 	return NULL;
 }
 
@@ -1610,6 +1612,7 @@
 	in coming releases */
 
 /*--- PBX interface functions */
+static void check_rtp_timeout(struct sip_pvt *dialog, time_t t);
 static struct ast_channel *sip_request_call(const char *type, int format, void *data, int *cause);
 static int sip_devicestate(void *data);
 static int sip_sendtext(struct ast_channel *ast, const char *text);
@@ -1666,7 +1669,9 @@
 static void sip_scheddestroy(struct sip_pvt *p, int ms);
 static void sip_cancel_destroy(struct sip_pvt *p);
 static struct sip_pvt *sip_destroy(struct sip_pvt *p);
-static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist);
+static void *dialog_unlink_all(struct sip_pvt *dialog, int lockowner, int lockdialoglist);
+static void *registry_unref(struct sip_registry *reg);
+static void __sip_destroy(struct sip_pvt *p);
 static void __sip_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod);
 static void __sip_pretend_ack(struct sip_pvt *p);
 static int __sip_semi_ack(struct sip_pvt *p, int seqno, int resp, int sipmethod);
@@ -2022,12 +2027,40 @@
  */
 static void unref_peer(struct sip_peer *peer)
 {
-	ao2_ref(peer,-1);
+	int rc = ao2_ref(peer,-1);
+	ast_log(LOG_NOTICE,"Unref peer %s prev refcount=%d\n", peer->name, rc);
 }
 
 static void unref_user(struct sip_user *user)
 {
-	ao2_ref(user,-1);
+	int rc = ao2_ref(user,-1);
+	ast_log(LOG_NOTICE,"Unref user %s prev refcount=%d\n", user->name, rc);
+}
+
+static void *dialog_unlink_all(struct sip_pvt *dialog, int lockowner, int lockdialoglist)
+{
+	struct sip_pvt *x;
+	int rc = ao2_ref(dialog,0);
+	ast_log(LOG_NOTICE,"Unlink dialog %s prev refcount=%d\n", dialog->callid, rc);
+	/* Remove link from peer to subscription of MWI */
+	if (dialog->relatedpeer && dialog->relatedpeer->mwipvt) 
+		dialog->relatedpeer->mwipvt = dialog_unref(dialog->relatedpeer->mwipvt);
+	if (dialog->registry) {
+		if (dialog->registry->call == dialog)
+			dialog->registry->call = NULL;
+		dialog->registry = registry_unref(dialog->registry);
+	}
+	/* Unlink us from the owner if we have one */
+	if (dialog->owner) {
+		if (lockowner)
+			ast_channel_lock(dialog->owner);
+		ast_debug(1, "Detaching from %s\n", dialog->owner->name);
+		dialog->owner->tech_pvt = NULL;
+		if (lockowner)
+			ast_channel_unlock(dialog->owner);
+	}
+	x = ao2_find(dialogs, dialog, OBJ_POINTER|OBJ_UNLINK);
+	return NULL;
 }
 
 static void *registry_unref(struct sip_registry *reg)
@@ -2596,7 +2629,10 @@
 	} else {
 		append_history(p, "AutoDestroy", "%s", p->callid);
 		ast_debug(3, "Auto destroying SIP dialog '%s'\n", p->callid);
-		sip_destroy(p);		/* Go ahead and destroy dialog. All attempts to recover is done */
+		ast_log(LOG_NOTICE,"AutoDestroy dialog %s\n", p->callid);
+		dialog_unlink_all(p, TRUE, TRUE); /* once it's unlinked and unrefd everywhere, it'll be freed automagically */
+		
+		/* sip_destroy(p); */		/* Go ahead and destroy dialog. All attempts to recover is done */
 		/* sip_destroy also absorbs the reference */
 	}
 	return 0;
@@ -3098,12 +3134,19 @@
 	peer->outboundproxy = NULL;
 
 	/* Delete it, it needs to disappear */
-	if (peer->call)
-		peer->call = sip_destroy(peer->call);
-
-	if (peer->mwipvt) 	/* We have an active subscription, delete it */
-		peer->mwipvt = sip_destroy(peer->mwipvt);
-
+	if (peer->call) {
+		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from peer for %s....\n", peer->call->callid);
+		dialog_unlink_all(peer->call, TRUE, TRUE);
+		/* peer->call = sip_destroy(peer->call); */
+	}
+	
+
+	if (peer->mwipvt) {	/* We have an active subscription, delete it */
+		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from mwipvt for %s....\n", peer->mwipvt->callid);
+		peer->mwipvt = dialog_unlink_all(peer->mwipvt, TRUE, TRUE);
+		/* peer->mwipvt = sip_destroy(peer->mwipvt); */
+	}
+	
 	if (peer->chanvars) {
 		ast_variables_destroy(peer->chanvars);
 		peer->chanvars = NULL;
@@ -3347,18 +3390,16 @@
 static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime)
 {
 	struct sip_peer *p = NULL;
+	int rc;
 	struct sip_peer tmp_peer;
 	
-	ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
-	if (sin) {
+	if (peer)
+	{
+		ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
+		p = ao2_find(peers, &tmp_peer, OBJ_POINTER);
+	} else if (sin) { /* search by addr? */
 		tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr;
 		tmp_peer.addr.sin_port = sin->sin_port;
-	}
-	
-	
-	if (peer)
-		p = ao2_find(peers, &tmp_peer, OBJ_POINTER);
-	else if (sin) { /* search by addr? */
 		ast_log(LOG_NOTICE,"Searching for peer %s by IP addr/port = %d/%d\n", peer, sin->sin_addr.s_addr, sin->sin_port);
 		p = ao2_find(peers_by_ip, &tmp_peer, OBJ_POINTER); /* WAS:  p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */
 	}
@@ -3372,9 +3413,10 @@
 	else if (!p)
 		ast_log(LOG_NOTICE,"Did not find peer %s / addr=%d port=%d\n", peer, sin->sin_addr.s_addr, sin->sin_port);
 
-	if (p)
-		ast_log(LOG_NOTICE,"FOUND peer %s\n", peer);
-		
+	if (p) {
+		rc = ao2_ref(p,0);
+		ast_log(LOG_NOTICE,"FOUND peer %s refcount = %d\n", peer, rc);
+	}
 	return p;
 }
 
@@ -3796,7 +3838,9 @@
 		   we don't get reentered trying to grab the registry lock */
 		reg->call->registry = NULL;
 		ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", reg->username, reg->hostname);
-		reg->call = sip_destroy(reg->call);
+		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from registry for %s....\n", reg->call->callid);
+		reg->call = dialog_unlink_all(reg->call, TRUE, TRUE);
+		/* reg->call = sip_destroy(reg->call); */
 	}
 	if (reg->expire > -1)
 		ast_sched_del(sched, reg->expire);
@@ -3808,12 +3852,13 @@
 	
 }
 
-/*! \brief Execute destruction of SIP dialog structure, release memory */
-static void __sip_destroy(struct sip_pvt *p, int lockowner, int lockdialoglist)
-{
-	struct sip_pvt *cur;
+/*! \brief Execute destruction of SIP dialog structure, release memory:
+     should be unlinked before destruction */
+static void __sip_destroy(struct sip_pvt *p)
+{
 	struct sip_pkt *cp;
 
+	ast_log(LOG_NOTICE,"Destroying the empty shell of dialog %s\n", p->callid);
 	if (sip_debug_test_pvt(p))
 		ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", p->callid, sip_methods[p->method].text);
 
@@ -3821,10 +3866,6 @@
 		update_call_counter(p, DEC_CALL_LIMIT);
 		ast_debug(2, "This call did not properly clean up call limits. Call ID %s\n", p->callid);
 	}
-
-	/* Remove link from peer to subscription of MWI */
-	if (p->relatedpeer && p->relatedpeer->mwipvt) 
-		p->relatedpeer->mwipvt = dialog_unref(p->relatedpeer->mwipvt);
 
 	if (dumphistory)
 		sip_dump_history(p);
@@ -3853,21 +3894,7 @@
 		free_old_route(p->route);
 		p->route = NULL;
 	}
-	if (p->registry) {
-		if (p->registry->call == p)
-			p->registry->call = NULL;
-		p->registry = registry_unref(p->registry);
-	}
-
-	/* Unlink us from the owner if we have one */
-	if (p->owner) {
-		if (lockowner)
-			ast_channel_lock(p->owner);
-		ast_debug(1, "Detaching from %s\n", p->owner->name);
-		p->owner->tech_pvt = NULL;
-		if (lockowner)
-			ast_channel_unlock(p->owner);
-	}
+
 	/* Clear history */
 	if (p->history) {
 		struct sip_history *hist;
@@ -3878,18 +3905,6 @@
 		ast_free(p->history);
 		p->history = NULL;
 	}
-
-	/* Lock dialog list before removing ourselves from the list */
-	if (lockdialoglist)
-		dialoglist_lock();
-	cur = ao2_find(dialogs, p, OBJ_POINTER|OBJ_UNLINK);
-	ast_log(LOG_NOTICE,"Searched for dialog %s, to UNLINK. got %p\n", p->callid, cur);
-	if (lockdialoglist)
-		dialoglist_unlock();
-	if (!cur) {
-		ast_log(LOG_WARNING, "Trying to destroy \"%s\", not found in dialog list?!?! \n", p->callid);
-		return;
-	} 
 
 	/* remove all current packets in this dialog */
 	while((cp = p->packets)) {
@@ -3906,7 +3921,9 @@
 	ast_mutex_destroy(&p->pvt_lock);
 
 	ast_string_field_free_memory(p);
-
+	
+	ast_log(LOG_NOTICE,"Destroying dialog;\n");
+	
 	ast_free(p);
 }
 
@@ -4029,6 +4046,7 @@
 
 static void sip_destroy_fn(void *p)
 {
+	ast_log(LOG_NOTICE,"sip_destroy_fn called\n");
 	sip_destroy(p);
 }
 
@@ -4040,7 +4058,7 @@
 static struct sip_pvt * sip_destroy(struct sip_pvt *p)
 {
 	ast_debug(3, "Destroying SIP dialog %s\n", p->callid);
-	__sip_destroy(p, TRUE, TRUE);
+	__sip_destroy(p);
 	return NULL;
 }
 
@@ -5186,7 +5204,10 @@
 				 int useglobal_nat, const int intended_method)
 {
 	struct sip_pvt *p;
-
+	struct sip_pvt *p2;
+	int rc;
+
+	ast_log(LOG_NOTICE,"allocating PVT for %s\n", callid);
 	if (!(p = ao2_alloc(sizeof(*p), sip_destroy_fn)))
 		return NULL;
 
@@ -5306,9 +5327,16 @@
 	ast_string_field_set(p, context, default_context);
 
 	/* Add to active dialog list */
+
+	ast_log(LOG_NOTICE,"***About to Search for dialog %s\n", p->callid);
+	p2 = ao2_find(dialogs, p, OBJ_POINTER);
+	if (p2) {
+		ast_log(LOG_NOTICE, "ABOUT TO LINK %s, but it is already in the dialog table!\n", p2->callid);
+		ao2_ref(p2,-1);
+	}
 	
 	ao2_link(dialogs, p);
-	ast_log(LOG_NOTICE,"Linked in dialog %s\n", p->callid);
+	rc = ao2_ref(p, 0);
 	
 	ast_debug(1, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : "(No Call-ID)", sip_methods[intended_method].text, p->rtp ? "With RTP" : "No RTP");
 	return p;
@@ -5366,12 +5394,14 @@
 	
 	dialoglist_lock();
 	if (!ast_string_field_init(&tmp_dialog, 100)) {
+		int rc;
 		ast_string_field_set(&tmp_dialog, callid, callid);
 	
 		sip_pvt_ptr = ao2_find(dialogs, &tmp_dialog, OBJ_POINTER);
 		if (sip_pvt_ptr) {
-			ast_log(LOG_NOTICE,"Found dialog %s\n", tmp_dialog.callid);
-			if (!(!pedanticsipchecking || !tag || ast_strlen_zero(p->theirtag) || !strcmp(p->theirtag, tag)))
+			rc = ao2_ref(sip_pvt_ptr,0);
+			ast_log(LOG_NOTICE,"Found CALL dialog %s, refcount = %d\n", tmp_dialog.callid, rc);
+			if (!(!pedanticsipchecking || !tag || ast_strlen_zero(sip_pvt_ptr->theirtag) || !strcmp(sip_pvt_ptr->theirtag, tag)))
 			{
 				ao2_ref(sip_pvt_ptr,-1); /* basically, if the extra pedanticssipchecking constraints don't pan out,
 											the the match is defeated. There should be no other entry that matches
@@ -5382,16 +5412,19 @@
 			if (pedanticsipchecking && sip_pvt_ptr  && req->method != SIP_RESPONSE) {	/* SIP Request */
 				if (sip_pvt_ptr->tag[0] == '\0' && totag[0]) {
 					/* We have no to tag, but they have. Wrong dialog */
+					ao2_ref(sip_pvt_ptr,-1);
 					sip_pvt_ptr = NULL;
 				} else if (totag[0]) {			/* Both have tags, compare them */
 					if (strcmp(totag, sip_pvt_ptr->tag)) {
+						ao2_ref(sip_pvt_ptr,-1);
 						sip_pvt_ptr = NULL;		/* This is not our packet */
 					}
 				}
 				if (!sip_pvt_ptr)
-					ast_debug(5, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag <null> Totag %s Method %s\n", p->callid, totag, sip_methods[req->method].text);
+					ast_debug(5, "= Being pedantic: This is not our match on request: Call ID: %s Ourtag <null> Totag %s Method %s\n", sip_pvt_ptr->callid, totag, sip_methods[req->method].text);
 			}
 		}
+		
 		ast_string_field_free_memory(&tmp_dialog);
 		if (sip_pvt_ptr) {
 			/* Found the call */
@@ -5414,6 +5447,9 @@
 		} else {
 			/* Ok, time to create a new SIP dialog object, a pvt */
 			if ((p = sip_alloc(callid, sin, 1, intended_method)))  {
+				int rc = ao2_ref(p,0);
+				ast_log(LOG_NOTICE,"Couldn't find call %s, so CREATED dialog, refcount = %d\n",
+						callid, rc);
 				/* Ok, we've created a dialog, let's go and process it */
 				sip_pvt_lock(p);
 			} else {
@@ -5491,7 +5527,7 @@
 			return -1;
 		}
 	}
-	if (!(reg = ast_calloc(1,sizeof(*reg)))) {
+	if (!(reg = ast_calloc(1, sizeof(*reg)))) {
 		ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n");
 		return -1;
 	}
@@ -5520,8 +5556,8 @@
 	reg->portno = portnum;
 	reg->callid_valid = FALSE;
 	reg->ocseq = INITIAL_CSEQ;
-	ASTOBJ_CONTAINER_LINK(&regl, reg);/* Add the new registry entry to the list */
-	registry_unref(reg);	/* release the reference. The container has another reference */
+	ASTOBJ_CONTAINER_LINK(&regl, reg); /* Add the new registry entry to the list */
+	registry_unref(reg);	/* release the reference given by ASTOBJ_INIT. The container has another reference */
 	return 0;
 }
 
@@ -8473,7 +8509,9 @@
 		if (create_addr(p, r->hostname)) {
 			/* we have what we hope is a temporary network error,
 			 * probably DNS.  We need to reschedule a registration try */
-			sip_destroy(p);
+			ast_log(LOG_NOTICE,"Calling Sip_Destroy() from registry building for %s....\n", p->callid);
+			dialog_unlink_all(p, TRUE, TRUE);
+			/* sip_destroy(p); */
 			if (r->timeout > -1) {
 				r->timeout = ast_sched_replace(r->timeout, sched, 
 					global_reg_timeout * 1000, sip_reg_timeout, r);
@@ -8842,8 +8880,28 @@
 	    ast_test_flag(&peer->flags[1], SIP_PAGE2_RTAUTOCLEAR)) {
 		struct sip_peer *peer3;
 		peer3 = ao2_find(peers, peer, OBJ_POINTER|OBJ_UNLINK);	/* Remove from peer list */
+		if (peer3) {
+			int rc = ao2_ref(peer3,0);
+			ast_log(LOG_NOTICE,"Peer %s removed from the name hash. Refc=%d\n", peer->name, rc);
+			if (peer3 != peer)
+				ast_log(LOG_WARNING,"Peer (%p) not equal to peer3 (%p); %s != %s;\n",
+						peer, peer3, peer->name, peer3->name);
+			unref_peer(peer);		/* Remove from memory */
+		} else {
+			ast_log(LOG_NOTICE,"Peer %s NOT found in the name hash table!\n", peer->name);
+		}
+		
 		peer3 = ao2_find(peers_by_ip, peer, OBJ_POINTER|OBJ_UNLINK);	/* Remove from peer list */
-		unref_peer(peer);		/* Remove from memory */
+		if (peer3) {
+			int rc = ao2_ref(peer3,0);
+			ast_log(LOG_NOTICE,"Peer %s removed from the IP hash. Refc=%d\n", peer->name, rc);
+			if (peer3 != peer)
+				ast_log(LOG_WARNING,"IP Peer (%p) not equal to peer3 (%p); %s != %s;\n",
+						peer, peer3, peer->name, peer3->name);
+			unref_peer(peer);		/* Remove from memory */
+		} else {
+			ast_log(LOG_NOTICE,"Peer %s NOT found in the IP hash table!\n", peer->name);
+		}
 	}
 
 	return 0;
@@ -9412,7 +9470,8 @@
 
 	/* Request device state update */
 	ast_device_state_changed("SIP/%s", peer->name);
-
+	unref_peer(peer);
+	
 	return;
 }
 
@@ -9896,7 +9955,8 @@
 		sip_pvt_ptr = ao2_find(dialogs, &tmp_dialog, OBJ_POINTER);
 		if (sip_pvt_ptr) {
 			char *ourtag = sip_pvt_ptr->tag;
-			ast_log(LOG_NOTICE,"Found dialog %s\n", sip_pvt_ptr->callid);
+			int rc = ao2_ref(sip_pvt_ptr,0);
+			ast_log(LOG_NOTICE,"Found dialog %s refcount=%d\n", sip_pvt_ptr->callid, rc);
 			/* Go ahead and lock it (and its owner) before returning */
 			sip_pvt_lock(sip_pvt_ptr);
 
@@ -11199,9 +11259,9 @@
 	if (a->argc != 3)
 		return CLI_SHOWUSAGE;
 	ast_cli(a->fd, "-= User objects: %d static, %d realtime =-\n\n", suserobjs, ruserobjs);
-	ao2_callback(users, 0, user_dump_func, &a->fd);
+	ao2_callback(users, OBJ_NODATA, user_dump_func, &a->fd);
 	ast_cli(a->fd, "-= Peer objects: %d static, %d realtime, %d autocreate =-\n\n", speerobjs, rpeerobjs, apeerobjs);
-	ao2_callback(users, 0, peer_dump_func, &a->fd);
+	ao2_callback(users, OBJ_NODATA, peer_dump_func, &a->fd);
 	ast_cli(a->fd, "-= Registry objects: %d =-\n\n", regobjs);
 	ASTOBJ_CONTAINER_DUMP(a->fd, tmp, sizeof(tmp), &regl);
 	return CLI_SUCCESS;
@@ -11275,26 +11335,49 @@
 	}
 }
 
-static int peer_prune_marked_func(void *userobj, void *arg, int flags)
-{
-	struct sip_peer *peer = userobj;
-	if (peer->theMark) {
-		ao2_unlink(peers,peer);
-		ao2_ref(peer,-1);
+/* this func is used with ao2_callback to unlink/delete all dialogs that
+   are marked needdestroy. It will return CMP_MATCH for candidates, and they
+   will be unlinked */
+
+static int dialog_needdestroy(void *dialogobj, void *arg, int flags) 
+{
+	struct sip_pvt *dialog = dialogobj;
+	time_t *t = arg;
+	
+	/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
+	check_rtp_timeout(dialog, *t);
+
+	if (dialog->needdestroy && !dialog->packets && !dialog->owner) {
+		ast_log(LOG_NOTICE, "Dialog %s should be destroyed\n", dialog->callid);
+		return CMP_MATCH;
 	}
 	return 0;
 }
 
-static int user_prune_marked_func(void *userobj, void *arg, int flags)
+/* this func is used with ao2_callback to unlink/delete all marked
+   peers */
+static int peer_is_marked(void *peerobj, void *arg, int flags) 
+{
+	struct sip_peer *peer = peerobj;
+	if (peer->theMark)
+	{
+		return CMP_MATCH;
+	} else {
+		return 0;
+	}
+}
+
+/* this func is used with ao2_callback to unlink/delete all marked
+   users */
+static int user_is_marked(void *userobj, void *arg, int flags)
 {
 	struct sip_user *user = userobj;
 	if (user->theMark) {
-		ao2_unlink(users,user);
-		ao2_ref(user,-1);
-	}
-	return 0;
-}
-
+		return CMP_MATCH;
+	} else {
+		return 0;
+	}
+}
 
 /*! \brief Remove temporary realtime objects from memory (CLI) */
 static char *sip_prune_realtime(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -11395,7 +11478,8 @@
 				}
 			}
 			if (pruned) {
-				ao2_callback(peers, 0, peer_prune_marked_func, 0);
+				ast_log(LOG_NOTICE,"Callback to PRUNE PEERS\n");
+				ao2_callback(peers, OBJ_NODATA|OBJ_UNLINK, peer_is_marked, 0);
 				ast_cli(a->fd, "%d peers pruned.\n", pruned);
 			} else
 				ast_cli(a->fd, "No peers found to prune.\n");
@@ -11416,7 +11500,8 @@
 				}
 			}
 			if (pruned) {
-				ao2_callback(users, 0, user_prune_marked_func, 0);
+				ast_log(LOG_NOTICE,"Callback to PRUNE USERS\n");
+				ao2_callback(users, OBJ_NODATA|OBJ_UNLINK, user_is_marked, 0);
 				ast_cli(a->fd, "%d users pruned.\n", pruned);
 			} else
 				ast_cli(a->fd, "No users found to prune.\n");
@@ -11942,6 +12027,7 @@
 		} else {
 			ast_cli(a->fd, "Peer %s not registered\n", a->argv[2]);
 		}
+		unref_peer(peer);
 	} else {
 		ast_cli(a->fd, "Peer unknown: \'%s\'. Not unregistered.\n", a->argv[2]);
 	}
@@ -12173,14 +12259,14 @@
 	struct sip_pvt *cur = __cur;
 	struct __show_chan_arg *arg = __arg;
 	const struct sockaddr_in *dst = sip_real_dst(cur);
-
-		/* XXX indentation preserved to reduce diff. Will be fixed later */
-		if (cur->subscribed == NONE && !arg->subscriptions) {
-			/* set if SIP transfer in progress */
-			const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
-			char formatbuf[BUFSIZ/2];
-
-			ast_cli(arg->fd, FORMAT, ast_inet_ntoa(dst->sin_addr), 
+	
+	/* XXX indentation preserved to reduce diff. Will be fixed later */
+	if (cur->subscribed == NONE && !arg->subscriptions) {
+		/* set if SIP transfer in progress */
+		const char *referstatus = cur->refer ? referstatus2str(cur->refer->status) : "";
+		char formatbuf[BUFSIZ/2];
+		
+		ast_cli(arg->fd, FORMAT, ast_inet_ntoa(dst->sin_addr), 
 				S_OR(cur->username, S_OR(cur->cid_num, "(None)")),
 				cur->callid, 
 				cur->ocseq, cur->icseq,
@@ -12190,13 +12276,13 @@
 				cur->lastmsg ,
 				referstatus
 			);
-			arg->numchans++;
-		}
-		if (cur->subscribed != NONE && arg->subscriptions) {
-			struct ast_str *mailbox_str = ast_str_alloca(512);
-			if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer)
-				peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer);
-			ast_cli(arg->fd, FORMAT3, ast_inet_ntoa(dst->sin_addr),
+		arg->numchans++;
+	}
+	if (cur->subscribed != NONE && arg->subscriptions) {
+		struct ast_str *mailbox_str = ast_str_alloca(512);
+		if (cur->subscribed == MWI_NOTIFICATION && cur->relatedpeer)
+			peer_mailboxes_to_str(&mailbox_str, cur->relatedpeer);
+		ast_cli(arg->fd, FORMAT3, ast_inet_ntoa(dst->sin_addr),
 				S_OR(cur->username, S_OR(cur->cid_num, "(None)")), 
 			   	cur->callid,
 				/* the 'complete' exten/context is hidden in the refer_to field for subscriptions */
@@ -12204,10 +12290,9 @@
 				cur->subscribed == MWI_NOTIFICATION ? "<none>" : ast_extension_state2str(cur->laststate), 
 				subscription_type2str(cur->subscribed),
 				cur->subscribed == MWI_NOTIFICATION ? S_OR(mailbox_str->str, "<none>") : "<none>"
-				);
-			arg->numchans++;
-		}
-
+			);
+		arg->numchans++;
+	}
 	return 0;	/* don't care, we scan all channels */
 }
 
@@ -12241,7 +12326,7 @@
 		ast_cli(arg.fd, FORMAT3, "Peer", "User", "Call ID", "Extension", "Last state", "Type", "Mailbox");
 
 	/* iterate on the container and invoke the callback on each item */
-	ao2_callback(dialogs, 0, show_channels_cb, &arg);
+	ao2_callback(dialogs, OBJ_NODATA, show_channels_cb, &arg);
 	
 	/* print summary information */
 	ast_cli(arg.fd, "%d active SIP %s%s\n", arg.numchans,
@@ -12905,7 +12990,9 @@
 
 		if (create_addr(p, a->argv[i])) {
 			/* Maybe they're not registered, etc. */
-			sip_destroy(p);
+			ast_log(LOG_NOTICE,"Calling Sip_Destroy() from sip_notify for %s....\n", p->callid);
+			dialog_unlink_all(p, TRUE, TRUE);
+			/* sip_destroy(p); */
 			ast_cli(a->fd, "Could not create address for '%s'\n", a->argv[i]);
 			continue;
 		}
@@ -15624,6 +15711,8 @@
 		transferer->refer->status = REFER_FAILED;
 		sip_pvt_unlock(targetcall_pvt);
 		ast_channel_unlock(current->chan1);
+		if (targetcall_pvt)
+			ao2_ref(targetcall_pvt,-1);
 		return -1;
 	}
 
@@ -15684,6 +15773,8 @@
 			ast_channel_unlock(targetcall_pvt->owner);
 		}
 	}
+	if (targetcall_pvt)
+		ao2_ref(targetcall_pvt,-1);
 	return 1;
 }
 
@@ -16448,11 +16539,14 @@
 		if (ast_test_flag(&authpeer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY)) {
 			add_peer_mwi_subs(authpeer);
 		}
-		if (authpeer->mwipvt && authpeer->mwipvt != p)	/* Destroy old PVT if this is a new one */
+		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);
-		authpeer->mwipvt = p;		/* Link from peer to pvt */
-		p->relatedpeer = authpeer;	/* Link from pvt to peer */
+			ast_log(LOG_NOTICE,"Calling Sip_Destroy() from subscribe request for %s....\n", authpeer->mwipvt->callid);
+			dialog_unlink_all(authpeer->mwipvt, TRUE, TRUE);
+			/* sip_destroy(authpeer->mwipvt); */
+		}
+		authpeer->mwipvt = p;		/* Link from peer to pvt UH- should this be dialog_ref()? */
+		p->relatedpeer = authpeer;	/* Link from pvt to peer UH- should this be dialog_ref()? */
 		/* Do not release authpeer here */
 	} else { /* At this point, Asterisk does not understand the specified event */
 		transmit_response(p, "489 Bad Event", req);
@@ -16884,6 +16978,8 @@
 			break;	/* locking succeeded */
 		ast_debug(1, "Failed to grab owner channel lock, trying again. (SIP call %s)\n", p->callid);
 		sip_pvt_unlock(p);
+		if (lockretry != 1)
+			ao2_ref(p,-1); /* we'll look for it again, but p is dead now */
 		ast_mutex_unlock(&netlock);
 		/* Sleep for a very short amount of time */
 		usleep(1);
@@ -16901,6 +16997,7 @@
 			transmit_response(p, "503 Server error", &req);	/* We must respond according to RFC 3261 sec 12.2 */
 		/* XXX We could add retry-after to make sure they come back */
 		append_history(p, "LockFail", "Owner lock failed, transaction failed.");
+		ao2_ref(p, -1); /* p is gone after the return */
 		return 1;
 	}
 	nounlock = 0;
@@ -16915,7 +17012,7 @@
 	ast_mutex_unlock(&netlock);
 	if (recount)
 		ast_update_use_count();
-
+	ao2_ref(p, -1); /* p is gone after the return */
 	return 1;
 }
 
@@ -16982,7 +17079,9 @@
 			return -1;
 		if (create_addr_from_peer(p, peer)) {
 			/* Maybe they're not registered, etc. */
-			sip_destroy(p);
+			ast_log(LOG_NOTICE,"Calling Sip_Destroy() from peer mwi for %s....\n", p->callid);
+			dialog_unlink_all(p, TRUE, TRUE);
+			/* sip_destroy(p); */
 			return 0;
 		}
 		/* Recalculate our side, and recalculate Call ID */
@@ -17075,10 +17174,8 @@
 static void *do_monitor(void *data)
 {
 	int res;
-	struct sip_pvt *dialog;
 	time_t t;
 	int reloading;
-	struct ao2_iterator i;
 
 	/* Add an I/O event to our SIP UDP socket */
 	if (sipsock > -1) 
@@ -17106,31 +17203,13 @@
 
 		/* Check for dialogs needing to be killed */
 
-		dialoglist_lock();
-restartsearch:		
 		t = time(NULL);
 		/* don't scan the dialogs list if it hasn't been a reasonable period
 		   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)
 		*/
 
-		i = ao2_iterator_init(dialogs, 0);
-
-		while ((dialog = ao2_iterator_next(&i))) {
-			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);
-			/* If we have sessions that needs to be destroyed, do it now */
-			/* Check if we have outstanding requests not responsed to or an active call
-				- if that's the case, wait with destruction */
-			if (dialog->needdestroy && !dialog->packets && !dialog->owner) {
-				sip_pvt_unlock(dialog);
-				__sip_destroy(dialog, TRUE, FALSE);
-				goto restartsearch;
-			}
-			sip_pvt_unlock(dialog);
-		}
-		dialoglist_unlock();
+		ao2_callback(dialogs, OBJ_UNLINK|OBJ_NODATA, dialog_needdestroy, &t);
 
 		pthread_testcancel();
 		/* Wait for sched or io */
@@ -17192,8 +17271,12 @@
 		if (global_regextenonqualify)
 			register_peer_exten(peer, FALSE);
 	}
-	if (peer->call)
-		peer->call = sip_destroy(peer->call);
+	if (peer->call) {
+		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from peer call poke for %s....\n", peer->call->callid);
+		peer->call = dialog_unlink_all(peer->call, TRUE, TRUE);
+		/* peer->call = sip_destroy(peer->call);*/
+	}
+	
 	peer->lastms = -1;
 	ast_device_state_changed("SIP/%s", peer->name);
 	/* Try again quickly */
@@ -17223,7 +17306,9 @@
 	if (peer->call) {
 		if (sipdebug)
 			ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n");
-		peer->call = sip_destroy(peer->call);
+		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from peer poking for %s....\n", peer->call->callid);
+		peer->call = dialog_unlink_all(peer->call, TRUE, TRUE);
+		/* peer->call = sip_destroy(peer->call); */
 	}
 	if (!(p = peer->call = sip_alloc(NULL, NULL, 0, SIP_OPTIONS)))
 		return -1;
@@ -17406,7 +17491,9 @@
 	p->outgoing_call = TRUE;
 
 	if (!(p->options = ast_calloc(1, sizeof(*p->options)))) {
-		sip_destroy(p);
+		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from call request for %s....\n", p->callid);
+		dialog_unlink_all(p, TRUE, TRUE);
+		/* sip_destroy(p); */
 		ast_log(LOG_ERROR, "Unable to build option SIP data structure - Out of memory\n");
 		*cause = AST_CAUSE_SWITCH_CONGESTION;
 		return NULL;
@@ -17427,7 +17514,9 @@
 	if (create_addr(p, host)) {
 		*cause = AST_CAUSE_UNREGISTERED;
 		ast_debug(3, "Cant create SIP call - target device not registred\n");
-		sip_destroy(p);
+		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from call request 2 for %s....\n", p->callid);
+		dialog_unlink_all(p, TRUE, TRUE);
+		/* sip_destroy(p); */
 		return NULL;
 	}
 	if (ast_strlen_zero(p->peername) && ext)
@@ -17457,8 +17546,12 @@
 			"Channel: %s\r\nChanneltype: %s\r\nSIPcallid: %s\r\nSIPfullcontact: %s\r\nPeername: %s\r\n",
 			p->owner? p->owner->name : "", "SIP", p->callid, p->fullcontact, p->peername);
 	sip_pvt_unlock(p);
-	if (!tmpc)
-		sip_destroy(p);
+	if (!tmpc) {
+		ast_log(LOG_NOTICE,"Calling Sip_Destroy() from call request 3 for %s....\n", p->callid);
+		dialog_unlink_all(p, TRUE, TRUE);
+		/* sip_destroy(p); */
+	}
+	
 	ast_update_use_count();
 	restart_monitor();
 	return tmpc;
@@ -17785,7 +17878,8 @@
 	struct ast_flags userflags[2] = {{(0)}};
 	struct ast_flags mask[2] = {{(0)}};
 
-
+	ast_log(LOG_NOTICE,"Allocating USER object for %s\n", name);
+	
 	if (!(user = ao2_alloc(sizeof(*user), sip_destroy_user_fn)))
 		return NULL;
 		
@@ -17941,6 +18035,7 @@
 {
 	struct sip_peer *peer;
 
+	ast_log(LOG_NOTICE,"Allocating PEER object for the %s\n", name);
 	if (!(peer = ao2_alloc(sizeof(*peer), sip_destroy_peer_fn)))
 		return NULL;
 
@@ -18003,6 +18098,7 @@
 		*/
 		strcpy(tmp_peer.name, name);
 		/* peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp); */
+		ast_log(LOG_NOTICE,"UNLINK peer %s\n", name);
 		peer = ao2_find(peers, &tmp_peer, OBJ_POINTER|OBJ_UNLINK);
 	}
 	
@@ -18012,6 +18108,8 @@
 		if (!(peer->theMark))
 			firstpass = 0;
  	} else {
+		ast_log(LOG_NOTICE,"Allocating PEER object to %s\n", name);
+		
 		if (!(peer = ao2_alloc(sizeof(*peer),sip_destroy_peer_fn)))
 			return NULL;
 
@@ -18328,7 +18426,9 @@
 			if (iterator->call) {
 				ast_debug(3, "Destroying active SIP dialog for registry %s@%s\n", iterator->username, iterator->hostname);
 				/* This will also remove references to the registry */
-				iterator->call = sip_destroy(iterator->call);
+				ast_log(LOG_NOTICE,"Calling Sip_Destroy() from reload reg for %s....\n", iterator->call->callid);
+				iterator->call = dialog_unlink_all(iterator->call, TRUE, TRUE);
+				/* iterator->call = sip_destroy(iterator->call); */
 			}
 			ASTOBJ_UNLOCK(iterator);
 
@@ -18339,7 +18439,7 @@
 		ast_debug(4, "--------------- Done destroying user list\n");
 		ASTOBJ_CONTAINER_DESTROYALL(&regl, sip_registry_destroy);
 		ast_debug(4, "--------------- Done destroying registry list\n");
-		ao2_callback(peers, 0, peer_markall_func, 0);
+		ao2_callback(peers, OBJ_NODATA, peer_markall_func, 0);
 	}
 
 	/* Initialize copy of current global_regcontext for later use in removing stale contexts */
@@ -19433,7 +19533,8 @@
 	reload_config(reason);
 
 	/* Prune peers who still are supposed to be deleted */
-	ao2_callback(peers, 0, peer_prune_marked_func, 0);
+	ast_log(LOG_NOTICE,"Callback to prune marked peers\n");
+	ao2_callback(peers, OBJ_NODATA|OBJ_UNLINK, peer_is_marked, 0);
 	
 	ast_debug(4, "--------------- Done destroying pruned peers\n");
 

Modified: team/murf/bug11210/configs/sip.conf.sample
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/configs/sip.conf.sample?view=diff&rev=90797&r1=90796&r2=90797
==============================================================================
--- team/murf/bug11210/configs/sip.conf.sample (original)
+++ team/murf/bug11210/configs/sip.conf.sample Mon Dec  3 22:38:23 2007
@@ -38,15 +38,20 @@
 ;match_auth_username=yes	; if available, match user entry using the
 				; 'username' field from the authentication line
 				; instead of the From: field.
+;;
 ;; hash table sizes. For maximum efficiency, adjust the following
 ;; values to be slightly larger than the maximum number of users/peers.
 ;; Too large, and space is wasted. Too small, and things will run slower.
 ;; 563 is probably way too big for small (home) applications, but it
 ;; should cover most small/medium sites.
+;; it is recommended to make the sizes be a prime number!
 ;; This was internally set to 17 for small-memory applications...
-hash_users=563
-hash_peers=563
-hash_dialogs=563
+;; All tables default to 563, except when compiled in LOW_MEMORY mode,
+;; in which case, they default to 17. You can override this by uncommenting
+;; the following, and changing the values.
+;hash_users=563
+;hash_peers=563
+;hash_dialogs=563
 
 allowoverlap=no			; Disable overlap dialing support. (Default is yes)
 ;allowtransfer=no		; Disable all transfers (unless enabled in peers or users)




More information about the asterisk-commits mailing list