Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 304)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 305)
@@ -101,4 +101,6 @@
 
     void		*app_data;  /**< Application data.		    */
+    pj_timer_entry	 refresh_tm;/**< Timer to send re-INVITE.	    */
+    pj_timer_entry	 hangup_tm; /**< Timer to hangup call.		    */
 };
 
@@ -197,4 +199,6 @@
     /* User Agent behaviour: */
     int		     auto_answer;   /**< Automatically answer in calls.	*/
+    int		     uas_refresh;   /**< Time to re-INVITE.		*/
+    int		     uas_duration;  /**< Max call duration.		*/
 
     /* Account: */
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 304)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 305)
@@ -28,4 +28,72 @@
 
 #define THIS_FILE   "pjsua_inv.c"
+
+
+#define REFRESH_CALL_TIMER	0x63
+#define HANGUP_CALL_TIMER	0x64
+
+/* Proto */
+static void schedule_call_timer( pjsua_call *call, pj_timer_entry *e,
+				 int timer_type, int duration );
+
+/*
+ * Timer callback when UAS needs to send re-INVITE to see if remote
+ * is still there.
+ */
+static void call_on_timer(pj_timer_heap_t *ht, pj_timer_entry *e)
+{
+    pjsua_call *call = e->user_data;
+
+    PJ_UNUSED_ARG(ht);
+
+    if (e->id == REFRESH_CALL_TIMER) {
+
+	/* If call is still not connected, hangup. */
+	if (call->inv->state != PJSIP_INV_STATE_CONFIRMED) {
+	    PJ_LOG(3,(THIS_FILE, "Refresh call timer is called when "
+		      "invite is still not confirmed. Call %d will "
+		      "disconnect.", call->index));
+	    pjsua_call_hangup(call->index);
+	} else {
+	    PJ_LOG(3,(THIS_FILE, "Refreshing call %d", call->index));
+	    schedule_call_timer(call,e,REFRESH_CALL_TIMER,pjsua.uas_refresh);
+	    pjsua_call_reinvite(call->index);
+	}
+
+    } else if (e->id == HANGUP_CALL_TIMER) {
+	PJ_LOG(3,(THIS_FILE, "Call %d duration exceeded, disconnecting call",
+			     call->index));
+	pjsua_call_hangup(call->index);
+
+    }
+}
+
+/*
+ * Schedule call timer.
+ */
+static void schedule_call_timer( pjsua_call *call, pj_timer_entry *e,
+				 int timer_type, int duration )
+{
+    pj_time_val timeout;
+
+    if (duration == 0) {
+	/* Cancel timer. */
+	if (e->id != 0) {
+	    pjsip_endpt_cancel_timer(pjsua.endpt, e);
+	    e->id = 0;
+	}
+
+    } else {
+	/* Schedule timer. */
+	timeout.sec = duration;
+	timeout.msec = 0;
+
+	e->cb = &call_on_timer;
+	e->id = timer_type;
+	e->user_data = call;
+
+	pjsip_endpt_schedule_timer( pjsua.endpt, e, &timeout);
+    }
+}
 
 
@@ -335,4 +403,20 @@
     ++pjsua.call_cnt;
 
+    /* Schedule timer to refresh. */
+    if (pjsua.uas_refresh > 0) {
+	schedule_call_timer( &pjsua.calls[call_index], 
+			     &pjsua.calls[call_index].refresh_tm,
+			     REFRESH_CALL_TIMER,
+			     pjsua.uas_refresh);
+    }
+
+    /* Schedule timer to hangup call. */
+    if (pjsua.uas_duration > 0) {
+	schedule_call_timer( &pjsua.calls[call_index], 
+			     &pjsua.calls[call_index].hangup_tm,
+			     HANGUP_CALL_TIMER,
+			     pjsua.uas_duration);
+    }
+
     /* This INVITE request has been handled. */
     return PJ_TRUE;
@@ -419,4 +503,9 @@
 	}
 
+	/* Remove timers. */
+	schedule_call_timer(call, &call->refresh_tm, REFRESH_CALL_TIMER, 0);
+	schedule_call_timer(call, &call->hangup_tm, HANGUP_CALL_TIMER, 0);
+
+	/* Free call */
 	call->inv = NULL;
 	--pjsua.call_cnt;
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 304)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 305)
@@ -70,4 +70,8 @@
 
 
+    /* Default call settings. */
+    pjsua.uas_refresh = -1;
+    pjsua.uas_duration = -1;
+
     /* Default: do not use STUN: */
     pjsua.stun_port1 = pjsua.stun_port2 = 0;
@@ -91,6 +95,9 @@
 
     /* Init call array: */
-    for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i)
+    for (i=0; i<PJ_ARRAY_SIZE(pjsua.calls); ++i) {
 	pjsua.calls[i].index = i;
+	pjsua.calls[i].refresh_tm._timer_id = -1;
+	pjsua.calls[i].hangup_tm._timer_id = -1;
+    }
 
     /* Default max nb of calls. */
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c	(revision 304)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_settings.c	(revision 305)
@@ -102,4 +102,6 @@
     puts  ("  --auto-answer=code  Automatically answer incoming calls with code (e.g. 200)");
     puts  ("  --max-calls=N       Maximum number of concurrent calls (default:4, max:255)");
+    puts  ("  --uas-refresh=N     Interval in UAS to send re-INVITE (default:-1)");
+    puts  ("  --uas-duration=N    Maximum duration of incoming call (default:-1)");
     puts  ("");
     fflush(stdout);
@@ -226,5 +228,6 @@
 	   OPT_PLAY_FILE, OPT_WB, OPT_UWB, OPT_RTP_PORT, OPT_ADD_CODEC,
 	   OPT_COMPLEXITY, OPT_QUALITY,
-	   OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS,
+	   OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS, OPT_UAS_REFRESH,
+	   OPT_UAS_DURATION,
     };
     struct pj_getopt_option long_options[] = {
@@ -266,4 +269,6 @@
 	{ "next-cred",	0, 0, OPT_NEXT_CRED},
 	{ "max-calls",	1, 0, OPT_MAX_CALLS},
+	{ "uas-refresh",1, 0, OPT_UAS_REFRESH},
+	{ "uas-duration",1,0, OPT_UAS_DURATION},
 	{ NULL, 0, 0, 0}
     };
@@ -534,4 +539,20 @@
 	    if (pjsua.max_calls < 1 || pjsua.max_calls > 255) {
 		PJ_LOG(1,(THIS_FILE,"Too many calls for max-calls (1-255)"));
+		return -1;
+	    }
+	    break;
+
+	case OPT_UAS_REFRESH:
+	    pjsua.uas_refresh = my_atoi(pj_optarg);
+	    if (pjsua.uas_refresh < 1) {
+		PJ_LOG(1,(THIS_FILE,"Invalid value for --uas-refresh (must be >0)"));
+		return -1;
+	    }
+	    break;
+
+	case OPT_UAS_DURATION:
+	    pjsua.uas_duration = my_atoi(pj_optarg);
+	    if (pjsua.uas_duration < 1) {
+		PJ_LOG(1,(THIS_FILE,"Invalid value for --uas-duration (must be >0)"));
 		return -1;
 	    }
@@ -916,4 +937,17 @@
     pj_strcat2(&cfg, line);
 
+    /* Uas-refresh. */
+    if (pjsua.uas_refresh > 0) {
+	pj_ansi_sprintf(line, "--uas-refresh %d\n",
+			pjsua.uas_refresh);
+	pj_strcat2(&cfg, line);
+    }
+
+    /* Uas-duration. */
+    if (pjsua.uas_duration > 0) {
+	pj_ansi_sprintf(line, "--uas-duration %d\n",
+			pjsua.uas_duration);
+	pj_strcat2(&cfg, line);
+    }
 
     pj_strcat2(&cfg, "#\n# Buddies:\n#\n");
