mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 12:16:00 +00:00
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) git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@67158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -1861,9 +1861,9 @@ static void __attempt_transmit(void *data)
|
||||
/* 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 @@ static void __get_from_jb(void *p)
|
||||
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 @@ static void __get_from_jb(void *p)
|
||||
|
||||
/* 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);
|
||||
/* iax2_queue_frame() could cause the call to disappear */
|
||||
pvt = iaxs[callno];
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case JB_DROP:
|
||||
iax2_frame_free(frame.data);
|
||||
break;
|
||||
@@ -2295,7 +2300,8 @@ static void __get_from_jb(void *p)
|
||||
break;
|
||||
}
|
||||
}
|
||||
update_jbsched(pvt);
|
||||
if (pvt)
|
||||
update_jbsched(pvt);
|
||||
ast_mutex_unlock(&iaxsl[callno]);
|
||||
}
|
||||
|
||||
@@ -2308,6 +2314,12 @@ static int get_from_jb(void *data)
|
||||
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 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
|
||||
|
||||
/* 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 @@ static int schedule_delivery(struct iax_frame *fr, int updatehistory, int fromtr
|
||||
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;
|
||||
jb_frame frame;
|
||||
|
||||
/* deliver any frames in the jb */
|
||||
while(jb_getall(iaxs[fr->callno]->jb,&frame) == JB_OK)
|
||||
__do_deliver(frame.data);
|
||||
/* 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 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha
|
||||
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 @@ static enum ast_bridge_result iax2_bridge(struct ast_channel *c0, struct ast_cha
|
||||
}
|
||||
/* 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 @@ retryowner:
|
||||
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 @@ retryowner2:
|
||||
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;
|
||||
|
Reference in New Issue
Block a user