Index: pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 1888)
+++ pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 1889)
@@ -695,5 +695,5 @@
 
 	case OPT_AUTO_UPDATE_NAT:   /* OPT_AUTO_UPDATE_NAT */
-            cur_acc->auto_update_nat  = pj_strtoul(pj_cstr(&tmp, pj_optarg));
+            cur_acc->allow_contact_rewrite  = pj_strtoul(pj_cstr(&tmp, pj_optarg));
 	    break;
 
@@ -1149,8 +1149,8 @@
 
     /*  */
-    //if (acc_cfg->auto_update_nat)
+    if (acc_cfg->allow_contact_rewrite==0)
     {
-	pj_ansi_sprintf(line, "--auto-update-nat %i\n",
-			(int)acc_cfg->auto_update_nat);
+	pj_ansi_sprintf(line, "--contact-rewrite %i\n",
+			(int)acc_cfg->allow_contact_rewrite);
 	pj_strcat2(result, line);
     }
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 1888)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 1889)
@@ -2027,15 +2027,16 @@
 
     /**
-     * This option is useful for keeping the UDP transport address up to
-     * date with the NAT public mapped address. When this option is 
-     * enabled and STUN is configured, the library will keep track of
-     * the public IP address from the response of REGISTER request. Once
-     * it detects that the address has changed, it will unregister current
-     * Contact, update the UDP transport address, and register a new
-     * Contact to the registrar.
+     * This option is used to update the UDP transport address and the Contact
+     * header of REGISTER request. When this option is  enabled, the library 
+     * will keep track of the public IP address from the response of REGISTER
+     * request. Once it detects that the address has changed, it will 
+     * unregister current Contact, update the Contact with transport address
+     * learned from Via header, and register a new Contact to the registrar.
+     * This will also update the public name of UDP transport if STUN is
+     * configured.
      *
      * Default: 1 (yes)
      */
-    pj_bool_t auto_update_nat;
+    pj_bool_t allow_contact_rewrite;
 
     /**
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 1888)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 1889)
@@ -85,4 +85,5 @@
     pj_str_t	     display;	    /**< Display name, if any.		*/
     pj_str_t	     user_part;	    /**< User part of local URI.	*/
+    pj_str_t	     contact;	    /**< Our Contact URI for REGISTER	*/
 
     pj_str_t	     srv_domain;    /**< Host part of reg server.	*/
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 1888)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 1889)
@@ -485,5 +485,7 @@
     pjsip_transport *tp;
     const pj_str_t *via_addr;
+    pj_pool_t *pool;
     int rport;
+    pjsip_sip_uri *uri;
     pjsip_via_hdr *via;
 
@@ -491,17 +493,25 @@
 
     /* Only update if account is configured to auto-update */
-    if (acc->cfg.auto_update_nat == PJ_FALSE)
+    if (acc->cfg.allow_contact_rewrite == PJ_FALSE)
 	return PJ_FALSE;
 
-    /* Only update if registration uses UDP transport */
-    if (tp->key.type != PJSIP_TRANSPORT_UDP)
+#if 0
+    // Always update
+    // See http://lists.pjsip.org/pipermail/pjsip_lists.pjsip.org/2008-March/002178.html
+
+    /* For UDP, only update if STUN is enabled (for now).
+     * For TCP/TLS, always check.
+     */
+    if ((tp->key.type == PJSIP_TRANSPORT_UDP &&
+	 (pjsua_var.ua_cfg.stun_domain.slen != 0 ||
+	 (pjsua_var.ua_cfg.stun_host.slen != 0))  ||
+	(tp->key.type == PJSIP_TRANSPORT_TCP) ||
+	(tp->key.type == PJSIP_TRANSPORT_TLS))
+    {
+	/* Yes we will check */
+    } else {
 	return PJ_FALSE;
-
-    /* Only update if STUN is enabled (for now) */
-    if (pjsua_var.ua_cfg.stun_domain.slen == 0 &&
-	pjsua_var.ua_cfg.stun_host.slen == 0)
-    {
-	return PJ_FALSE;
-    }
+    }
+#endif
 
     /* Get the received and rport info */
@@ -510,4 +520,6 @@
 	/* Remote doesn't support rport */
 	rport = via->sent_by.port;
+	if (rport==0)
+	    rport = pjsip_transport_get_default_port_for_type(tp->key.type);
     } else
 	rport = via->rport_param;
@@ -518,9 +530,19 @@
 	via_addr = &via->sent_by.host;
 
-    /* Compare received and rport with transport published address */
-    if (tp->local_name.port == rport &&
-	pj_stricmp(&tp->local_name.host, via_addr)==0)
+    /* Compare received and rport with the URI in our registration */
+    pool = pjsua_pool_create("tmp", 512, 512);
+    uri = (pjsip_sip_uri*)
+	  pjsip_parse_uri(pool, acc->contact.ptr, acc->contact.slen, 0);
+    pj_assert(uri != NULL);
+    uri = pjsip_uri_get_uri(uri);
+
+    if (uri->port == 0)
+	uri->port = pjsip_transport_get_default_port_for_type(tp->key.type);
+
+    if (uri->port == rport &&
+	pj_stricmp(&uri->host, via_addr)==0)
     {
 	/* Address doesn't change */
+	pj_pool_release(pool);
 	return PJ_FALSE;
     }
@@ -532,7 +554,7 @@
 			 "(%.*s:%d --> %.*s:%d). Updating registration..",
 			 acc->index,
-			 (int)tp->local_name.host.slen,
-			 tp->local_name.host.ptr,
-			 tp->local_name.port,
+			 (int)uri->host.slen,
+			 uri->host.ptr,
+			 uri->port,
 			 (int)via_addr->slen,
 			 via_addr->ptr,
@@ -546,10 +568,41 @@
     }
 
-    /* Update transport address */
-    pj_strdup_with_null(tp->pool, &tp->local_name.host, via_addr);
-    tp->local_name.port = rport;
+    /* Update account's Contact header */
+    {
+	char *tmp;
+	int len;
+
+	tmp = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
+	len = pj_ansi_snprintf(tmp, PJSIP_MAX_URL_SIZE,
+			       "<sip:%.*s@%.*s:%d;transport=%s>",
+			       (int)acc->user_part.slen,
+			       acc->user_part.ptr,
+			       (int)via_addr->slen,
+			       via_addr->ptr,
+			       rport,
+			       tp->type_name);
+	if (len < 1) {
+	    PJ_LOG(1,(THIS_FILE, "URI too long"));
+	    pj_pool_release(pool);
+	    return PJ_FALSE;
+	}
+	pj_strdup2(pjsua_var.pool, &acc->contact, tmp);
+    }
+
+    /* For UDP transport, if STUN is enabled then update the transport's
+     * published name as well.
+     */
+    if (tp->key.type==PJSIP_TRANSPORT_UDP &&
+	(pjsua_var.ua_cfg.stun_domain.slen != 0 ||
+	 pjsua_var.ua_cfg.stun_host.slen != 0))
+    {
+	pj_strdup_with_null(tp->pool, &tp->local_name.host, via_addr);
+	tp->local_name.port = rport;
+    }
 
     /* Perform new registration */
     pjsua_acc_set_registration(acc->index, PJ_TRUE);
+
+    pj_pool_release(pool);
 
     return PJ_TRUE;
@@ -864,5 +917,4 @@
 {
     pjsua_acc *acc;
-    pj_str_t contact;
     pj_pool_t *pool;
     pj_status_t status;
@@ -894,14 +946,21 @@
 
     pool = pjsua_pool_create("tmpregc", 512, 512);
-    status = pjsua_acc_create_uac_contact( pool, &contact,
-					   acc_id, &acc->cfg.reg_uri);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Unable to generate suitable Contact header"
-				" for registration", 
-		     status);
-	pjsip_regc_destroy(acc->regc);
-	pj_pool_release(pool);
-	acc->regc = NULL;
-	return status;
+
+    if (acc->contact.slen == 0) {
+	pj_str_t tmp_contact;
+
+	status = pjsua_acc_create_uac_contact( pool, &tmp_contact,
+					       acc_id, &acc->cfg.reg_uri);
+	if (status != PJ_SUCCESS) {
+	    pjsua_perror(THIS_FILE, "Unable to generate suitable Contact header"
+				    " for registration", 
+			 status);
+	    pjsip_regc_destroy(acc->regc);
+	    pj_pool_release(pool);
+	    acc->regc = NULL;
+	    return status;
+	}
+
+	pj_strdup_with_null(pjsua_var.pool, &acc->contact, &tmp_contact);
     }
 
@@ -910,5 +969,5 @@
 			      &acc->cfg.id, 
 			      &acc->cfg.id,
-			      1, &contact, 
+			      1, &acc->contact, 
 			      acc->cfg.reg_timeout);
     if (status != PJ_SUCCESS) {
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 1888)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 1889)
@@ -143,5 +143,5 @@
     cfg->reg_timeout = PJSUA_REG_INTERVAL;
     cfg->transport_id = PJSUA_INVALID_ID;
-    cfg->auto_update_nat = PJ_TRUE;
+    cfg->allow_contact_rewrite = PJ_TRUE;
     cfg->require_100rel = pjsua_var.ua_cfg.require_100rel;
     cfg->ka_interval = 15;
