Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(revision 316293)
+++ channels/chan_sip.c	(working copy)
@@ -2657,7 +2657,7 @@
 static int parse_minse(const char *p_hdrval, int *const p_interval);
 static int st_get_se(struct sip_pvt *, int max);
 static enum st_refresher st_get_refresher(struct sip_pvt *);
-static enum st_mode st_get_mode(struct sip_pvt *);
+static enum st_mode st_get_mode(struct sip_pvt *, int force_peer);
 static struct sip_st_dlg* sip_st_alloc(struct sip_pvt *const p);
 
 /*!--- SIP MWI Subscription support */
@@ -9473,7 +9473,7 @@
 static int add_supported_header(struct sip_pvt *pvt, struct sip_request *req)
 {
 	int res;
-	if (st_get_mode(pvt) != SESSION_TIMER_MODE_REFUSE) {
+	if (st_get_mode(pvt, 0) != SESSION_TIMER_MODE_REFUSE) {
 		res = add_header(req, "Supported", "replaces, timer");
 	} else {
 		res = add_header(req, "Supported", "replaces");
@@ -11376,7 +11376,7 @@
 	}
 
 	/* Add Session-Timers related headers */
-	if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) {
+	if (st_get_mode(p, 0) == SESSION_TIMER_MODE_ORIGINATE) {
 		char i2astr[10];
 
 		if (!p->stimer->st_interval)
@@ -18311,7 +18311,7 @@
 		}
 
 		/* Check for Session-Timers related headers */
-		if (st_get_mode(p) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) {
+		if (st_get_mode(p, 0) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) {
 			p_hdrval = (char*)get_header(req, "Session-Expires");
 			if (!ast_strlen_zero(p_hdrval)) {
 				/* UAS supports Session-Timers */
@@ -18333,7 +18333,7 @@
 				start_session_timer(p);
 			} else {
 				/* UAS doesn't support Session-Timers */
-				if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) {
+				if (st_get_mode(p, 0) == SESSION_TIMER_MODE_ORIGINATE) {
 					p->stimer->st_ref = SESSION_TIMER_REFRESHER_UAC;
 					p->stimer->st_active_peer_ua = FALSE;
 					start_session_timer(p);
@@ -20742,7 +20742,7 @@
 		}
 
 		dlg_min_se = st_get_se(p, FALSE);
-		switch (st_get_mode(p)) {
+		switch (st_get_mode(p, 1)) {
 		case SESSION_TIMER_MODE_ACCEPT:
 		case SESSION_TIMER_MODE_ORIGINATE:
 			if (uac_max_se > 0 && uac_max_se < dlg_min_se) {
@@ -20788,14 +20788,14 @@
 			break;
 
 		default:
-			ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p), __FILE__, __LINE__);
+			ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p, 1), __FILE__, __LINE__);
 			break;
 		}
 	} else {
 		/* The UAC did not request session-timers.  Asterisk (UAS), will now decide
 		(based on session-timer-mode in sip.conf) whether to run session-timers for
 		this session or not. */
-		switch (st_get_mode(p)) {
+		switch (st_get_mode(p, 1)) {
 		case SESSION_TIMER_MODE_ORIGINATE:
 			st_active = TRUE;
 			st_interval = st_get_se(p, TRUE);
@@ -23468,25 +23468,45 @@
 /*! \brief Get the session-timer mode 
  * \param p pointer to the SIP dialog 
 */
-enum st_mode st_get_mode(struct sip_pvt *p)
+enum st_mode st_get_mode(struct sip_pvt *p, int force_peer)
 {
-	if (!p->stimer) 
+	enum st_mode cached_mode = 0;
+	enum st_mode peer_mode = 0;
+	enum st_mode res = 0;
+
+	if (!p->stimer) {
 		sip_st_alloc(p);
+	}
 
-	if (p->stimer->st_cached_mode != SESSION_TIMER_MODE_INVALID) 
-		return p->stimer->st_cached_mode;
+	if (p->stimer->st_cached_mode != SESSION_TIMER_MODE_INVALID) {
+		cached_mode = p->stimer->st_cached_mode;
+	}
 
 	if (p->peername) {
 		struct sip_peer *pp = find_peer(p->peername, NULL, TRUE, FINDPEERS, FALSE, 0);
 		if (pp) {
-			p->stimer->st_cached_mode = pp->stimer.st_mode_oper;
 			unref_peer(pp, "unref peer pointer from find_peer call in st_get_mode");
-			return pp->stimer.st_mode_oper;
+			peer_mode = pp->stimer.st_mode_oper;
 		}
 	}
 
-	p->stimer->st_cached_mode = global_st_mode;
-	return global_st_mode;
+	/* The order is as follows.
+	 * 1. If force_peer and peer mode is found, use it.
+	 * 2. If cached is set, use it.
+	 * 3. If peer is found and cached was not set, use peer_mode
+	 * 4. If nothing is set, use the global setting */
+	if (force_peer && peer_mode) {
+		res = peer_mode;
+	} else if (cached_mode) {
+		res = cached_mode;
+	} else if (peer_mode) {
+		res = peer_mode;
+	} else {
+		res = global_st_mode;
+	}
+
+	p->stimer->st_cached_mode = res;
+	return res;
 }
 
 
