diff options
author | Russell Bryant <russell@russellbryant.com> | 2007-06-04 23:32:26 +0000 |
---|---|---|
committer | Russell Bryant <russell@russellbryant.com> | 2007-06-04 23:32:26 +0000 |
commit | 71544542a0ebf099a9ed034382c95a53803ca365 (patch) | |
tree | 7e687144bd3bf63646d9463ad28a887e4baff6bf /channels/chan_iax2.c | |
parent | 95327fdb2f0933bd9b73e3162d04c417098a4253 (diff) |
Merged revisions 67158 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r67158 | russell | 2007-06-04 18:31:40 -0500 (Mon, 04 Jun 2007) | 5 lines
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/trunk@67160 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_iax2.c')
-rw-r--r-- | channels/chan_iax2.c | 53 |
1 files changed, 39 insertions, 14 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 0b909ceaa..e32983b43 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -1950,9 +1950,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) { @@ -2388,6 +2388,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: { @@ -2403,10 +2405,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; @@ -2419,7 +2424,8 @@ static void __get_from_jb(void *p) break; } } - update_jbsched(pvt); + if (pvt) + update_jbsched(pvt); ast_mutex_unlock(&iaxsl[callno]); } @@ -2432,6 +2438,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; @@ -2440,7 +2452,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)) @@ -2475,16 +2486,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; @@ -3226,6 +3241,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; @@ -3264,8 +3283,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; } @@ -7095,6 +7116,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; /* Get OSP token if it does exist */ @@ -7845,7 +7870,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; |