Skip to content
Snippets Groups Projects
Commit aec4d2f2 authored by Alec L Davis's avatar Alec L Davis
Browse files

chan_sip: Session-Expires: Set timer to correctly expire at (~2/3) of the...

chan_sip: Session-Expires: Set timer to correctly expire at (~2/3) of the interval when not the refresher

RFC 4028 Section 10
	if the side not performing refreshes does not receive a
	session refresh request before the session expiration, it SHOULD send
	a BYE to terminate the session, slightly before the session
	expiration.  The minimum of 32 seconds and one third of the session
	interval is RECOMMENDED.

Prior to this asterisk would refresh at 1/2 the Session-Expires interval,
or if the remote device was the refresher, asterisk would timeout at interval end.

Now, when not refresher, timeout as per RFC noted above.

(closes issue ASTERISK-21742)

Reported by: alecdavis
Tested by: alecdavis
alecdavis (license 585)

Review https://reviewboard.asterisk.org/r/2488/
........

Merged revisions 387344 from http://svn.asterisk.org/svn/asterisk/branches/1.8


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/11@387345 65c4cc65-6c06-0410-ace0-fbb531ad65f3
parent 28468810
Branches
Tags
No related merge requests found
...@@ -21117,7 +21117,6 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a ...@@ -21117,7 +21117,6 @@ static char *sip_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_a
if (cur->stimer->st_active == TRUE) { if (cur->stimer->st_active == TRUE) {
ast_cli(a->fd, " S-Timer Interval: %d\n", cur->stimer->st_interval); ast_cli(a->fd, " S-Timer Interval: %d\n", cur->stimer->st_interval);
ast_cli(a->fd, " S-Timer Refresher: %s\n", strefresher2str(cur->stimer->st_ref)); ast_cli(a->fd, " S-Timer Refresher: %s\n", strefresher2str(cur->stimer->st_ref));
ast_cli(a->fd, " S-Timer Expirys: %d\n", cur->stimer->st_expirys);
ast_cli(a->fd, " S-Timer Sched Id: %d\n", cur->stimer->st_schedid); ast_cli(a->fd, " S-Timer Sched Id: %d\n", cur->stimer->st_schedid);
ast_cli(a->fd, " S-Timer Peer Sts: %s\n", cur->stimer->st_active_peer_ua ? "Active" : "Inactive"); ast_cli(a->fd, " S-Timer Peer Sts: %s\n", cur->stimer->st_active_peer_ua ? "Active" : "Inactive");
ast_cli(a->fd, " S-Timer Cached Min-SE: %d\n", cur->stimer->st_cached_min_se); ast_cli(a->fd, " S-Timer Cached Min-SE: %d\n", cur->stimer->st_cached_min_se);
...@@ -25569,9 +25568,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str ...@@ -25569,9 +25568,6 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
} }
   
restart_session_timer(p); restart_session_timer(p);
if (p->stimer->st_expirys > 0) {
p->stimer->st_expirys--;
}
} }
} }
   
...@@ -28979,6 +28975,8 @@ static void stop_session_timer(struct sip_pvt *p) ...@@ -28979,6 +28975,8 @@ static void stop_session_timer(struct sip_pvt *p)
/*! \brief Session-Timers: Start session timer */ /*! \brief Session-Timers: Start session timer */
static void start_session_timer(struct sip_pvt *p) static void start_session_timer(struct sip_pvt *p)
{ {
unsigned int timeout_ms;
if (!p->stimer) { if (!p->stimer) {
ast_log(LOG_WARNING, "Null stimer in start_session_timer - %s\n", p->callid); ast_log(LOG_WARNING, "Null stimer in start_session_timer - %s\n", p->callid);
return; return;
...@@ -28991,14 +28989,31 @@ static void start_session_timer(struct sip_pvt *p) ...@@ -28991,14 +28989,31 @@ static void start_session_timer(struct sip_pvt *p)
dialog_unref(p, "unref stimer->st_schedid from dialog")); dialog_unref(p, "unref stimer->st_schedid from dialog"));
} }
   
p->stimer->st_schedid = ast_sched_add(sched, p->stimer->st_interval * 1000 / 2, proc_session_timer, /*
* RFC 4028 Section 10
* If the side not performing refreshes does not receive a
* session refresh request before the session expiration, it SHOULD send
* a BYE to terminate the session, slightly before the session
* expiration. The minimum of 32 seconds and one third of the session
* interval is RECOMMENDED.
*/
timeout_ms = (1000 * p->stimer->st_interval);
if (p->stimer->st_ref == SESSION_TIMER_REFRESHER_US) {
timeout_ms /= 2;
} else {
timeout_ms -= MIN(timeout_ms / 3, 32000);
}
p->stimer->st_schedid = ast_sched_add(sched, timeout_ms, proc_session_timer,
dialog_ref(p, "adding session timer ref")); dialog_ref(p, "adding session timer ref"));
if (p->stimer->st_schedid < 0) { if (p->stimer->st_schedid < 0) {
dialog_unref(p, "removing session timer ref"); dialog_unref(p, "removing session timer ref");
ast_log(LOG_ERROR, "ast_sched_add failed - %s\n", p->callid); ast_log(LOG_ERROR, "ast_sched_add failed - %s\n", p->callid);
} else { } else {
p->stimer->st_active = TRUE; p->stimer->st_active = TRUE;
ast_debug(2, "Session timer started: %d - %s\n", p->stimer->st_schedid, p->callid); ast_debug(2, "Session timer started: %d - %s %ums\n", p->stimer->st_schedid, p->callid, timeout_ms);
} }
} }
   
...@@ -29032,30 +29047,25 @@ static int proc_session_timer(const void *vp) ...@@ -29032,30 +29047,25 @@ static int proc_session_timer(const void *vp)
transmit_reinvite_with_sdp(p, FALSE, TRUE); transmit_reinvite_with_sdp(p, FALSE, TRUE);
} }
} else { } else {
p->stimer->st_expirys++; if (p->stimer->quit_flag) {
if (p->stimer->st_expirys >= 2) { goto return_unref;
if (p->stimer->quit_flag) { }
ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid);
sip_pvt_lock(p);
while (p->owner && ast_channel_trylock(p->owner)) {
sip_pvt_unlock(p);
usleep(1);
if (p->stimer && p->stimer->quit_flag) {
goto return_unref; goto return_unref;
} }
ast_log(LOG_WARNING, "Session-Timer expired - %s\n", p->callid);
sip_pvt_lock(p); sip_pvt_lock(p);
while (p->owner && ast_channel_trylock(p->owner)) {
sip_pvt_unlock(p);
usleep(1);
if (p->stimer && p->stimer->quit_flag) {
goto return_unref;
}
sip_pvt_lock(p);
}
manager_event(EVENT_FLAG_CALL, "SessionTimeout", "Source: SIPSessionTimer\r\n"
"Channel: %s\r\nUniqueid: %s\r\n", ast_channel_name(p->owner), ast_channel_uniqueid(p->owner));
ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
ast_channel_unlock(p->owner);
sip_pvt_unlock(p);
} else {
res = 1;
} }
manager_event(EVENT_FLAG_CALL, "SessionTimeout", "Source: SIPSessionTimer\r\n"
"Channel: %s\r\nUniqueid: %s\r\n", ast_channel_name(p->owner), ast_channel_uniqueid(p->owner));
ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_DEV);
ast_channel_unlock(p->owner);
sip_pvt_unlock(p);
} }
   
return_unref: return_unref:
...@@ -963,7 +963,6 @@ struct sip_st_dlg { ...@@ -963,7 +963,6 @@ struct sip_st_dlg {
int st_interval; /*!< Session-Timers negotiated session refresh interval */ int st_interval; /*!< Session-Timers negotiated session refresh interval */
enum st_refresher st_ref; /*!< Session-Timers cached refresher */ enum st_refresher st_ref; /*!< Session-Timers cached refresher */
int st_schedid; /*!< Session-Timers ast_sched scheduler id */ int st_schedid; /*!< Session-Timers ast_sched scheduler id */
int st_expirys; /*!< Session-Timers number of expirys */
int st_active_peer_ua; /*!< Session-Timers on/off in peer UA */ int st_active_peer_ua; /*!< Session-Timers on/off in peer UA */
int st_cached_min_se; /*!< Session-Timers cached Min-SE */ int st_cached_min_se; /*!< Session-Timers cached Min-SE */
int st_cached_max_se; /*!< Session-Timers cached Session-Expires */ int st_cached_max_se; /*!< Session-Timers cached Session-Expires */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment