Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(revision 410027)
+++ channels/chan_sip.c	(working copy)
@@ -22691,6 +22691,145 @@
 	return 0;
 }
 
+/*
+ * \internal \brief Check Session Timers for an INVITE request
+ *
+ * \retval 0 ok
+ * \retval -1 failure
+ */
+static int handle_request_invite_st(struct sip_pvt *p, struct sip_request *req,
+		const char *required, int reinvite)
+{
+	const char *p_uac_se_hdr;       /* UAC's Session-Expires header string                      */
+	const char *p_uac_min_se;       /* UAC's requested Min-SE interval (char string)            */
+	int uac_max_se = -1;            /* UAC's Session-Expires in integer format                  */
+	int uac_min_se = -1;            /* UAC's Min-SE in integer format                           */
+	int st_active = FALSE;          /* Session-Timer on/off boolean                             */
+	int st_interval = 0;            /* Session-Timer negotiated refresh interval                */
+	enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; /* Session-Timer refresher     */
+	int dlg_min_se = -1;
+	int dlg_max_se = global_max_se;
+	int rtn;
+
+	/* Session-Timers */
+	if ((p->sipoptions & SIP_OPT_TIMER)) {
+		enum st_refresher_param st_ref_param = SESSION_TIMER_REFRESHER_PARAM_UNKNOWN;
+
+		/* The UAC has requested session-timers for this session. Negotiate
+		the session refresh interval and who will be the refresher */
+		ast_debug(2, "Incoming INVITE with 'timer' option supported\n");
+
+		/* Allocate Session-Timers struct w/in the dialog */
+		if (!p->stimer) {
+			sip_st_alloc(p);
+		}
+
+		/* Parse the Session-Expires header */
+		p_uac_se_hdr = get_header(req, "Session-Expires");
+		if (!ast_strlen_zero(p_uac_se_hdr)) {
+			ast_debug(2, "INVITE also has \"Session-Expires\" header.\n");
+			rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref_param);
+			tmp_st_ref = (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UAC) ? SESSION_TIMER_REFRESHER_THEM : SESSION_TIMER_REFRESHER_US;
+			if (rtn != 0) {
+				transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req);
+				return -1;
+			}
+		}
+
+		/* Parse the Min-SE header */
+		p_uac_min_se = get_header(req, "Min-SE");
+		if (!ast_strlen_zero(p_uac_min_se)) {
+			ast_debug(2, "INVITE also has \"Min-SE\" header.\n");
+			rtn = parse_minse(p_uac_min_se, &uac_min_se);
+			if (rtn != 0) {
+				transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req);
+				return -1;
+			}
+		}
+
+		dlg_min_se = st_get_se(p, FALSE);
+		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) {
+				transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se);
+				return -1;
+			}
+
+			p->stimer->st_active_peer_ua = TRUE;
+			st_active = TRUE;
+			if (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UNKNOWN) {
+				tmp_st_ref = st_get_refresher(p);
+			}
+
+			dlg_max_se = st_get_se(p, TRUE);
+			if (uac_max_se > 0) {
+				if (dlg_max_se >= uac_min_se) {
+					st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se;
+				} else {
+					st_interval = uac_max_se;
+				}
+			} else if (uac_min_se > 0) {
+				st_interval = MAX(dlg_max_se, uac_min_se);
+			} else {
+				st_interval = dlg_max_se;
+			}
+			break;
+
+		case SESSION_TIMER_MODE_REFUSE:
+			if (p->reqsipoptions & SIP_OPT_TIMER) {
+				transmit_response_with_unsupported(p, "420 Option Disabled", req, required);
+				ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required);
+				return -1;
+			}
+			break;
+
+		default:
+			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, 1)) {
+		case SESSION_TIMER_MODE_ORIGINATE:
+			st_active = TRUE;
+			st_interval = st_get_se(p, TRUE);
+			tmp_st_ref = SESSION_TIMER_REFRESHER_US;
+			p->stimer->st_active_peer_ua = (p->sipoptions & SIP_OPT_TIMER) ? TRUE : FALSE;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (reinvite == 0) {
+		/* Session-Timers: Start session refresh timer based on negotiation/config */
+		if (st_active == TRUE) {
+			p->stimer->st_active = TRUE;
+			p->stimer->st_interval = st_interval;
+			p->stimer->st_ref = tmp_st_ref;
+		}
+	} else {
+		if (p->stimer->st_active == TRUE) {
+			/* Session-Timers:  A re-invite request sent within a dialog will serve as
+			a refresh request, no matter whether the re-invite was sent for refreshing
+			the session or modifying it.*/
+			ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid);
+
+			/* The UAC may be adjusting the session-timers mid-session */
+			if (st_interval > 0) {
+				p->stimer->st_interval = st_interval;
+				p->stimer->st_ref      = tmp_st_ref;
+			}
+		}
+	}
+
+	return 0;
+}
+
 /*!
  * \brief Handle incoming INVITE request
  * \note If the INVITE has a Replaces header, it is part of an
@@ -22710,18 +22849,9 @@
 	struct ast_channel *c = NULL;		/* New channel */
 	struct sip_peer *authpeer = NULL;	/* Matching Peer */
 	int reinvite = 0;
-	int rtn;
 	struct ast_party_redirecting redirecting;
 	struct ast_set_party_redirecting update_redirecting;
 
-	const char *p_uac_se_hdr;       /* UAC's Session-Expires header string                      */
-	const char *p_uac_min_se;       /* UAC's requested Min-SE interval (char string)            */
-	int uac_max_se = -1;            /* UAC's Session-Expires in integer format                  */
-	int uac_min_se = -1;            /* UAC's Min-SE in integer format                           */
-	int st_active = FALSE;          /* Session-Timer on/off boolean                             */
-	int st_interval = 0;            /* Session-Timer negotiated refresh interval                */
-	enum st_refresher tmp_st_ref = SESSION_TIMER_REFRESHER_AUTO; /* Session-Timer refresher     */
-	int dlg_min_se = -1;
 	struct {
 		char exten[AST_MAX_EXTENSION];
 		char context[AST_MAX_CONTEXT];
@@ -23202,6 +23332,14 @@
 			/* Initialize our tag */
 
 			make_our_tag(p->tag, sizeof(p->tag));
+
+			if (handle_request_invite_st(p, req, required, reinvite)) {
+				p->invitestate = INV_COMPLETED;
+				sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+				res = -1;
+				goto request_invite_cleanup;
+			}
+
 			/* First invitation - create the channel.  Allocation
 			 * failures are handled below. */
 			c = sip_new(p, AST_STATE_DOWN, S_OR(p->peername, NULL), NULL);
@@ -23234,32 +23372,8 @@
 		}
 		if (!req->ignore)
 			reinvite = 1;
-		c = p->owner;
-		change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE); /*Will return immediately if no Diversion header is present */
-		if (c) {
-			ast_channel_set_redirecting(c, &redirecting, &update_redirecting);
-		}
-		ast_party_redirecting_free(&redirecting);
-	}
 
-	/* Session-Timers */
-	if ((p->sipoptions & SIP_OPT_TIMER) && !ast_strlen_zero(get_header(req, "Session-Expires"))) {
-		enum st_refresher_param st_ref_param;
-
-		/* The UAC has requested session-timers for this session. Negotiate
-		the session refresh interval and who will be the refresher */
-		ast_debug(2, "Incoming INVITE with 'timer' option supported and \"Session-Expires\" header.\n");
-
-		/* Allocate Session-Timers struct w/in the dialog */
-		if (!p->stimer)
-			sip_st_alloc(p);
-
-		/* Parse the Session-Expires header */
-		p_uac_se_hdr = get_header(req, "Session-Expires");
-		rtn = parse_session_expires(p_uac_se_hdr, &uac_max_se, &st_ref_param);
-		tmp_st_ref = (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UAC) ? SESSION_TIMER_REFRESHER_THEM : SESSION_TIMER_REFRESHER_US;
-		if (rtn != 0) {
-			transmit_response_reliable(p, "400 Session-Expires Invalid Syntax", req);
+		if (handle_request_invite_st(p, req, required, reinvite)) {
 			p->invitestate = INV_COMPLETED;
 			if (!p->lastinvite) {
 				sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
@@ -23268,109 +23382,18 @@
 			goto request_invite_cleanup;
 		}
 
-		/* Parse the Min-SE header */
-		p_uac_min_se = get_header(req, "Min-SE");
-		if (!ast_strlen_zero(p_uac_min_se)) {
-			rtn = parse_minse(p_uac_min_se, &uac_min_se);
-			if (rtn != 0) {
-				transmit_response_reliable(p, "400 Min-SE Invalid Syntax", req);
-				p->invitestate = INV_COMPLETED;
-				if (!p->lastinvite) {
-					sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-				}
-				res = -1;
-				goto request_invite_cleanup;
-			}
+		c = p->owner;
+		change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE); /*Will return immediately if no Diversion header is present */
+		if (c) {
+			ast_channel_set_redirecting(c, &redirecting, &update_redirecting);
 		}
-
-		dlg_min_se = st_get_se(p, FALSE);
-		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) {
-				transmit_response_with_minse(p, "422 Session Interval Too Small", req, dlg_min_se);
-				p->invitestate = INV_COMPLETED;
-				if (!p->lastinvite) {
-					sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-				}
-				res = -1;
-				goto request_invite_cleanup;
-			}
-
-			p->stimer->st_active_peer_ua = TRUE;
-			st_active = TRUE;
-			if (st_ref_param == SESSION_TIMER_REFRESHER_PARAM_UNKNOWN) {
-				tmp_st_ref = st_get_refresher(p);
-			}
-
-			if (uac_max_se > 0) {
-				int dlg_max_se = st_get_se(p, TRUE);
-				if (dlg_max_se >= uac_min_se) {
-					st_interval = (uac_max_se < dlg_max_se) ? uac_max_se : dlg_max_se;
-				} else {
-					st_interval = uac_max_se;
-				}
-			} else {
-				/* Set to default max value */
-				st_interval = global_max_se;
-			}
-			break;
-
-		case SESSION_TIMER_MODE_REFUSE:
-			if (p->reqsipoptions & SIP_OPT_TIMER) {
-				transmit_response_with_unsupported(p, "420 Option Disabled", req, required);
-				ast_log(LOG_WARNING, "Received SIP INVITE with supported but disabled option: %s\n", required);
-				p->invitestate = INV_COMPLETED;
-				if (!p->lastinvite) {
-					sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-				}
-				res = -1;
-				goto request_invite_cleanup;
-			}
-			break;
-
-		default:
-			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, 1)) {
-		case SESSION_TIMER_MODE_ORIGINATE:
-			st_active = TRUE;
-			st_interval = st_get_se(p, TRUE);
-			tmp_st_ref = SESSION_TIMER_REFRESHER_US;
-			p->stimer->st_active_peer_ua = FALSE;
-			break;
-
-		default:
-			break;
-		}
+		ast_party_redirecting_free(&redirecting);
 	}
 
-	if (reinvite == 0) {
-		/* Session-Timers: Start session refresh timer based on negotiation/config */
-		if (st_active == TRUE) {
-			p->stimer->st_active = TRUE;
-			p->stimer->st_interval = st_interval;
-			p->stimer->st_ref = tmp_st_ref;
+	if (p->stimer->st_active == TRUE) {
+		if (reinvite == 0) {
 			start_session_timer(p);
-		}
-	} else {
-		if (p->stimer->st_active == TRUE) {
-			/* Session-Timers:  A re-invite request sent within a dialog will serve as
-			a refresh request, no matter whether the re-invite was sent for refreshing
-			the session or modifying it.*/
-			ast_debug (2, "Restarting session-timers on a refresh - %s\n", p->callid);
-
-			/* The UAC may be adjusting the session-timers mid-session */
-			if (st_interval > 0) {
-				p->stimer->st_interval = st_interval;
-				p->stimer->st_ref      = tmp_st_ref;
-			}
-
+		} else {
 			restart_session_timer(p);
 			if (p->stimer->st_expirys > 0) {
 				p->stimer->st_expirys--;
