Index: /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 2858)
+++ /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 2859)
@@ -839,6 +839,6 @@
 
 	case OPT_TIMER_SE: /** session timer session expiration */
-	    cur_acc->timer_se = pj_strtoul(pj_cstr(&tmp, pj_optarg));
-	    if (cur_acc->timer_se < 90) {
+	    cur_acc->timer_setting.sess_expires = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+	    if (cur_acc->timer_setting.min_se < 90) {
 		PJ_LOG(1,(THIS_FILE, 
 			  "Error: invalid value for --timer-se "
@@ -846,10 +846,10 @@
 		return PJ_EINVAL;
 	    }
-	    cfg->cfg.timer_se = cur_acc->timer_se;
+	    cfg->cfg.timer_setting.sess_expires = cur_acc->timer_setting.sess_expires;
 	    break;
 
 	case OPT_TIMER_MIN_SE: /** session timer minimum session expiration */
-	    cur_acc->timer_min_se = pj_strtoul(pj_cstr(&tmp, pj_optarg));
-	    if (cur_acc->timer_min_se < 90) {
+	    cur_acc->timer_setting.min_se = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+	    if (cur_acc->timer_setting.min_se < 90) {
 		PJ_LOG(1,(THIS_FILE, 
 			  "Error: invalid value for --timer-min-se "
@@ -857,5 +857,5 @@
 		return PJ_EINVAL;
 	    }
-	    cfg->cfg.timer_min_se = cur_acc->timer_min_se;
+	    cfg->cfg.timer_setting.min_se = cur_acc->timer_setting.min_se;
 	    break;
 
Index: /pjproject/trunk/pjsip-apps/src/python/_pjsua.h
===================================================================
--- /pjproject/trunk/pjsip-apps/src/python/_pjsua.h	(revision 2858)
+++ /pjproject/trunk/pjsip-apps/src/python/_pjsua.h	(revision 2859)
@@ -1735,6 +1735,6 @@
     obj->require_100rel = cfg->require_100rel;
     obj->require_timer = cfg->require_timer;
-    obj->timer_se = cfg->timer_se;
-    obj->timer_min_se = cfg->timer_min_se;
+    obj->timer_se = cfg->timer_setting.sess_expires;
+    obj->timer_min_se = cfg->timer_setting.min_se;
     obj->allow_contact_rewrite = cfg->allow_contact_rewrite;
     obj->ka_interval = cfg->ka_interval;
@@ -1784,6 +1784,6 @@
     cfg->require_100rel = obj->require_100rel;
     cfg->require_timer = obj->require_timer;
-    cfg->timer_se = obj->timer_se;
-    cfg->timer_min_se = obj->timer_min_se;
+    cfg->timer_setting.sess_expires = obj->timer_se;
+    cfg->timer_setting.min_se = obj->timer_min_se;
     cfg->allow_contact_rewrite = obj->allow_contact_rewrite;
     cfg->ka_interval = obj->ka_interval;
Index: /pjproject/trunk/pjsip/include/pjsip-ua/sip_timer.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip-ua/sip_timer.h	(revision 2858)
+++ /pjproject/trunk/pjsip/include/pjsip-ua/sip_timer.h	(revision 2859)
@@ -126,5 +126,5 @@
  * @return		PJ_SUCCESS on successful.
  */
-PJ_DECL(pj_status_t) pjsip_timer_default_setting(pjsip_timer_setting *setting);
+PJ_DECL(pj_status_t) pjsip_timer_setting_default(pjsip_timer_setting *setting);
 
 
@@ -192,9 +192,12 @@
  * @param inv		The invite session.
  * @param rdata		Incoming response data.
+ * @param st_code	Output buffer to store corresponding SIP status code 
+ *			when function returning non-PJ_SUCCESS.
  *
  * @return		PJ_SUCCESS on successful.
  */
 PJ_DECL(pj_status_t) pjsip_timer_process_resp(pjsip_inv_session *inv,
-					      const pjsip_rx_data *rdata);
+					      const pjsip_rx_data *rdata,
+					      pjsip_status_code *st_code);
 
 
@@ -208,9 +211,12 @@
  * @param inv		The invite session.
  * @param rdata		Incoming INVITE or UPDATE request.
+ * @param st_code	Output buffer to store corresponding SIP status code 
+ *			when function returning non-PJ_SUCCESS.
  *
  * @return		PJ_SUCCESS on successful.
  */
 PJ_DECL(pj_status_t) pjsip_timer_process_req(pjsip_inv_session *inv,
-					     const pjsip_rx_data *rdata);
+					     const pjsip_rx_data *rdata,
+					     pjsip_status_code *st_code);
 
 
Index: /pjproject/trunk/pjsip/include/pjsip/sip_config.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 2858)
+++ /pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 2859)
@@ -884,4 +884,17 @@
 
 
+/**
+ * Default session interval for Session Timer (RFC 4028) extension, in
+ * seconds. As specified in RFC 4028 Section 4, this value must not be 
+ * less than the absolute minimum for the Session-Expires header field
+ * 90 seconds, and the recommended value is 1800 seconds.
+ *
+ * Default: 1800 seconds
+ */
+#ifndef PJSIP_SESS_TIMER_DEF_SE
+#   define PJSIP_SESS_TIMER_DEF_SE		1800
+#endif
+
+
 PJ_END_DECL
 
Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 2858)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 2859)
@@ -937,20 +937,9 @@
 
     /**
-     * Specify session expiration period of Session Timers, in seconds. 
+     * Specify Session Timer settings, see #pjsip_timer_setting. 
      * Note that this setting can be further customized in account 
      * configuration (#pjsua_acc_config).
-     *
-     * Default: 1800 (seconds)
-     */
-    unsigned	    timer_se;
-
-    /**
-     * Specify minimum session expiration period of Session Timers, 
-     * in seconds. Note that this setting can be further customized in 
-     * account configuration (#pjsua_acc_config).
-     *
-     * Default: 90 (seconds)
-     */
-    unsigned	    timer_min_se;
+     */
+    pjsip_timer_setting timer_setting;
 
     /** 
@@ -1734,18 +1723,7 @@
 
     /**
-     * Specify session expiration period of Session Timers, in seconds,
-     * for this account. 
-     *
-     * Default: 1800 (seconds)
-     */
-    unsigned	    timer_se;
-
-    /**
-     * Specify minimum session expiration period of Session Timers, 
-     * in seconds, for this account.
-     *
-     * Default: 90 (seconds)
-     */
-    unsigned	    timer_min_se;
+     * Specify Session Timer settings, see #pjsip_timer_setting. 
+     */
+    pjsip_timer_setting timer_setting;
 
     /**
Index: /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 2858)
+++ /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 2859)
@@ -485,4 +485,5 @@
     pjsip_msg *msg = rdata->msg_info.msg;
     pj_status_t status;
+    pjsip_status_code st_code;
 
     dlg = pjsip_rdata_get_dlg(rdata);
@@ -513,5 +514,5 @@
 
     /* Pass response to timer session module */
-    status = pjsip_timer_process_resp(inv, rdata);
+    status = pjsip_timer_process_resp(inv, rdata, &st_code);
     if (status != PJ_SUCCESS) {
 	pjsip_event e;
@@ -521,6 +522,5 @@
 	inv_send_ack(inv, &e);
 
-	status = pjsip_inv_end_session(inv, PJSIP_ERRNO_TO_SIP_STATUS(status),
-				       NULL, &tdata);
+	status = pjsip_inv_end_session(inv, st_code, NULL, &tdata);
 	if (tdata && status == PJ_SUCCESS)
 	    pjsip_inv_send_msg(inv, tdata);
@@ -975,6 +975,6 @@
     if ( ((*options & PJSIP_INV_REQUIRE_100REL)!=0 && 
 	  (rem_option & PJSIP_INV_SUPPORT_100REL)==0) ||
-	 ((*options & PJSIP_INV_REQUIRE_100REL)!=0 && 
-	  (rem_option & PJSIP_INV_SUPPORT_100REL)==0))
+	 ((*options & PJSIP_INV_REQUIRE_TIMER)!=0 && 
+	  (rem_option & PJSIP_INV_SUPPORT_TIMER)==0))
     {
 	code = PJSIP_SC_EXTENSION_REQUIRED;
@@ -1756,4 +1756,5 @@
     pjsip_tx_data *tdata;
     pj_status_t status;
+    pjsip_status_code st_code2;
 
     /* Verify arguments. */
@@ -1772,11 +1773,9 @@
 
     /* Invoke Session Timers module */
-    status = pjsip_timer_process_req(inv, rdata);
+    status = pjsip_timer_process_req(inv, rdata, &st_code2);
     if (status != PJ_SUCCESS) {
 	pj_status_t status2;
 
-	status2 = pjsip_dlg_modify_response(inv->dlg, tdata, 
-					    PJSIP_ERRNO_TO_SIP_STATUS(status),
-					    NULL);
+	status2 = pjsip_dlg_modify_response(inv->dlg, tdata, st_code2, NULL);
 	if (status2 != PJ_SUCCESS) {
 	    pjsip_tx_data_dec_ref(tdata);
@@ -2639,10 +2638,10 @@
     pj_status_t status;
     pjsip_tx_data *tdata = NULL;
+    pjsip_status_code st_code;
 
     /* Invoke Session Timers module */
-    status = pjsip_timer_process_req(inv, rdata);
+    status = pjsip_timer_process_req(inv, rdata, &st_code);
     if (status != PJ_SUCCESS) {
-	status = pjsip_dlg_create_response(inv->dlg, rdata, 
-					   PJSIP_ERRNO_TO_SIP_STATUS(status),
+	status = pjsip_dlg_create_response(inv->dlg, rdata, st_code,
 					   NULL, &tdata);
 	goto on_return;
@@ -3660,4 +3659,5 @@
 	    pjsip_tx_data *tdata;
 	    pj_status_t status;
+	    pjsip_status_code st_code;
 
 	    /* Check if we have INVITE pending. */
@@ -3683,9 +3683,8 @@
 
 	    /* Process session timers headers in the re-INVITE */
-	    status = pjsip_timer_process_req(inv, rdata);
+	    status = pjsip_timer_process_req(inv, rdata, &st_code);
 	    if (status != PJ_SUCCESS) {
-		status = pjsip_dlg_create_response(inv->dlg, rdata, 
-					   PJSIP_ERRNO_TO_SIP_STATUS(status), 
-					   NULL, &tdata);
+		status = pjsip_dlg_create_response(inv->dlg, rdata, st_code,
+						   NULL, &tdata);
 		if (status != PJ_SUCCESS)
 		    return;
Index: /pjproject/trunk/pjsip/src/pjsip-ua/sip_timer.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip-ua/sip_timer.c	(revision 2858)
+++ /pjproject/trunk/pjsip/src/pjsip-ua/sip_timer.c	(revision 2859)
@@ -28,7 +28,6 @@
 
 
-/* Constant values of Session Timers */
+/* Constant of Session Timers */
 #define ABS_MIN_SE		90	/* Absolute Min-SE, in seconds	    */
-#define DEF_SE			1800	/* Default SE, in seconds	    */
 
 
@@ -61,4 +60,6 @@
     pj_bool_t			 use_update;	/**< Use UPDATE method to
 						     refresh the session    */
+    pjsip_role_e		 role;		/**< Role in last INVITE/
+						     UPDATE transaction.    */
 
 } pjsip_timer;
@@ -121,4 +122,8 @@
     const pj_str_t *hname = pjsip_use_compact_form? &hdr->sname : &hdr->name;
 
+    /* Print header name and value */
+    if ((endbuf - p) < (hname->slen + 16))
+	return -1;
+
     copy_advance(p, (*hname));
     *p++ = ':';
@@ -128,6 +133,10 @@
     p += printed;
 
-    if (hdr->refresher.slen && (endbuf-p) > (hdr->refresher.slen + 2))
+    /* Print 'refresher' param */
+    if (hdr->refresher.slen)
     {
+	if  ((endbuf - p) < (STR_REFRESHER.slen + 2 + hdr->refresher.slen))
+	    return -1;
+
 	*p++ = ';';
 	copy_advance(p, STR_REFRESHER);
@@ -136,4 +145,5 @@
     }
 
+    /* Print generic params */
     printed = pjsip_param_print_on(&hdr->other_param, p, endbuf-p,
 				   &pc->pjsip_TOKEN_SPEC, 
@@ -177,4 +187,8 @@
     const pjsip_parser_const_t *pc = pjsip_parser_const();
 
+    /* Print header name and value */
+    if ((endbuf - p) < (hdr->name.slen + 16))
+	return -1;
+
     copy_advance(p, hdr->name);
     *p++ = ':';
@@ -184,4 +198,5 @@
     p += printed;
 
+    /* Print generic params */
     printed = pjsip_param_print_on(&hdr->other_param, p, endbuf-p,
 				   &pc->pjsip_TOKEN_SPEC, 
@@ -324,6 +339,6 @@
     /* Check our role */
     as_refresher = 
-	(inv->timer->refresher == TR_UAC && inv->role == PJSIP_ROLE_UAC) ||
-	(inv->timer->refresher == TR_UAS && inv->role == PJSIP_ROLE_UAS);
+	(inv->timer->refresher == TR_UAC && inv->timer->role == PJSIP_ROLE_UAC) ||
+	(inv->timer->refresher == TR_UAS && inv->timer->role == PJSIP_ROLE_UAS);
 
     /* Do action based on role, refresher or refreshee */
@@ -418,6 +433,6 @@
     
     /* Set delay based on role, refresher or refreshee */
-    if ((timer->refresher == TR_UAC && inv->role == PJSIP_ROLE_UAC) ||
-	(timer->refresher == TR_UAS && inv->role == PJSIP_ROLE_UAS))
+    if ((timer->refresher == TR_UAC && inv->timer->role == PJSIP_ROLE_UAC) ||
+	(timer->refresher == TR_UAS && inv->timer->role == PJSIP_ROLE_UAS))
     {
 	/* Next refresh, the delay is half of session expire */
@@ -488,9 +503,9 @@
  * Initialize Session Timers setting with default values.
  */
-PJ_DEF(pj_status_t) pjsip_timer_default_setting(pjsip_timer_setting *setting)
+PJ_DEF(pj_status_t) pjsip_timer_setting_default(pjsip_timer_setting *setting)
 {
     pj_bzero(setting, sizeof(pjsip_timer_setting));
 
-    setting->sess_expires = DEF_SE;
+    setting->sess_expires = PJSIP_SESS_TIMER_DEF_SE;
     setting->min_se = ABS_MIN_SE;
 
@@ -527,5 +542,5 @@
 	pj_memcpy(s, setting, sizeof(*s));
     } else {
-	pjsip_timer_default_setting(s);
+	pjsip_timer_setting_default(s);
     }
 
@@ -605,9 +620,11 @@
  */
 PJ_DEF(pj_status_t) pjsip_timer_process_resp(pjsip_inv_session *inv,
-					     const pjsip_rx_data *rdata)
+					     const pjsip_rx_data *rdata,
+					     pjsip_status_code *st_code)
 {
     const pjsip_msg *msg;
 
-    PJ_ASSERT_RETURN(inv && rdata, PJ_EINVAL);
+    PJ_ASSERT_ON_FAIL(inv && rdata,
+	{if(st_code)*st_code=PJSIP_SC_INTERNAL_SERVER_ERROR;return PJ_EINVAL;});
 
     /* Check if Session Timers is supported */
@@ -705,4 +722,6 @@
 	     */
 	    if (inv->options & PJSIP_INV_REQUIRE_TIMER) {
+		if (st_code)
+		    *st_code = PJSIP_SC_EXTENSION_REQUIRED;
 		pjsip_timer_end_session(inv);
 		return PJSIP_ERRNO_FROM_SIP_STATUS(
@@ -727,4 +746,6 @@
 	    se_hdr->sess_expires < inv->timer->setting.min_se)
 	{
+	    if (st_code)
+		*st_code = PJSIP_SC_SESSION_TIMER_TOO_SMALL;
 	    pjsip_timer_end_session(inv);
 	    return PJSIP_ERRNO_FROM_SIP_STATUS(
@@ -758,4 +779,7 @@
 	PJ_TODO(CHECK_IF_REMOTE_SUPPORT_UPDATE);
 
+	/* Remember our role in this transaction */
+	inv->timer->role = PJSIP_ROLE_UAC;
+
 	/* Finally, set active flag and start the Session Timers */
 	inv->timer->active = PJ_TRUE;
@@ -770,5 +794,6 @@
  */
 PJ_DEF(pj_status_t) pjsip_timer_process_req(pjsip_inv_session *inv,
-					    const pjsip_rx_data *rdata)
+					    const pjsip_rx_data *rdata,
+					    pjsip_status_code *st_code)
 {
     pjsip_min_se_hdr *min_se_hdr;
@@ -777,5 +802,6 @@
     unsigned min_se;
 
-    PJ_ASSERT_RETURN(inv && rdata, PJ_EINVAL);
+    PJ_ASSERT_ON_FAIL(inv && rdata,
+	{if(st_code)*st_code=PJSIP_SC_INTERNAL_SERVER_ERROR;return PJ_EINVAL;});
 
     /* Check if Session Timers is supported */
@@ -828,6 +854,9 @@
      * (or 90 seconds if Min-SE is not set).
      */
-    if (se_hdr && se_hdr->sess_expires < min_se)
+    if (se_hdr && se_hdr->sess_expires < min_se) {
+	if (st_code)
+	    *st_code = PJSIP_SC_SESSION_TIMER_TOO_SMALL;
 	return PJSIP_ERRNO_FROM_SIP_STATUS(PJSIP_SC_SESSION_TIMER_TOO_SMALL);
+    }
 
     /* Update SE. Note that there is a case that SE is not available in the
@@ -882,6 +911,9 @@
     if (msg->line.status.code/100 == 2)
     {
-	/* Add Session-Expires header and start the timer */
 	if (inv->timer && inv->timer->active) {
+	    /* Remember our role in this transaction */
+	    inv->timer->role = PJSIP_ROLE_UAS;
+
+	    /* Add Session-Expires header and start the timer */
 	    add_timer_headers(inv, tdata, PJ_TRUE, PJ_FALSE);
 	    start_timer(inv);
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 2858)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 2859)
@@ -493,16 +493,8 @@
 
     /* Init Session Timers */
-    {
-	pjsip_timer_setting timer_setting;
-
-	pjsip_timer_default_setting(&timer_setting);
-	timer_setting.sess_expires = acc->cfg.timer_se;
-	timer_setting.min_se = acc->cfg.timer_min_se;
-
-	status = pjsip_timer_init_session(inv, &timer_setting);
-	if (status != PJ_SUCCESS) {
-	    pjsua_perror(THIS_FILE, "Session Timer init failed", status);
-	    goto on_error;
-	}
+    status = pjsip_timer_init_session(inv, &acc->cfg.timer_setting);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror(THIS_FILE, "Session Timer init failed", status);
+	goto on_error;
     }
 
@@ -917,24 +909,17 @@
 
     /* Init Session Timers */
-    {
-	pjsip_timer_setting timer_setting;
-
-	pjsip_timer_default_setting(&timer_setting);
-	timer_setting.sess_expires = pjsua_var.acc[acc_id].cfg.timer_se;
-	timer_setting.min_se = pjsua_var.acc[acc_id].cfg.timer_min_se;
-
-	status = pjsip_timer_init_session(inv, &timer_setting);
-	if (status != PJ_SUCCESS) {
-	    pjsua_perror(THIS_FILE, "Session Timer init failed", status);
-	    status = pjsip_inv_end_session(inv, PJSIP_SC_INTERNAL_SERVER_ERROR,
-					   NULL, &response);
-	    if (status == PJ_SUCCESS && response)
-		status = pjsip_inv_send_msg(inv, response);
-
-	    pjsua_media_channel_deinit(call->index);
-
-	    PJSUA_UNLOCK();
-	    return PJ_TRUE;
-	}
+    status = pjsip_timer_init_session(inv, 
+				    &pjsua_var.acc[acc_id].cfg.timer_setting);
+    if (status != PJ_SUCCESS) {
+	pjsua_perror(THIS_FILE, "Session Timer init failed", status);
+	status = pjsip_inv_end_session(inv, PJSIP_SC_INTERNAL_SERVER_ERROR,
+				       NULL, &response);
+	if (status == PJ_SUCCESS && response)
+	    status = pjsip_inv_send_msg(inv, response);
+
+	pjsua_media_channel_deinit(call->index);
+
+	PJSUA_UNLOCK();
+	return PJ_TRUE;
     }
 
@@ -979,5 +964,5 @@
 	} else {
 	    pjsip_inv_send_msg(inv, response);
-	    pjsip_inv_terminate(inv, PJSIP_ERRNO_TO_SIP_STATUS(status), 
+	    pjsip_inv_terminate(inv, response->msg->line.status.code, 
 				PJ_FALSE);
 	}
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 2858)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 2859)
@@ -88,6 +88,4 @@
 PJ_DEF(void) pjsua_config_default(pjsua_config *cfg)
 {
-    pjsip_timer_setting timer_setting;
-
     pj_bzero(cfg, sizeof(*cfg));
 
@@ -102,7 +100,5 @@
     cfg->hangup_forked_call = PJ_TRUE;
 
-    pjsip_timer_default_setting(&timer_setting);
-    cfg->timer_se = timer_setting.sess_expires;
-    cfg->timer_min_se = timer_setting.min_se;
+    pjsip_timer_setting_default(&cfg->timer_setting);
 }
 
@@ -158,6 +154,5 @@
     cfg->require_100rel = pjsua_var.ua_cfg.require_100rel;
     cfg->require_timer = pjsua_var.ua_cfg.require_timer;
-    cfg->timer_se = pjsua_var.ua_cfg.timer_se;
-    cfg->timer_min_se = pjsua_var.ua_cfg.timer_min_se;
+    cfg->timer_setting = pjsua_var.ua_cfg.timer_setting;
     cfg->ka_interval = 15;
     cfg->ka_data = pj_str("\r\n");
