diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-06-25 16:05:36 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-06-25 16:05:36 +0000 |
commit | 1add16fb09a32d8932f0c11da03c21154a716c0a (patch) | |
tree | 29f8a15c018544e812097d0b1605726b8be1bde3 /channels | |
parent | 1447facb2a123c59f3fd85526e64a1e5cb08bac3 (diff) |
Merged revisions 203116 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
................
r203116 | russell | 2009-06-25 11:04:10 -0500 (Thu, 25 Jun 2009) | 18 lines
Merged revisions 203115 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r203115 | russell | 2009-06-25 11:02:16 -0500 (Thu, 25 Jun 2009) | 11 lines
Resolve a crash related to a T.38 reinvite race condition.
This change resolves a crash observed locally during some T.38 testing.
A call was set up using a call file, and when the T.38 reinvite came in,
the channel state was still AST_STATE_DOWN. The reason is explained by
a comment in the code that previously lived in the handling of
AST_STATE_RINGING. This change modifies the logic to handle the same
race condition for any channel state that is not UP.
(closes ABE-1895)
........
................
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.0@203117 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_sip.c | 36 |
1 files changed, 20 insertions, 16 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 12b4822a5..804116f7a 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -17769,7 +17769,23 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int if (c) { /* We have a call -either a new call or an old one (RE-INVITE) */ - switch(c->_state) { + enum ast_channel_state c_state = c->_state; + + if (c_state != AST_STATE_UP && reinvite && + (p->invitestate == INV_TERMINATED || p->invitestate == INV_CONFIRMED)) { + /* If these conditions are true, and the channel is still in the 'ringing' + * state, then this likely means that we have a situation where the initial + * INVITE transaction has completed *but* the channel's state has not yet been + * changed to UP. The reason this could happen is if the reinvite is received + * on the SIP socket prior to an application calling ast_read on this channel + * to read the answer frame we earlier queued on it. In this case, the reinvite + * is completely legitimate so we need to handle this the same as if the channel + * were already UP. Thus we are purposely falling through to the AST_STATE_UP case. + */ + c_state = AST_STATE_UP; + } + + switch(c_state) { case AST_STATE_DOWN: ast_debug(2, "%s: New call is still down.... Trying... \n", c->name); transmit_response(p, "100 Trying", req); @@ -17831,21 +17847,9 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int p->invitestate = INV_PROCEEDING; break; case AST_STATE_RINGING: - if (reinvite && (p->invitestate == INV_TERMINATED || p->invitestate == INV_CONFIRMED)) { - /* If these conditions are true, and the channel is still in the 'ringing' - * state, then this likely means that we have a situation where the initial - * INVITE transaction has completed *but* the channel's state has not yet been - * changed to UP. The reason this could happen is if the reinvite is received - * on the SIP socket prior to an application calling ast_read on this channel - * to read the answer frame we earlier queued on it. In this case, the reinvite - * is completely legitimate so we need to handle this the same as if the channel - * were already UP. Thus we are purposely falling through to the AST_STATE_UP case. - */ - } else { - transmit_response(p, "180 Ringing", req); - p->invitestate = INV_PROCEEDING; - break; - } + transmit_response(p, "180 Ringing", req); + p->invitestate = INV_PROCEEDING; + break; case AST_STATE_UP: ast_debug(2, "%s: This call is UP.... \n", c->name); |