From: Walter Doekes Date: Tue, 27 May 2014 21:19:26 +0000 (+0000) Subject: chan_sip: Start session timer at 200, not at INVITE. X-Git-Tag: 11.11.0-rc1~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=611f27fbd95cb6e92a854561933ddd41bfe34106;p=thirdparty%2Fasterisk.git chan_sip: Start session timer at 200, not at INVITE. Asterisk started counting the session timer at INVITE while the other end correctly started at 200. This meant that for short session-expiries (90 seconds) combined with long ringing times (e.g. 30 seconds), asterisk would wrongly assume that the timer was hit before the other end thought it was time to send a session refresh. This resulted in prematurely ended calls. This changes the session timer to start counting first at 200 like RFC says it should. (Also removed a few excess NULL checks that would never hit, because if they did, asterisk would have crashed already.) ASTERISK-22551 #close Reported by: i2045 Review: https://reviewboard.asterisk.org/r/3562/ ........ Merged revisions 414620 from http://svn.asterisk.org/svn/asterisk/branches/1.8 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@414628 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- diff --git a/channels/chan_sip.c b/channels/chan_sip.c index be1274b67f..7a960922dd 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -7270,6 +7270,11 @@ static int sip_answer(struct ast_channel *ast) ast_rtp_instance_update_source(p->rtp); res = transmit_response_with_sdp(p, "200 OK", &p->initreq, XMIT_CRITICAL, oldsdp, TRUE); ast_set_flag(&p->flags[1], SIP_PAGE2_DIALOG_ESTABLISHED); + /* RFC says the session timer starts counting on 200, + * not on INVITE. */ + if (p->stimer->st_active == TRUE) { + start_session_timer(p); + } } sip_pvt_unlock(p); return res; @@ -25805,12 +25810,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str /* Check if OLI/ANI-II is present in From: */ parse_oli(req, p->owner); - if (p->stimer->st_active == TRUE) { - if (reinvite == 0) { - start_session_timer(p); - } else { - restart_session_timer(p); - } + if (reinvite && p->stimer->st_active == TRUE) { + restart_session_timer(p); } if (!req->ignore && p) @@ -26893,7 +26894,9 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req) } stop_media_flows(p); /* Immediately stop RTP, VRTP and UDPTL as applicable */ - stop_session_timer(p); /* Stop Session-Timer */ + if (p->stimer) { + stop_session_timer(p); /* Stop Session-Timer */ + } if (!ast_strlen_zero(sip_get_header(req, "Also"))) { ast_log(LOG_NOTICE, "Client '%s' using deprecated BYE/Also transfer method. Ask vendor to support REFER instead\n", @@ -29196,11 +29199,6 @@ static void acl_change_event_cb(const struct ast_event *event, void *userdata) /*! \brief Session-Timers: Restart session timer */ static void restart_session_timer(struct sip_pvt *p) { - if (!p->stimer) { - ast_log(LOG_WARNING, "Null stimer in restart_session_timer - %s\n", p->callid); - return; - } - if (p->stimer->st_active == TRUE) { ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); AST_SCHED_DEL_UNREF(sched, p->stimer->st_schedid, @@ -29213,11 +29211,6 @@ static void restart_session_timer(struct sip_pvt *p) /*! \brief Session-Timers: Stop session timer */ static void stop_session_timer(struct sip_pvt *p) { - if (!p->stimer) { - ast_log(LOG_WARNING, "Null stimer in stop_session_timer - %s\n", p->callid); - return; - } - if (p->stimer->st_active == TRUE) { p->stimer->st_active = FALSE; ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); @@ -29232,11 +29225,6 @@ static void start_session_timer(struct sip_pvt *p) { unsigned int timeout_ms; - if (!p->stimer) { - ast_log(LOG_WARNING, "Null stimer in start_session_timer - %s\n", p->callid); - return; - } - if (p->stimer->st_schedid > -1) { /* in the event a timer is already going, stop it */ ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); @@ -29328,7 +29316,11 @@ return_unref: /* An error occurred. Stop session timer processing */ if (p->stimer) { ast_debug(2, "Session timer stopped: %d - %s\n", p->stimer->st_schedid, p->callid); + /* Don't pass go, don't collect $200.. we are the scheduled + * callback. We can rip ourself out here. */ p->stimer->st_schedid = -1; + /* Calling stop_session_timer is nice for consistent debug + * logs. */ stop_session_timer(p); }