[asterisk-commits] russell: branch 1.4 r67158 - /branches/1.4/channels/chan_iax2.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Mon Jun 4 16:31:40 MST 2007


Author: russell
Date: Mon Jun  4 18:31:40 2007
New Revision: 67158

URL: http://svn.digium.com/view/asterisk?view=rev&rev=67158
Log:
Fix up a bunch of places where the iax2 pvt structure can disappear and the
code did not account for it and crashes.
(issues #9642, #9569, #9666, probably others ... based on the work by
 stevedavies and mihai, with additional changes from me)

Modified:
    branches/1.4/channels/chan_iax2.c

Modified: branches/1.4/channels/chan_iax2.c
URL: http://svn.digium.com/view/asterisk/branches/1.4/channels/chan_iax2.c?view=diff&rev=67158&r1=67157&r2=67158
==============================================================================
--- branches/1.4/channels/chan_iax2.c (original)
+++ branches/1.4/channels/chan_iax2.c Mon Jun  4 18:31:40 2007
@@ -1861,9 +1861,9 @@
 							/* Hangup the fd */
 							fr.frametype = AST_FRAME_CONTROL;
 							fr.subclass = AST_CONTROL_HANGUP;
-							iax2_queue_frame(callno, &fr);
+							iax2_queue_frame(callno, &fr); // XXX
 							/* Remember, owner could disappear */
-							if (iaxs[callno]->owner)
+							if (iaxs[callno] && iaxs[callno]->owner)
 								iaxs[callno]->owner->hangupcause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
 						} else {
 							if (iaxs[callno]->reg) {
@@ -2264,6 +2264,8 @@
 		case JB_OK:
 			fr = frame.data;
 			__do_deliver(fr);
+			/* __do_deliver() can cause the call to disappear */
+			pvt = iaxs[callno];
 			break;
 		case JB_INTERP:
 		{
@@ -2279,10 +2281,13 @@
 			
 			/* 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 (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE))
+			if (!ast_test_flag(iaxs[callno], IAX_ALREADYGONE)) {
 				iax2_queue_frame(callno, &af);
-		}
-		break;
+				/* iax2_queue_frame() could cause the call to disappear */
+				pvt = iaxs[callno];
+			}
+		}
+			break;
 		case JB_DROP:
 			iax2_frame_free(frame.data);
 			break;
@@ -2295,7 +2300,8 @@
 			break;
 		}
 	}
-	update_jbsched(pvt);
+	if (pvt)
+		update_jbsched(pvt);
 	ast_mutex_unlock(&iaxsl[callno]);
 }
 
@@ -2308,6 +2314,12 @@
 	return 0;
 }
 
+/*!
+ * \note This function assumes fr->callno is locked
+ *
+ * \note IMPORTANT NOTE!!! Any time this function is used, even if iaxs[callno]
+ * was valid before calling it, it may no longer be valid after calling it.
+ */
 static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtrunk, unsigned int *tsout)
 {
 	int type, len;
@@ -2316,7 +2328,6 @@
 
 	/* Attempt to recover wrapped timestamps */
 	unwrap_timestamp(fr);
-	
 
 	/* delivery time is sender's sent timestamp converted back into absolute time according to our clock */
 	if ( !fromtrunk && !ast_tvzero(iaxs[fr->callno]->rxcore))
@@ -2350,16 +2361,20 @@
 	if( (!ast_test_flag(iaxs[fr->callno], IAX_FORCEJITTERBUF)) &&
 	    iaxs[fr->callno]->owner && ast_bridged_channel(iaxs[fr->callno]->owner) &&
 	    (ast_bridged_channel(iaxs[fr->callno]->owner)->tech->properties & AST_CHAN_TP_WANTSJITTER)) {
-                jb_frame frame;
-
-                /* deliver any frames in the jb */
-                while(jb_getall(iaxs[fr->callno]->jb,&frame) == JB_OK)
-                        __do_deliver(frame.data);
+		jb_frame frame;
+
+		/* deliver any frames in the jb */
+		while (jb_getall(iaxs[fr->callno]->jb, &frame) == JB_OK) {
+			__do_deliver(frame.data);
+			/* __do_deliver() can make the call disappear */
+			if (!iaxs[fr->callno])
+				return -1;
+		}
 
 		jb_reset(iaxs[fr->callno]->jb);
 
 		if (iaxs[fr->callno]->jbid > -1)
-                        ast_sched_del(sched, iaxs[fr->callno]->jbid);
+			ast_sched_del(sched, iaxs[fr->callno]->jbid);
 
 		iaxs[fr->callno]->jbid = -1;
 
@@ -3068,6 +3083,10 @@
 	struct timeval waittimer = {0, 0}, tv;
 
 	lock_both(callno0, callno1);
+	if (!iaxs[callno0] || !iaxs[callno1]) {
+		unlock_both(callno0, callno1);
+		return AST_BRIDGE_FAILED;
+	}
 	/* Put them in native bridge mode */
 	if (!flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) {
 		iaxs[callno0]->bridgecallno = callno1;
@@ -3106,8 +3125,10 @@
 			}
 			/* Remove from native mode */
 			lock_both(callno0, callno1);
-			iaxs[callno0]->bridgecallno = 0;
-			iaxs[callno1]->bridgecallno = 0;
+			if (iaxs[callno0])
+				iaxs[callno0]->bridgecallno = 0;
+			if (iaxs[callno1])
+				iaxs[callno1]->bridgecallno = 0;
 			unlock_both(callno0, callno1);
 			return AST_BRIDGE_FAILED_NOWARN;
 		}
@@ -6837,6 +6858,10 @@
 					ast_mutex_unlock(&iaxsl[fr->callno]);
 					exists = ast_exists_extension(NULL, iaxs[fr->callno]->context, iaxs[fr->callno]->exten, 1, iaxs[fr->callno]->cid_num);
 					ast_mutex_lock(&iaxsl[fr->callno]);
+					if (!iaxs[fr->callno]) {
+						ast_mutex_unlock(&iaxsl[fr->callno]);
+						return 1;
+					}
 				} else
 					exists = 0;
 				if (ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) {
@@ -7561,7 +7586,7 @@
 			return 1;
 		}
 		/* Unless this is an ACK or INVAL frame, ack it */
-		if (iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
+		if (iaxs[fr->callno] && iaxs[fr->callno]->aseqno != iaxs[fr->callno]->iseqno)
 			send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno);
 	} else if (minivid) {
 		f.frametype = AST_FRAME_VIDEO;



More information about the asterisk-commits mailing list