Index: /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 3127)
+++ /pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 3128)
@@ -190,4 +190,5 @@
     puts  ("                      May be specified multiple times");
     puts  ("  --reg-timeout=SEC   Optional registration interval (default 55)");
+    puts  ("  --rereg-delay=SEC   Optional auto retry registration interval (default 300)");
     puts  ("  --realm=string      Set realm");
     puts  ("  --username=string   Set authentication username");
@@ -485,4 +486,5 @@
 	   OPT_BOUND_ADDR, OPT_CONTACT_PARAMS, OPT_CONTACT_URI_PARAMS,
 	   OPT_100REL, OPT_USE_IMS, OPT_REALM, OPT_USERNAME, OPT_PASSWORD,
+	   OPT_REG_RETRY_INTERVAL,
 	   OPT_MWI, OPT_NAMESERVER, OPT_STUN_SRV,
 	   OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE,
@@ -551,4 +553,5 @@
 	{ "username",	1, 0, OPT_USERNAME},
 	{ "password",	1, 0, OPT_PASSWORD},
+	{ "rereg-delay",1, 0, OPT_REG_RETRY_INTERVAL},
 	{ "nameserver", 1, 0, OPT_NAMESERVER},
 	{ "stun-srv",   1, 0, OPT_STUN_SRV},
@@ -960,4 +963,8 @@
 	    break;
 
+	case OPT_REG_RETRY_INTERVAL:
+	    cur_acc->reg_retry_interval = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+	    break;
+
 	case OPT_NEXT_CRED: /* next credential */
 	    cur_acc->cred_count++;
Index: /pjproject/trunk/pjsip/include/pjsip-ua/sip_regc.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip-ua/sip_regc.h	(revision 3127)
+++ /pjproject/trunk/pjsip/include/pjsip-ua/sip_regc.h	(revision 3128)
@@ -95,4 +95,5 @@
     int		interval;   /**< Registration interval (seconds).	    */
     int		next_reg;   /**< Time until next registration (seconds).    */
+    pjsip_transport *transport; /**< Last transport used.		    */
 };
 
Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 3127)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 3128)
@@ -1866,4 +1866,16 @@
 
 /**
+ * Default auto retry re-registration interval, in seconds. Set to 0
+ * to disable this. Application can set the timer on per account basis 
+ * by setting the pjsua_acc_config.reg_retry_interval field instead.
+ *
+ * Default: 300 (5 minutes)
+ */
+#ifndef PJSUA_REG_RETRY_INTERVAL
+#   define PJSUA_REG_RETRY_INTERVAL	300
+#endif
+
+
+/**
  * This structure describes account configuration to be specified when
  * adding a new account with #pjsua_acc_add(). Application MUST initialize
@@ -2116,4 +2128,22 @@
     int		     srtp_secure_signaling;
 #endif
+
+    /**
+     * Specify interval of auto registration retry upon registration failure
+     * (including caused by transport problem), in second. Set to 0 to
+     * disable auto re-registration.
+     *
+     * Default: #PJSUA_REG_RETRY_INTERVAL
+     */
+    unsigned	     reg_retry_interval;
+
+    /**
+     * Specify whether calls of the configured account should be dropped
+     * after registration failure and an attempt of re-registration has 
+     * also failed.
+     *
+     * Default: PJ_FALSE (disabled)
+     */
+    pj_bool_t	     drop_calls_on_reg_fail;
 
 } pjsua_acc_config;
Index: /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 3127)
+++ /pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 3128)
@@ -129,4 +129,11 @@
     int		     reg_last_code; /**< Last status last register.	*/
 
+    struct {
+	pj_bool_t	 active;    /**< Flag of reregister status.	*/
+	pj_timer_entry   timer;	    /**< Timer for reregistration.	*/
+	void		*reg_tp;    /**< Transport for registration.	*/
+	unsigned	 attempt_cnt; /**< Attempt counter.		*/
+    } auto_rereg;		    /**< Reregister/reconnect data.	*/
+
     pj_timer_entry   ka_timer;	    /**< Keep-alive timer for UDP.	*/
     pjsip_transport *ka_transport;  /**< Transport for keep-alive.	*/
Index: /pjproject/trunk/pjsip/src/pjsip-ua/sip_reg.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip-ua/sip_reg.c	(revision 3127)
+++ /pjproject/trunk/pjsip/src/pjsip-ua/sip_reg.c	(revision 3128)
@@ -204,4 +204,5 @@
     info->auto_reg = regc->auto_reg;
     info->interval = regc->expires;
+    info->transport = regc->last_transport;
     
     if (regc->has_tsx)
@@ -1203,4 +1204,9 @@
 	regc->current_op = REGC_REGISTERING;
 
+    /* Prevent deletion of tdata, e.g: when something wrong in sending,
+     * we need tdata to retrieve the transport.
+     */
+    pjsip_tx_data_add_ref(tdata);
+
     status = pjsip_endpt_send_request(regc->endpt, tdata, REGC_TSX_TIMEOUT,
 				      regc, &tsx_callback);
@@ -1209,4 +1215,20 @@
     }
 
+    /* Get last transport used and add reference to it */
+    if (tdata->tp_info.transport != regc->last_transport) {
+	if (regc->last_transport) {
+	    pjsip_transport_dec_ref(regc->last_transport);
+	    regc->last_transport = NULL;
+	}
+
+	if (tdata->tp_info.transport) {
+	    regc->last_transport = tdata->tp_info.transport;
+	    pjsip_transport_add_ref(regc->last_transport);
+	}
+    }
+
+    /* Release tdata */
+    pjsip_tx_data_dec_ref(tdata);
+
     pj_lock_release(regc->lock);
 
Index: /pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c	(revision 3127)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c	(revision 3128)
@@ -178,4 +178,10 @@
 	return;
 
+    /* Prevent immediate transport destroy by application, as transport
+     * state notification callback may be stacked and transport instance
+     * must remain valid at any point in the callback.
+     */
+    pjsip_transport_add_ref(&tcp->base);
+
     /* Notify application of transport disconnected state */
     state_cb = pjsip_tpmgr_get_status_cb(tcp->base.tpmgr);
@@ -194,4 +200,7 @@
      */
     pjsip_transport_shutdown(&tcp->base);
+
+    /* Now, it is ok to destroy the transport. */
+    pjsip_transport_dec_ref(&tcp->base);
 }
 
Index: /pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c	(revision 3127)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c	(revision 3128)
@@ -185,4 +185,10 @@
 	return;
 
+    /* Prevent immediate transport destroy by application, as transport
+     * state notification callback may be stacked and transport instance
+     * must remain valid at any point in the callback.
+     */
+    pjsip_transport_add_ref(&tls->base);
+
     /* Notify application of transport disconnected state */
     state_cb = pjsip_tpmgr_get_status_cb(tls->base.tpmgr);
@@ -201,4 +207,7 @@
      */
     pjsip_transport_shutdown(&tls->base);
+
+    /* Now, it is ok to destroy the transport. */
+    pjsip_transport_dec_ref(&tls->base);
 }
 
@@ -518,5 +527,5 @@
 {
     struct tls_transport *tls;
-    const pj_str_t ka_pkt = PJSIP_TCP_KEEP_ALIVE_DATA;
+    const pj_str_t ka_pkt = PJSIP_TLS_KEEP_ALIVE_DATA;
     pj_status_t status;
     
@@ -579,5 +588,10 @@
     sockaddr_to_host_port(pool, &tls->base.local_name, 
 			  (pj_sockaddr_in*)&tls->base.local_addr);
-    sockaddr_to_host_port(pool, &tls->base.remote_name, remote);
+    if (tls->remote_name.slen) {
+	tls->base.remote_name.host = tls->remote_name;
+	tls->base.remote_name.port = pj_sockaddr_in_get_port(remote);
+    } else {
+	sockaddr_to_host_port(pool, &tls->base.remote_name, remote);
+    }
 
     tls->base.endpt = listener->endpt;
@@ -1076,6 +1090,6 @@
     } else {
 	/* Start keep-alive timer */
-	if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) {
-	    pj_time_val delay = {PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0};
+	if (PJSIP_TLS_KEEP_ALIVE_INTERVAL) {
+	    pj_time_val delay = {PJSIP_TLS_KEEP_ALIVE_INTERVAL, 0};
 	    pjsip_endpt_schedule_timer(listener->endpt, 
 				       &tls->ka_timer, 
@@ -1508,6 +1522,6 @@
 
     /* Start keep-alive timer */
-    if (PJSIP_TCP_KEEP_ALIVE_INTERVAL) {
-	pj_time_val delay = { PJSIP_TCP_KEEP_ALIVE_INTERVAL, 0 };
+    if (PJSIP_TLS_KEEP_ALIVE_INTERVAL) {
+	pj_time_val delay = { PJSIP_TLS_KEEP_ALIVE_INTERVAL, 0 };
 	pjsip_endpt_schedule_timer(tls->base.endpt, &tls->ka_timer, 
 				   &delay);
@@ -1541,7 +1555,7 @@
     PJ_TIME_VAL_SUB(now, tls->last_activity);
 
-    if (now.sec > 0 && now.sec < PJSIP_TCP_KEEP_ALIVE_INTERVAL) {
+    if (now.sec > 0 && now.sec < PJSIP_TLS_KEEP_ALIVE_INTERVAL) {
 	/* There has been activity, so don't send keep-alive */
-	delay.sec = PJSIP_TCP_KEEP_ALIVE_INTERVAL - now.sec;
+	delay.sec = PJSIP_TLS_KEEP_ALIVE_INTERVAL - now.sec;
 	delay.msec = 0;
 
@@ -1571,5 +1585,5 @@
 
     /* Register next keep-alive */
-    delay.sec = PJSIP_TCP_KEEP_ALIVE_INTERVAL;
+    delay.sec = PJSIP_TLS_KEEP_ALIVE_INTERVAL;
     delay.msec = 0;
 
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 3127)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 3128)
@@ -25,4 +25,6 @@
 
 
+static void schedule_reregistration(pjsua_acc *acc);
+
 /*
  * Get number of current accounts.
@@ -442,4 +444,7 @@
 
     PJSUA_LOCK();
+
+    /* Cancel any re-registration timer */
+    pjsua_cancel_timer(&pjsua_var.acc[acc_id].auto_rereg.timer);
 
     /* Delete registration */
@@ -1032,4 +1037,8 @@
     } else if (PJSIP_IS_STATUS_IN_CLASS(param->code, 200)) {
 
+	/* Update auto registration flag */
+	acc->auto_rereg.active = PJ_FALSE;
+	acc->auto_rereg.attempt_cnt = 0;
+
 	if (param->expiration < 1) {
 	    pjsip_regc_destroy(acc->regc);
@@ -1082,4 +1091,19 @@
     if (pjsua_var.ua_cfg.cb.on_reg_state)
 	(*pjsua_var.ua_cfg.cb.on_reg_state)(acc->index);
+
+    /* Check if we need to auto retry registration. Basically, registration
+     * failure codes triggering auto-retry are those of temporal failures
+     * considered to be recoverable in relatively short term.
+     */
+    if (acc->cfg.reg_retry_interval && 
+	(param->code == PJSIP_SC_REQUEST_TIMEOUT ||
+	 param->code == PJSIP_SC_INTERNAL_SERVER_ERROR ||
+	 param->code == PJSIP_SC_BAD_GATEWAY ||
+	 param->code == PJSIP_SC_SERVICE_UNAVAILABLE ||
+	 param->code == PJSIP_SC_SERVER_TIMEOUT ||
+	 PJSIP_IS_STATUS_IN_CLASS(param->code, 600))) /* Global failure */
+    {
+	schedule_reregistration(acc);
+    }
 
     PJSUA_UNLOCK();
@@ -1221,4 +1245,10 @@
     PJSUA_LOCK();
 
+    /* Cancel any re-registration timer */
+    pjsua_cancel_timer(&pjsua_var.acc[acc_id].auto_rereg.timer);
+
+    /* Reset pointer to registration transport */
+    pjsua_var.acc[acc_id].auto_rereg.reg_tp = NULL;
+
     if (renew) {
 	if (pjsua_var.acc[acc_id].regc == NULL) {
@@ -1274,4 +1304,12 @@
 	//pjsua_process_msg_data(tdata, NULL);
 	status = pjsip_regc_send( pjsua_var.acc[acc_id].regc, tdata );
+    }
+
+    /* Update pointer to registration transport */
+    if (status == PJ_SUCCESS) {
+	pjsip_regc_info reg_info;
+
+	pjsip_regc_get_info(pjsua_var.acc[acc_id].regc, &reg_info);
+	pjsua_var.acc[acc_id].auto_rereg.reg_tp = reg_info.transport;
     }
 
@@ -1926,2 +1964,121 @@
 }
 
+
+/* Auto re-registration timeout callback */
+static void auto_rereg_timer_cb(pj_timer_heap_t *th, pj_timer_entry *te)
+{
+    pjsua_acc *acc;
+    pj_status_t status;
+
+    PJ_UNUSED_ARG(th);
+    acc = (pjsua_acc*) te->user_data;
+    pj_assert(acc);
+
+    PJSUA_LOCK();
+
+    if (!acc->valid || !acc->auto_rereg.active)
+	goto on_return;
+
+    /* Start re-registration */
+    acc->auto_rereg.attempt_cnt++;
+    status = pjsua_acc_set_registration(acc->index, PJ_TRUE);
+    if (status != PJ_SUCCESS)
+	schedule_reregistration(acc);
+
+    /* If configured, disconnect calls of this account after the first
+     * reregistration attempt failed.
+     */
+    if (acc->cfg.drop_calls_on_reg_fail && acc->auto_rereg.attempt_cnt > 1)
+    {
+	unsigned i, cnt;
+
+	for (i = 0, cnt = 0; i < pjsua_var.ua_cfg.max_calls; ++i) {
+	    if (pjsua_var.calls[i].acc_id == acc->index) {
+		pjsua_call_hangup(i, 0, NULL, NULL);
+		++cnt;
+	    }
+	}
+
+	if (cnt) {
+	    PJ_LOG(3, (THIS_FILE, "Disconnecting %d call(s) of account #%d "
+				  "after reregistration attempt failed",
+				  cnt, acc->index));
+	}
+    }
+
+on_return:
+
+    PJSUA_UNLOCK();
+}
+
+
+/* Schedule reregistration for specified account. Note that the first 
+ * re-registration after a registration failure will be done immediately.
+ * Also note that this function should be called within PJSUA mutex.
+ */
+static void schedule_reregistration(pjsua_acc *acc)
+{
+    pj_time_val delay;
+
+    pj_assert(acc && acc->valid && acc->cfg.reg_retry_interval);
+
+    /* Cancel any re-registration timer */
+    pjsua_cancel_timer(&acc->auto_rereg.timer);
+
+    /* Update re-registration flag */
+    acc->auto_rereg.active = PJ_TRUE;
+
+    /* Set up timer for reregistration */
+    acc->auto_rereg.timer.cb = &auto_rereg_timer_cb;
+    acc->auto_rereg.timer.user_data = acc;
+
+    /* Reregistration attempt. The first attempt will be done immediately. */
+    delay.sec = acc->auto_rereg.attempt_cnt? acc->cfg.reg_retry_interval : 0;
+    delay.msec = 0;
+    pjsua_schedule_timer(&acc->auto_rereg.timer, &delay);
+}
+
+
+/* Internal function to perform auto-reregistration on transport 
+ * connection/disconnection events.
+ */
+void pjsua_acc_on_tp_state_changed(pjsip_transport *tp,
+				   pjsip_transport_state state,
+				   const pjsip_transport_state_info *info)
+{
+    unsigned i;
+
+    PJ_UNUSED_ARG(info);
+
+    /* Only care for transport disconnection events */
+    if (state != PJSIP_TP_STATE_DISCONNECTED)
+	return;
+
+    /* Shutdown this transport, to make sure that the transport manager 
+     * will create a new transport for reconnection.
+     */
+    pjsip_transport_shutdown(tp);
+
+    PJSUA_LOCK();
+
+    /* Enumerate accounts using this transport and perform actions
+     * based on the transport state.
+     */
+    for (i = 0; i < PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
+	pjsua_acc *acc = &pjsua_var.acc[i];
+
+	/* Skip if this account is not valid OR auto re-registration
+	 * feature is disabled OR this transport is not used by this account.
+	 */
+	if (!acc->valid || !acc->cfg.reg_retry_interval || 
+	    tp != acc->auto_rereg.reg_tp)
+	{
+	    continue;
+	}
+
+	/* Schedule reregistration for this account */
+	schedule_reregistration(acc);
+    }
+
+    PJSUA_UNLOCK();
+}
Index: /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 3127)
+++ /pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 3128)
@@ -177,4 +177,5 @@
     cfg->srtp_secure_signaling = pjsua_var.ua_cfg.srtp_secure_signaling;
 #endif
+    cfg->reg_retry_interval = PJSUA_REG_RETRY_INTERVAL;
 }
 
@@ -1526,4 +1527,8 @@
 }
 
+void pjsua_acc_on_tp_state_changed(pjsip_transport *tp,
+				   pjsip_transport_state state,
+				   const pjsip_transport_state_info *info);
+
 /* Callback to receive transport state notifications */
 static void on_tp_state_callback(pjsip_transport *tp,
@@ -1537,4 +1542,5 @@
 	(*pjsua_var.old_tp_cb)(tp, state, info);
     }
+    pjsua_acc_on_tp_state_changed(tp, state, info);
 }
 
