Index: pjproject/trunk/pjlib/include/pj/addr_resolv.h
===================================================================
--- pjproject/trunk/pjlib/include/pj/addr_resolv.h	(revision 4217)
+++ pjproject/trunk/pjlib/include/pj/addr_resolv.h	(revision 4218)
@@ -118,4 +118,29 @@
 
 /**
+ * Get the interface IP address to send data to the specified destination.
+ *
+ * @param af	    The desired address family to query. Valid values
+ *		    are pj_AF_INET() or pj_AF_INET6().
+ * @param dst	    The destination host.
+ * @param itf_addr  On successful resolution, the address family and address
+ *		    part of this socket address will be filled up with the host
+ *		    IP address, in network byte order. Other parts of the socket
+ *		    address should be ignored.
+ * @param allow_resolve   If \a dst may contain hostname (instead of IP
+ * 		    address), specify whether hostname resolution should
+ * 	            be performed. If not, default interface address will
+ *  		    be returned.
+ * @param p_dst_addr If not NULL, it will be filled with the IP address of
+ * 		    the destination host.
+ *
+ * @return	    PJ_SUCCESS on success, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pj_getipinterface(int af,
+                                       const pj_str_t *dst,
+                                       pj_sockaddr *itf_addr,
+                                       pj_bool_t allow_resolve,
+                                       pj_sockaddr *p_dst_addr);
+
+/**
  * Get the IP address of the default interface. Default interface is the
  * interface of the default route.
Index: pjproject/trunk/pjlib/src/pj/sock_common.c
===================================================================
--- pjproject/trunk/pjlib/src/pj/sock_common.c	(revision 4217)
+++ pjproject/trunk/pjlib/src/pj/sock_common.c	(revision 4218)
@@ -957,20 +957,77 @@
 }
 
-/* Get the default IP interface */
-PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr)
-{
+/* Get IP interface for sending to the specified destination */
+PJ_DEF(pj_status_t) pj_getipinterface(int af,
+                                      const pj_str_t *dst,
+                                      pj_sockaddr *itf_addr,
+                                      pj_bool_t allow_resolve,
+                                      pj_sockaddr *p_dst_addr)
+{
+    pj_sockaddr dst_addr;
     pj_sock_t fd;
-    pj_str_t cp;
-    pj_sockaddr a;
     int len;
     pj_uint8_t zero[64];
     pj_status_t status;
 
-    addr->addr.sa_family = (pj_uint16_t)af;
-
+    pj_sockaddr_init(af, &dst_addr, NULL, 53);
+    status = pj_inet_pton(af, dst, pj_sockaddr_get_addr(&dst_addr));
+    if (status != PJ_SUCCESS) {
+	/* "dst" is not an IP address. */
+	if (allow_resolve) {
+	    status = pj_sockaddr_init(af, &dst_addr, dst, 53);
+	} else {
+	    pj_str_t cp;
+
+	    if (af == PJ_AF_INET) {
+		cp = pj_str("1.1.1.1");
+	    } else {
+		cp = pj_str("1::1");
+	    }
+	    status = pj_sockaddr_init(af, &dst_addr, &cp, 53);
+	}
+
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    /* Create UDP socket and connect() to the destination IP */
     status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &fd);
     if (status != PJ_SUCCESS) {
 	return status;
     }
+
+    status = pj_sock_connect(fd, &dst_addr, pj_sockaddr_get_len(&dst_addr));
+    if (status != PJ_SUCCESS) {
+	pj_sock_close(fd);
+	return status;
+    }
+
+    len = sizeof(*itf_addr);
+    status = pj_sock_getsockname(fd, itf_addr, &len);
+    if (status != PJ_SUCCESS) {
+	pj_sock_close(fd);
+	return status;
+    }
+
+    pj_sock_close(fd);
+
+    /* Check that the address returned is not zero */
+    pj_bzero(zero, sizeof(zero));
+    if (pj_memcmp(pj_sockaddr_get_addr(itf_addr), zero,
+		  pj_sockaddr_get_addr_len(itf_addr))==0)
+    {
+	return PJ_ENOTFOUND;
+    }
+
+    if (p_dst_addr)
+	*p_dst_addr = dst_addr;
+
+    return PJ_SUCCESS;
+}
+
+/* Get the default IP interface */
+PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr)
+{
+    pj_str_t cp;
 
     if (af == PJ_AF_INET) {
@@ -979,37 +1036,6 @@
 	cp = pj_str("1::1");
     }
-    status = pj_sockaddr_init(af, &a, &cp, 53);
-    if (status != PJ_SUCCESS) {
-	pj_sock_close(fd);
-	return status;
-    }
-
-    status = pj_sock_connect(fd, &a, pj_sockaddr_get_len(&a));
-    if (status != PJ_SUCCESS) {
-	pj_sock_close(fd);
-	return status;
-    }
-
-    len = sizeof(a);
-    status = pj_sock_getsockname(fd, &a, &len);
-    if (status != PJ_SUCCESS) {
-	pj_sock_close(fd);
-	return status;
-    }
-
-    pj_sock_close(fd);
-
-    /* Check that the address returned is not zero */
-    pj_bzero(zero, sizeof(zero));
-    if (pj_memcmp(pj_sockaddr_get_addr(&a), zero,
-		  pj_sockaddr_get_addr_len(&a))==0)
-    {
-	return PJ_ENOTFOUND;
-    }
-
-    pj_sockaddr_copy_addr(addr, &a);
-
-    /* Success */
-    return PJ_SUCCESS;
+
+    return pj_getipinterface(af, &cp, addr, PJ_FALSE, NULL);
 }
 
Index: pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 4217)
+++ pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 4218)
@@ -225,12 +225,9 @@
     puts  ("");
     puts  ("SIP Account options:");
-    puts  ("  --use-ims           Enable 3GPP/IMS related settings on this account");
-#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
-    puts  ("  --use-srtp=N        Use SRTP?  0:disabled, 1:optional, 2:mandatory,");
-    puts  ("                      3:optional by duplicating media offer (def:0)");
-    puts  ("  --srtp-secure=N     SRTP require secure SIP? 0:no, 1:tls, 2:sips (def:1)");
-#endif
     puts  ("  --registrar=url     Set the URL of registrar server");
     puts  ("  --id=url            Set the URL of local ID (used in From header)");
+    puts  ("  --realm=string      Set realm");
+    puts  ("  --username=string   Set authentication username");
+    puts  ("  --password=string   Set authentication password");
     puts  ("  --contact=url       Optionally override the Contact information");
     puts  ("  --contact-params=S  Append the specified parameters S in Contact header");
@@ -244,9 +241,12 @@
     puts  ("  --reg-use-proxy=N   Control the use of proxy settings in REGISTER.");
     puts  ("                      0=no proxy, 1=outbound only, 2=acc only, 3=all (default)");
-    puts  ("  --realm=string      Set realm");
-    puts  ("  --username=string   Set authentication username");
-    puts  ("  --password=string   Set authentication password");
     puts  ("  --publish           Send presence PUBLISH for this account");
     puts  ("  --mwi               Subscribe to message summary/waiting indication");
+    puts  ("  --use-ims           Enable 3GPP/IMS related settings on this account");
+#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
+    puts  ("  --use-srtp=N        Use SRTP?  0:disabled, 1:optional, 2:mandatory,");
+    puts  ("                      3:optional by duplicating media offer (def:0)");
+    puts  ("  --srtp-secure=N     SRTP require secure SIP? 0:no, 1:tls, 2:sips (def:1)");
+#endif
     puts  ("  --use-100rel        Require reliable provisional response (100rel)");
     puts  ("  --use-timer=N       Use SIP session timers? (default=1)");
@@ -258,4 +258,5 @@
     puts  ("  --auto-update-nat=N Where N is 0 or 1 to enable/disable SIP traversal behind");
     puts  ("                      symmetric NAT (default 1)");
+    puts  ("  --disable-stun      Disable STUN for this account");
     puts  ("  --next-cred         Add another credentials");
     puts  ("");
@@ -590,5 +591,5 @@
 #endif
 	   OPT_AUTO_UPDATE_NAT,OPT_USE_COMPACT_FORM,OPT_DIS_CODEC,
-	   OPT_NO_FORCE_LR,
+	   OPT_DISABLE_STUN, OPT_NO_FORCE_LR,
 	   OPT_TIMER, OPT_TIMER_SE, OPT_TIMER_MIN_SE,
 	   OPT_VIDEO, OPT_EXTRA_AUDIO,
@@ -630,4 +631,5 @@
 	{ "contact-uri-params",1,0, OPT_CONTACT_URI_PARAMS},
 	{ "auto-update-nat",	1, 0, OPT_AUTO_UPDATE_NAT},
+	{ "disable-stun",0,0, OPT_DISABLE_STUN},
         { "use-compact-form",	0, 0, OPT_USE_COMPACT_FORM},
 	{ "accept-redirect", 1, 0, OPT_ACCEPT_REDIRECT},
@@ -1022,4 +1024,9 @@
 	    break;
 
+	case OPT_DISABLE_STUN:
+	    cur_acc->sip_stun_use = PJSUA_STUN_USE_DISABLED;
+	    cur_acc->media_stun_use = PJSUA_STUN_USE_DISABLED;
+	    break;
+
 	case OPT_USE_COMPACT_FORM:
 	    /* enable compact form - from Ticket #342 */
@@ -1172,40 +1179,52 @@
 
 	case OPT_USE_ICE:
-	    cfg->media_cfg.enable_ice = PJ_TRUE;
+	    cfg->media_cfg.enable_ice =
+		    cur_acc->ice_cfg.enable_ice = PJ_TRUE;
 	    break;
 
 	case OPT_ICE_REGULAR:
-	    cfg->media_cfg.ice_opt.aggressive = PJ_FALSE;
+	    cfg->media_cfg.ice_opt.aggressive =
+		    cur_acc->ice_cfg.ice_opt.aggressive = PJ_FALSE;
 	    break;
 
 	case OPT_USE_TURN:
-	    cfg->media_cfg.enable_turn = PJ_TRUE;
+	    cfg->media_cfg.enable_turn =
+		    cur_acc->turn_cfg.enable_turn = PJ_TRUE;
 	    break;
 
 	case OPT_ICE_MAX_HOSTS:
-	    cfg->media_cfg.ice_max_host_cands = my_atoi(pj_optarg);
+	    cfg->media_cfg.ice_max_host_cands =
+		    cur_acc->ice_cfg.ice_max_host_cands = my_atoi(pj_optarg);
 	    break;
 
 	case OPT_ICE_NO_RTCP:
-	    cfg->media_cfg.ice_no_rtcp = PJ_TRUE;
+	    cfg->media_cfg.ice_no_rtcp =
+		    cur_acc->ice_cfg.ice_no_rtcp = PJ_TRUE;
 	    break;
 
 	case OPT_TURN_SRV:
-	    cfg->media_cfg.turn_server = pj_str(pj_optarg);
+	    cfg->media_cfg.turn_server =
+		    cur_acc->turn_cfg.turn_server = pj_str(pj_optarg);
 	    break;
 
 	case OPT_TURN_TCP:
-	    cfg->media_cfg.turn_conn_type = PJ_TURN_TP_TCP;
+	    cfg->media_cfg.turn_conn_type =
+		    cur_acc->turn_cfg.turn_conn_type = PJ_TURN_TP_TCP;
 	    break;
 
 	case OPT_TURN_USER:
-	    cfg->media_cfg.turn_auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;
-	    cfg->media_cfg.turn_auth_cred.data.static_cred.realm = pj_str("*");
-	    cfg->media_cfg.turn_auth_cred.data.static_cred.username = pj_str(pj_optarg);
+	    cfg->media_cfg.turn_auth_cred.type =
+		    cur_acc->turn_cfg.turn_auth_cred.type = PJ_STUN_AUTH_CRED_STATIC;
+	    cfg->media_cfg.turn_auth_cred.data.static_cred.realm =
+		    cur_acc->turn_cfg.turn_auth_cred.data.static_cred.realm = pj_str("*");
+	    cfg->media_cfg.turn_auth_cred.data.static_cred.username =
+		    cur_acc->turn_cfg.turn_auth_cred.data.static_cred.username = pj_str(pj_optarg);
 	    break;
 
 	case OPT_TURN_PASSWD:
-	    cfg->media_cfg.turn_auth_cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
-	    cfg->media_cfg.turn_auth_cred.data.static_cred.data = pj_str(pj_optarg);
+	    cfg->media_cfg.turn_auth_cred.data.static_cred.data_type =
+		    cur_acc->turn_cfg.turn_auth_cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
+	    cfg->media_cfg.turn_auth_cred.data.static_cred.data =
+		    cur_acc->turn_cfg.turn_auth_cred.data.static_cred.data = pj_str(pj_optarg);
 	    break;
 
@@ -1576,4 +1595,11 @@
 	{
 	    acfg->cred_count++;
+	}
+
+	if (acfg->ice_cfg.enable_ice) {
+	    acfg->ice_cfg_use = PJSUA_ICE_CONFIG_USE_CUSTOM;
+	}
+	if (acfg->turn_cfg.enable_turn) {
+	    acfg->turn_cfg_use = PJSUA_TURN_CONFIG_USE_CUSTOM;
 	}
 
@@ -1772,4 +1798,53 @@
     if (acc_cfg->mwi_enabled)
 	pj_strcat2(result, "--mwi\n");
+
+    if (acc_cfg->sip_stun_use != PJSUA_STUN_USE_DEFAULT ||
+	acc_cfg->media_stun_use != PJSUA_STUN_USE_DEFAULT)
+    {
+	pj_strcat2(result, "--disable-stun\n");
+    }
+
+    /* Media Transport*/
+    if (acc_cfg->ice_cfg.enable_ice)
+	pj_strcat2(result, "--use-ice\n");
+
+    if (acc_cfg->ice_cfg.ice_opt.aggressive == PJ_FALSE)
+	pj_strcat2(result, "--ice-regular\n");
+
+    if (acc_cfg->turn_cfg.enable_turn)
+	pj_strcat2(result, "--use-turn\n");
+
+    if (acc_cfg->ice_cfg.ice_max_host_cands >= 0) {
+	pj_ansi_sprintf(line, "--ice_max_host_cands %d\n",
+	                acc_cfg->ice_cfg.ice_max_host_cands);
+	pj_strcat2(result, line);
+    }
+
+    if (acc_cfg->ice_cfg.ice_no_rtcp)
+	pj_strcat2(result, "--ice-no-rtcp\n");
+
+    if (acc_cfg->turn_cfg.turn_server.slen) {
+	pj_ansi_sprintf(line, "--turn-srv %.*s\n",
+			(int)acc_cfg->turn_cfg.turn_server.slen,
+			acc_cfg->turn_cfg.turn_server.ptr);
+	pj_strcat2(result, line);
+    }
+
+    if (acc_cfg->turn_cfg.turn_conn_type == PJ_TURN_TP_TCP)
+	pj_strcat2(result, "--turn-tcp\n");
+
+    if (acc_cfg->turn_cfg.turn_auth_cred.data.static_cred.username.slen) {
+	pj_ansi_sprintf(line, "--turn-user %.*s\n",
+			(int)acc_cfg->turn_cfg.turn_auth_cred.data.static_cred.username.slen,
+			acc_cfg->turn_cfg.turn_auth_cred.data.static_cred.username.ptr);
+	pj_strcat2(result, line);
+    }
+
+    if (acc_cfg->turn_cfg.turn_auth_cred.data.static_cred.data.slen) {
+	pj_ansi_sprintf(line, "--turn-passwd %.*s\n",
+			(int)acc_cfg->turn_cfg.turn_auth_cred.data.static_cred.data.slen,
+			acc_cfg->turn_cfg.turn_auth_cred.data.static_cred.data.ptr);
+	pj_strcat2(result, line);
+    }
 }
 
@@ -1967,47 +2042,4 @@
     }
 #endif
-
-    /* Media Transport*/
-    if (config->media_cfg.enable_ice)
-	pj_strcat2(&cfg, "--use-ice\n");
-
-    if (config->media_cfg.ice_opt.aggressive == PJ_FALSE)
-	pj_strcat2(&cfg, "--ice-regular\n");
-
-    if (config->media_cfg.enable_turn)
-	pj_strcat2(&cfg, "--use-turn\n");
-
-    if (config->media_cfg.ice_max_host_cands >= 0) {
-	pj_ansi_sprintf(line, "--ice_max_host_cands %d\n",
-			config->media_cfg.ice_max_host_cands);
-	pj_strcat2(&cfg, line);
-    }
-
-    if (config->media_cfg.ice_no_rtcp)
-	pj_strcat2(&cfg, "--ice-no-rtcp\n");
-
-    if (config->media_cfg.turn_server.slen) {
-	pj_ansi_sprintf(line, "--turn-srv %.*s\n",
-			(int)config->media_cfg.turn_server.slen,
-			config->media_cfg.turn_server.ptr);
-	pj_strcat2(&cfg, line);
-    }
-
-    if (config->media_cfg.turn_conn_type == PJ_TURN_TP_TCP)
-	pj_strcat2(&cfg, "--turn-tcp\n");
-
-    if (config->media_cfg.turn_auth_cred.data.static_cred.username.slen) {
-	pj_ansi_sprintf(line, "--turn-user %.*s\n",
-			(int)config->media_cfg.turn_auth_cred.data.static_cred.username.slen,
-			config->media_cfg.turn_auth_cred.data.static_cred.username.ptr);
-	pj_strcat2(&cfg, line);
-    }
-
-    if (config->media_cfg.turn_auth_cred.data.static_cred.data.slen) {
-	pj_ansi_sprintf(line, "--turn-passwd %.*s\n",
-			(int)config->media_cfg.turn_auth_cred.data.static_cred.data.slen,
-			config->media_cfg.turn_auth_cred.data.static_cred.data.ptr);
-	pj_strcat2(&cfg, line);
-    }
 
     /* Media */
Index: pjproject/trunk/pjsip/include/pjsip/sip_transport.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_transport.h	(revision 4217)
+++ pjproject/trunk/pjsip/include/pjsip/sip_transport.h	(revision 4218)
@@ -1077,4 +1077,6 @@
  * the transport type in the request.
  *
+ * @see pjsip_tpmgr_find_local_addr2()
+ *
  * @param tpmgr	    The transport manager.
  * @param pool	    Pool to allocate memory for the IP address.
@@ -1092,4 +1094,74 @@
 						  pj_str_t *ip_addr,
 						  int *port);
+
+/**
+ * Parameter for pjsip_tpmgr_find_local_addr2() function.
+ */
+typedef struct pjsip_tpmgr_fla2_param
+{
+    /**
+     * Specify transport type to use. This must be set.
+     */
+    pjsip_transport_type_e	 tp_type;
+
+    /**
+     * Optional pointer to preferred transport, if any.
+     */
+    const pjsip_tpselector	*tp_sel;
+
+    /**
+     * Destination host, if known. The destination host is needed
+     * if \a local_if field below is set.
+     */
+    pj_str_t			 dst_host;
+
+    /**
+     * Specify if the function should return which local interface
+     * to use for the specified destination in \a dst_host. By definition,
+     * the returned address will always be local interface address.
+     */
+    pj_bool_t			 local_if;
+
+    /**
+     * The returned address.
+     */
+    pj_str_t			 ret_addr;
+
+    /**
+     * The returned port.
+     */
+    pj_uint16_t			 ret_port;
+
+    /**
+     * Returned pointer to the transport. Only set if local_if is set.
+     */
+    const void			*ret_tp;
+
+} pjsip_tpmgr_fla2_param;
+
+/**
+ * Initialize with default values.
+ *
+ * @param prm	    The parameter to be initialized.
+ */
+PJ_DECL(void) pjsip_tpmgr_fla2_param_default(pjsip_tpmgr_fla2_param *prm);
+
+/**
+ * Find out the appropriate local address info (IP address and port) to
+ * advertise in Contact or Via header header based on the remote address
+ * to be contacted. The local address info would be the address name of the
+ * transport or listener which will be used to send the request.
+ *
+ * @see pjsip_tpmgr_find_local_addr()
+ *
+ * @param tpmgr	    The transport manager.
+ * @param pool	    Pool to allocate memory for the IP address.
+ * @param param	    Function input and output parameters.
+ *
+ * @return	    PJ_SUCCESS, or the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tpmgr_find_local_addr2(pjsip_tpmgr *tpmgr,
+                                                  pj_pool_t *pool,
+                                                  pjsip_tpmgr_fla2_param *prm);
 
 /**
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 4217)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 4218)
@@ -2568,4 +2568,118 @@
 
 /**
+ * This enumeration controls the use of STUN in the account.
+ */
+typedef enum pjsua_stun_use
+{
+    /**
+     * Follow the default setting in the global \a pjsua_config.
+     */
+    PJSUA_STUN_USE_DEFAULT,
+
+    /**
+     * Disable STUN. If STUN is not enabled in the global \a pjsua_config,
+     * this setting has no effect.
+     */
+    PJSUA_STUN_USE_DISABLED
+
+} pjsua_stun_use;
+
+/**
+ * This enumeration controls the use of ICE settings in the account.
+ */
+typedef enum pjsua_ice_config_use
+{
+    /**
+     * Use the default settings in the global \a pjsua_media_config.
+     */
+    PJSUA_ICE_CONFIG_USE_DEFAULT,
+
+    /**
+     * Use the custom \a pjsua_ice_config setting in the account.
+     */
+    PJSUA_ICE_CONFIG_USE_CUSTOM
+
+} pjsua_ice_config_use;
+
+/**
+ * This enumeration controls the use of TURN settings in the account.
+ */
+typedef enum pjsua_turn_config_use
+{
+    /**
+     * Use the default setting in the global \a pjsua_media_config.
+     */
+    PJSUA_TURN_CONFIG_USE_DEFAULT,
+
+    /**
+     * Use the custom \a pjsua_turn_config setting in the account.
+     */
+    PJSUA_TURN_CONFIG_USE_CUSTOM
+
+} pjsua_turn_config_use;
+
+/**
+ * ICE setting. This setting is used in the pjsua_acc_config.
+ */
+typedef struct pjsua_ice_config
+{
+    /**
+     * Enable ICE.
+     */
+    pj_bool_t		enable_ice;
+
+    /**
+     * Set the maximum number of host candidates.
+     *
+     * Default: -1 (maximum not set)
+     */
+    int			ice_max_host_cands;
+
+    /**
+     * ICE session options.
+     */
+    pj_ice_sess_options	ice_opt;
+
+    /**
+     * Disable RTCP component.
+     *
+     * Default: no
+     */
+    pj_bool_t		ice_no_rtcp;
+
+} pjsua_ice_config;
+
+/**
+ * TURN setting. This setting is used in the pjsua_acc_config.
+ */
+typedef struct pjsua_turn_config
+{
+    /**
+     * Enable TURN candidate in ICE.
+     */
+    pj_bool_t		enable_turn;
+
+    /**
+     * Specify TURN domain name or host name, in in "DOMAIN:PORT" or
+     * "HOST:PORT" format.
+     */
+    pj_str_t		turn_server;
+
+    /**
+     * Specify the connection type to be used to the TURN server. Valid
+     * values are PJ_TURN_TP_UDP or PJ_TURN_TP_TCP.
+     *
+     * Default: PJ_TURN_TP_UDP
+     */
+    pj_turn_tp_type	turn_conn_type;
+
+    /**
+     * Specify the credential to authenticate with the TURN server.
+     */
+    pj_stun_auth_cred	turn_auth_cred;
+
+} pjsua_turn_config;
+
+/**
  * This structure describes account configuration to be specified when
  * adding a new account with #pjsua_acc_add(). Application MUST initialize
@@ -2968,4 +3082,46 @@
 
     /**
+     * Control the use of STUN for the SIP signaling.
+     *
+     * Default: PJSUA_STUN_USE_DEFAULT
+     */
+    pjsua_stun_use 		sip_stun_use;
+
+    /**
+     * Control the use of STUN for the media transports.
+     *
+     * Default: PJSUA_STUN_USE_DEFAULT
+     */
+    pjsua_stun_use 		media_stun_use;
+
+    /**
+     * Control the use of ICE in the account. By default, the settings in the
+     * \a pjsua_media_config will be used.
+     *
+     * Default: PJSUA_ICE_CONFIG_USE_DEFAULT
+     */
+    pjsua_ice_config_use	ice_cfg_use;
+
+    /**
+     * The custom ICE setting for this account. This setting will only be
+     * used if \a ice_cfg_use is set to PJSUA_ICE_CONFIG_USE_CUSTOM
+     */
+    pjsua_ice_config		ice_cfg;
+
+    /**
+     * Control the use of TURN in the account. By default, the settings in the
+     * \a pjsua_media_config will be used
+     *
+     * Default: PJSUA_TURN_CONFIG_USE_DEFAULT
+     */
+    pjsua_turn_config_use	turn_cfg_use;
+
+    /**
+     * The custom TURN setting for this account. This setting will only be
+     * used if \a turn_cfg_use is set to PJSUA_TURN_CONFIG_USE_CUSTOM
+     */
+    pjsua_turn_config		turn_cfg;
+
+    /**
      * Specify whether secure media transport should be used for this account.
      * Valid values are PJMEDIA_SRTP_DISABLED, PJMEDIA_SRTP_OPTIONAL, and
@@ -2974,5 +3130,5 @@
      * Default: #PJSUA_DEFAULT_USE_SRTP
      */
-    pjmedia_srtp_use	use_srtp;
+    pjmedia_srtp_use		use_srtp;
 
     /**
@@ -3070,4 +3226,50 @@
 } pjsua_acc_config;
 
+
+/**
+ * Initialize ICE config from a media config. If the \a pool argument
+ * is NULL, a simple memcpy() will be used.
+ *
+ * @param pool	    Memory to duplicate strings.
+ * @param dst	    Destination config.
+ * @param src	    Source config.
+ */
+PJ_DECL(void) pjsua_ice_config_from_media_config(pj_pool_t *pool,
+                                              pjsua_ice_config *dst,
+                                              const pjsua_media_config *src);
+
+/**
+ * Clone. If the \a pool argument is NULL, a simple memcpy() will be used.
+ *
+ * @param pool	    Memory to duplicate strings.
+ * @param dst	    Destination config.
+ * @param src	    Source config.
+ */
+PJ_DECL(void) pjsua_ice_config_dup( pj_pool_t *pool,
+                                    pjsua_ice_config *dst,
+                                    const pjsua_ice_config *src);
+
+/**
+ * Initialize TURN config from a media config. If the \a pool argument
+ * is NULL, a simple memcpy() will be used.
+ *
+ * @param pool	    Memory to duplicate strings.
+ * @param dst	    Destination config.
+ * @param src	    Source config.
+ */
+PJ_DECL(void) pjsua_turn_config_from_media_config(pj_pool_t *pool,
+                                               pjsua_turn_config *dst,
+                                               const pjsua_media_config *src);
+
+/**
+ * Clone. If the \a pool argument is NULL, a simple memcpy() will be used.
+ *
+ * @param pool	    Memory to duplicate strings.
+ * @param dst	    Destination config.
+ * @param src	    Source config.
+ */
+PJ_DECL(void) pjsua_turn_config_dup(pj_pool_t *pool,
+                                    pjsua_turn_config *dst,
+                                    const pjsua_turn_config *src);
 
 /**
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 4217)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua_internal.h	(revision 4218)
@@ -584,4 +584,18 @@
 pj_status_t normalize_route_uri(pj_pool_t *pool, pj_str_t *uri);
 
+/* acc use stun? */
+pj_bool_t pjsua_sip_acc_is_using_stun(pjsua_acc_id acc_id);
+
+/* Get local transport address suitable to be used for Via or Contact address
+ * to send request to the specified destination URI.
+ */
+pj_status_t pjsua_acc_get_uac_addr(pjsua_acc_id acc_id,
+				   pj_pool_t *pool,
+				   const pj_str_t *dst_uri,
+				   pjsip_host_port *addr,
+				   pjsip_transport_type_e *p_tp_type,
+				   int *p_secure,
+				   const void **p_tp);
+
 /**
  * Handle incoming invite request.
Index: pjproject/trunk/pjsip/src/pjsip/sip_transport.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 4217)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 4218)
@@ -25,4 +25,5 @@
 #include <pjsip/sip_errno.h>
 #include <pjsip/sip_module.h>
+#include <pj/addr_resolv.h>
 #include <pj/except.h>
 #include <pj/os.h>
@@ -1081,4 +1082,8 @@
 }
 
+PJ_DECL(void) pjsip_tpmgr_fla2_param_default(pjsip_tpmgr_fla2_param *prm)
+{
+    pj_bzero(prm, sizeof(*prm));
+}
 
 /*****************************************************************************
@@ -1139,5 +1144,25 @@
 }
 
-
+/* Get the interface to send packet to the specified address */
+static pj_status_t get_net_interface(pjsip_transport_type_e tp_type,
+				     const pj_str_t *dst,
+                                     pj_str_t *itf_str_addr)
+{
+    int af;
+    pj_sockaddr itf_addr;
+    pj_status_t status;
+
+    af = (tp_type & PJSIP_TRANSPORT_IPV6)? PJ_AF_INET6 : PJ_AF_INET;
+    status = pj_getipinterface(af, dst, &itf_addr, PJ_FALSE, NULL);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Print address */
+    pj_sockaddr_print(&itf_addr, itf_str_addr->ptr,
+		      PJ_INET6_ADDRSTRLEN, 0);
+    itf_str_addr->slen = pj_ansi_strlen(itf_str_addr->ptr);
+
+    return PJ_SUCCESS;
+}
 
 /*
@@ -1150,4 +1175,123 @@
  * the transport type in the request.
  */
+PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr2(pjsip_tpmgr *tpmgr,
+						 pj_pool_t *pool,
+						 pjsip_tpmgr_fla2_param *prm)
+{
+    char tmp_buf[PJ_INET6_ADDRSTRLEN+10];
+    pj_str_t tmp_str = { tmp_buf, 0 };
+    pj_status_t status = PJSIP_EUNSUPTRANSPORT;
+    unsigned flag;
+
+    /* Sanity checks */
+    PJ_ASSERT_RETURN(tpmgr && pool && prm, PJ_EINVAL);
+
+    prm->ret_addr.slen = 0;
+    prm->ret_port = 0;
+    prm->ret_tp = NULL;
+
+    flag = pjsip_transport_get_flag_from_type(prm->tp_type);
+
+    if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
+	prm->tp_sel->u.transport)
+    {
+	const pjsip_transport *tp = prm->tp_sel->u.transport;
+	if (prm->local_if) {
+	    status = get_net_interface(tp->key.type, &prm->dst_host,
+	                               &tmp_str);
+	    if (status != PJ_SUCCESS)
+		goto on_return;
+	    pj_strdup(pool, &prm->ret_addr, &tmp_str);
+	    prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
+	    prm->ret_tp = tp;
+	} else {
+	    pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
+	    prm->ret_port = tp->local_name.port;
+	}
+	status = PJ_SUCCESS;
+
+    } else if (prm->tp_sel && prm->tp_sel->type == PJSIP_TPSELECTOR_LISTENER &&
+	       prm->tp_sel->u.listener)
+    {
+	if (prm->local_if) {
+	    status = get_net_interface(prm->tp_sel->u.listener->type,
+	                               &prm->dst_host, &tmp_str);
+	    if (status != PJ_SUCCESS)
+		goto on_return;
+	    pj_strdup(pool, &prm->ret_addr, &tmp_str);
+	} else {
+	    pj_strdup(pool, &prm->ret_addr,
+		      &prm->tp_sel->u.listener->addr_name.host);
+	}
+	prm->ret_port = prm->tp_sel->u.listener->addr_name.port;
+	status = PJ_SUCCESS;
+
+    } else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
+	pj_sockaddr remote;
+	int addr_len;
+	pjsip_transport *tp;
+
+	pj_bzero(&remote, sizeof(remote));
+	if (prm->tp_type & PJSIP_TRANSPORT_IPV6) {
+	    addr_len = sizeof(pj_sockaddr_in6);
+	    remote.addr.sa_family = pj_AF_INET6();
+	} else {
+	    addr_len = sizeof(pj_sockaddr_in);
+	    remote.addr.sa_family = pj_AF_INET();
+	}
+
+	status = pjsip_tpmgr_acquire_transport(tpmgr, prm->tp_type, &remote,
+					       addr_len, NULL, &tp);
+
+	if (status == PJ_SUCCESS) {
+	    if (prm->local_if) {
+		status = get_net_interface(tp->key.type, &prm->dst_host,
+					   &tmp_str);
+		if (status != PJ_SUCCESS)
+		    goto on_return;
+		pj_strdup(pool, &prm->ret_addr, &tmp_str);
+		prm->ret_port = pj_sockaddr_get_port(&tp->local_addr);
+		prm->ret_tp = tp;
+	    } else {
+		pj_strdup(pool, &prm->ret_addr, &tp->local_name.host);
+		prm->ret_port = tp->local_name.port;
+	    }
+
+	    pjsip_transport_dec_ref(tp);
+	}
+
+    } else {
+	/* For connection oriented transport, enum the factories */
+	pjsip_tpfactory *f;
+
+	pj_lock_acquire(tpmgr->lock);
+
+	f = tpmgr->factory_list.next;
+	while (f != &tpmgr->factory_list) {
+	    if (f->type == prm->tp_type)
+		break;
+	    f = f->next;
+	}
+
+	if (f != &tpmgr->factory_list) {
+	    if (prm->local_if) {
+		status = get_net_interface(f->type, &prm->dst_host,
+					   &tmp_str);
+		if (status != PJ_SUCCESS)
+		    goto on_return;
+		pj_strdup(pool, &prm->ret_addr, &tmp_str);
+	    } else {
+		pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
+	    }
+	    prm->ret_port = f->addr_name.port;
+	    status = PJ_SUCCESS;
+	}
+	pj_lock_release(tpmgr->lock);
+    }
+
+on_return:
+    return status;
+}
+
 PJ_DEF(pj_status_t) pjsip_tpmgr_find_local_addr( pjsip_tpmgr *tpmgr,
 						 pj_pool_t *pool,
@@ -1157,77 +1301,19 @@
 						 int *port)
 {
-    pj_status_t status = PJSIP_EUNSUPTRANSPORT;
-    unsigned flag;
-
-    /* Sanity checks */
-    PJ_ASSERT_RETURN(tpmgr && pool && ip_addr && port, PJ_EINVAL);
-
-    ip_addr->slen = 0;
-    *port = 0;
-
-    flag = pjsip_transport_get_flag_from_type(type);
-
-    if (sel && sel->type == PJSIP_TPSELECTOR_TRANSPORT &&
-	sel->u.transport)
-    {
-	pj_strdup(pool, ip_addr, &sel->u.transport->local_name.host);
-	*port = sel->u.transport->local_name.port;
-	status = PJ_SUCCESS;
-
-    } else if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
-	       sel->u.listener)
-    {
-	pj_strdup(pool, ip_addr, &sel->u.listener->addr_name.host);
-	*port = sel->u.listener->addr_name.port;
-	status = PJ_SUCCESS;
-
-    } else if ((flag & PJSIP_TRANSPORT_DATAGRAM) != 0) {
-	
-	pj_sockaddr remote;
-	int addr_len;
-	pjsip_transport *tp;
-
-	pj_bzero(&remote, sizeof(remote));
-	if (type & PJSIP_TRANSPORT_IPV6) {
-	    addr_len = sizeof(pj_sockaddr_in6);
-	    remote.addr.sa_family = pj_AF_INET6();
-	} else {
-	    addr_len = sizeof(pj_sockaddr_in);
-	    remote.addr.sa_family = pj_AF_INET();
-	}
-
-	status = pjsip_tpmgr_acquire_transport(tpmgr, type, &remote,
-					       addr_len, NULL, &tp);
-
-	if (status == PJ_SUCCESS) {
-	    pj_strdup(pool, ip_addr, &tp->local_name.host);
-	    *port = tp->local_name.port;
-	    status = PJ_SUCCESS;
-
-	    pjsip_transport_dec_ref(tp);
-	}
-
-    } else {
-	/* For connection oriented transport, enum the factories */
-	pjsip_tpfactory *f;
-
-	pj_lock_acquire(tpmgr->lock);
-
-	f = tpmgr->factory_list.next;
-	while (f != &tpmgr->factory_list) {
-	    if (f->type == type)
-		break;
-	    f = f->next;
-	}
-
-	if (f != &tpmgr->factory_list) {
-	    pj_strdup(pool, ip_addr, &f->addr_name.host);
-	    *port = f->addr_name.port;
-	    status = PJ_SUCCESS;
-	}
-	pj_lock_release(tpmgr->lock);
-    }
-
-    return status;
+    pjsip_tpmgr_fla2_param prm;
+    pj_status_t status;
+
+    pjsip_tpmgr_fla2_param_default(&prm);
+    prm.tp_type = type;
+    prm.tp_sel = sel;
+
+    status = pjsip_tpmgr_find_local_addr2(tpmgr, pool, &prm);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    *ip_addr = prm.ret_addr;
+    *port = prm.ret_port;
+
+    return PJ_SUCCESS;
 }
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 4217)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 4218)
@@ -134,4 +134,7 @@
     pjsua_transport_config_dup(pool, &dst->rtp_cfg, &src->rtp_cfg);
 
+    pjsua_ice_config_dup(pool, &dst->ice_cfg, &src->ice_cfg);
+    pjsua_turn_config_dup(pool, &dst->turn_cfg, &src->turn_cfg);
+
     pj_strdup(pool, &dst->ka_data, &src->ka_data);
 }
@@ -284,5 +287,5 @@
      */
 #if PJSUA_ADD_ICE_TAGS
-    if (pjsua_var.media_cfg.enable_ice) {
+    if (acc_cfg->ice_cfg.enable_ice) {
 	unsigned new_len;
 	pj_str_t new_prm;
@@ -347,4 +350,16 @@
 	    acc->rfc5626_regprm.slen = len;
 	}
+    }
+
+    /* If account's ICE and TURN customization is not set, then
+     * initialize it with the settings from the global media config.
+     */
+    if (acc->cfg.ice_cfg_use == PJSUA_ICE_CONFIG_USE_DEFAULT) {
+	pjsua_ice_config_from_media_config(NULL, &acc->cfg.ice_cfg,
+	                                &pjsua_var.media_cfg);
+    }
+    if (acc->cfg.turn_cfg_use == PJSUA_TURN_CONFIG_USE_DEFAULT) {
+	pjsua_turn_config_from_media_config(NULL, &acc->cfg.turn_cfg,
+	                                    &pjsua_var.media_cfg);
     }
 
@@ -1153,4 +1168,66 @@
     }
 
+    /* Video settings */
+    acc->cfg.vid_in_auto_show = cfg->vid_in_auto_show;
+    acc->cfg.vid_out_auto_transmit = cfg->vid_out_auto_transmit;
+    acc->cfg.vid_wnd_flags = cfg->vid_wnd_flags;
+    acc->cfg.vid_cap_dev = cfg->vid_cap_dev;
+    acc->cfg.vid_rend_dev = cfg->vid_rend_dev;
+    acc->cfg.vid_stream_rc_cfg = cfg->vid_stream_rc_cfg;
+
+    /* Media settings */
+    if (pj_stricmp(&acc->cfg.rtp_cfg.public_addr, &cfg->rtp_cfg.public_addr) ||
+	pj_stricmp(&acc->cfg.rtp_cfg.bound_addr, &cfg->rtp_cfg.bound_addr))
+    {
+	pjsua_transport_config_dup(acc->pool, &acc->cfg.rtp_cfg,
+				   &cfg->rtp_cfg);
+    } else {
+	/* ..to save memory by not using the pool */
+	acc->cfg.rtp_cfg =  cfg->rtp_cfg;
+    }
+
+    /* STUN and Media customization */
+    if (acc->cfg.sip_stun_use != cfg->sip_stun_use) {
+	acc->cfg.sip_stun_use = cfg->sip_stun_use;
+	update_reg = PJ_TRUE;
+    }
+    acc->cfg.media_stun_use = cfg->media_stun_use;
+
+    /* ICE settings */
+    acc->cfg.ice_cfg_use = cfg->ice_cfg_use;
+    switch (acc->cfg.ice_cfg_use) {
+    case PJSUA_ICE_CONFIG_USE_DEFAULT:
+	/* Copy ICE settings from media settings so that we don't need to
+	 * check the media config if we look for ICE config.
+	 */
+	pjsua_ice_config_from_media_config(NULL, &acc->cfg.ice_cfg,
+	                                &pjsua_var.media_cfg);
+	break;
+    case PJSUA_ICE_CONFIG_USE_CUSTOM:
+	pjsua_ice_config_dup(acc->pool, &acc->cfg.ice_cfg, &cfg->ice_cfg);
+	break;
+    }
+
+    /* TURN settings */
+    acc->cfg.turn_cfg_use = cfg->turn_cfg_use;
+    switch (acc->cfg.turn_cfg_use) {
+    case PJSUA_TURN_CONFIG_USE_DEFAULT:
+	/* Copy TURN settings from media settings so that we don't need to
+	 * check the media config if we look for TURN config.
+	 */
+	pjsua_turn_config_from_media_config(NULL, &acc->cfg.turn_cfg,
+	                                    &pjsua_var.media_cfg);
+	break;
+    case PJSUA_TURN_CONFIG_USE_CUSTOM:
+	pjsua_turn_config_dup(acc->pool, &acc->cfg.turn_cfg,
+	                      &cfg->turn_cfg);
+	break;
+    }
+
+    acc->cfg.use_srtp = cfg->use_srtp;
+
+    /* Call hold type */
+    acc->cfg.call_hold_type = cfg->call_hold_type;
+
     /* Unregister first */
     if (unreg_first) {
@@ -1174,14 +1251,4 @@
 	pjsua_start_mwi(acc_id, PJ_TRUE);
     }
-
-    /* Video settings */
-    acc->cfg.vid_in_auto_show = cfg->vid_in_auto_show;
-    acc->cfg.vid_out_auto_transmit = cfg->vid_out_auto_transmit;
-    acc->cfg.vid_wnd_flags = cfg->vid_wnd_flags;
-    acc->cfg.vid_cap_dev = cfg->vid_cap_dev;
-    acc->cfg.vid_rend_dev = cfg->vid_rend_dev;
-
-    /* Call hold type */
-    acc->cfg.call_hold_type = cfg->call_hold_type;
 
 on_return:
@@ -1516,4 +1583,5 @@
 	char *tmp;
 	const char *beginquote, *endquote;
+	char transport_param[32];
 	int len;
 
@@ -1526,7 +1594,18 @@
 	}
 
+	/* Don't add transport parameter if it's UDP */
+	if (tp->key.type != PJSIP_TRANSPORT_UDP &&
+		tp->key.type != PJSIP_TRANSPORT_UDP6)
+	{
+	    pj_ansi_snprintf(transport_param, sizeof(transport_param),
+			     ";transport=%s",
+			     pjsip_transport_get_type_name(tp->key.type));
+	} else {
+	    transport_param[0] = '\0';
+	}
+
 	tmp = (char*) pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
 	len = pj_ansi_snprintf(tmp, PJSIP_MAX_URL_SIZE,
-			       "<sip:%.*s%s%s%.*s%s:%d;transport=%s%.*s%s>%.*s",
+			       "<sip:%.*s%s%s%.*s%s:%d%s%.*s%s>%.*s",
 			       (int)acc->user_part.slen,
 			       acc->user_part.ptr,
@@ -1537,5 +1616,5 @@
 			       endquote,
 			       rport,
-			       tp->type_name,
+			       transport_param,
 			       (int)acc->cfg.contact_uri_params.slen,
 			       acc->cfg.contact_uri_params.ptr,
@@ -2147,4 +2226,11 @@
 }
 
+pj_bool_t pjsua_sip_acc_is_using_stun(pjsua_acc_id acc_id)
+{
+    pjsua_acc *acc = &pjsua_var.acc[acc_id];
+
+    return acc->cfg.sip_stun_use != PJSUA_STUN_USE_DISABLED &&
+	    pjsua_var.ua_cfg.stun_srv_cnt != 0;
+}
 
 /*
@@ -2154,4 +2240,5 @@
 						pj_bool_t renew)
 {
+    pjsua_acc *acc;
     pj_status_t status = 0;
     pjsip_tx_data *tdata = 0;
@@ -2166,4 +2253,6 @@
 
     PJSUA_LOCK();
+
+    acc = &pjsua_var.acc[acc_id];
 
     /* Cancel any re-registration timer */
@@ -2233,4 +2322,13 @@
                                        &pjsua_var.acc[acc_id].via_addr,
                                        pjsua_var.acc[acc_id].via_tp);
+        } else if (!pjsua_sip_acc_is_using_stun(acc_id)) {
+            /* Choose local interface to use in Via if acc is not using
+             * STUN
+             */
+            pjsua_acc_get_uac_addr(acc_id, tdata->pool,
+	                           &acc->cfg.reg_uri,
+	                           &tdata->via_addr,
+	                           NULL, NULL,
+	                           &tdata->via_tp);
         }
 
@@ -2613,9 +2711,14 @@
 }
 
-
-PJ_DEF(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool,
-						  pj_str_t *contact,
-						  pjsua_acc_id acc_id,
-						  const pj_str_t *suri)
+/* Get local transport address suitable to be used for Via or Contact address
+ * to send request to the specified destination URI.
+ */
+pj_status_t pjsua_acc_get_uac_addr(pjsua_acc_id acc_id,
+				   pj_pool_t *pool,
+				   const pj_str_t *dst_uri,
+				   pjsip_host_port *addr,
+				   pjsip_transport_type_e *p_tp_type,
+				   int *secure,
+				   const void **p_tp)
 {
     pjsua_acc *acc;
@@ -2623,28 +2726,17 @@
     pj_status_t status;
     pjsip_transport_type_e tp_type = PJSIP_TRANSPORT_UNSPECIFIED;
-    pj_str_t local_addr;
+    unsigned flag;
     pjsip_tpselector tp_sel;
-    unsigned flag;
-    int secure;
-    int local_port;
-    const char *beginquote, *endquote;
-    char transport_param[32];
-    const char *ob = ";ob";
-
-    
+    pjsip_tpmgr *tpmgr;
+    pjsip_tpmgr_fla2_param tfla2_prm;
+
     PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL);
     acc = &pjsua_var.acc[acc_id];
 
-    /* If force_contact is configured, then use use it */
-    if (acc->cfg.force_contact.slen) {
-	*contact = acc->cfg.force_contact;
-	return PJ_SUCCESS;
-    }
-
-    /* If route-set is configured for the account, then URI is the 
+    /* If route-set is configured for the account, then URI is the
      * first entry of the route-set.
      */
     if (!pj_list_empty(&acc->route_set)) {
-	sip_uri = (pjsip_sip_uri*) 
+	sip_uri = (pjsip_sip_uri*)
 		  pjsip_uri_get_uri(acc->route_set.next->name_addr.uri);
     } else {
@@ -2652,5 +2744,5 @@
 	pjsip_uri *uri;
 
-	pj_strdup_with_null(pool, &tmp, suri);
+	pj_strdup_with_null(pool, &tmp, dst_uri);
 
 	uri = pjsip_parse_uri(pool, tmp.ptr, tmp.slen, 0);
@@ -2672,5 +2764,5 @@
     } else
 	tp_type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
-    
+
     if (tp_type == PJSIP_TRANSPORT_UNSPECIFIED)
 	return PJSIP_EUNSUPTRANSPORT;
@@ -2683,13 +2775,64 @@
 
     flag = pjsip_transport_get_flag_from_type(tp_type);
-    secure = (flag & PJSIP_TRANSPORT_SECURE) != 0;
 
     /* Init transport selector. */
-    pjsua_init_tpselector(pjsua_var.acc[acc_id].cfg.transport_id, &tp_sel);
+    pjsua_init_tpselector(acc->cfg.transport_id, &tp_sel);
 
     /* Get local address suitable to send request from */
-    status = pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(pjsua_var.endpt),
-					 pool, tp_type, &tp_sel, 
-					 &local_addr, &local_port);
+    pjsip_tpmgr_fla2_param_default(&tfla2_prm);
+    tfla2_prm.tp_type = tp_type;
+    tfla2_prm.tp_sel = &tp_sel;
+    tfla2_prm.dst_host = sip_uri->host;
+    tfla2_prm.local_if = (!pjsua_sip_acc_is_using_stun(acc_id) ||
+	                  (flag & PJSIP_TRANSPORT_RELIABLE));
+
+    tpmgr = pjsip_endpt_get_tpmgr(pjsua_var.endpt);
+    status = pjsip_tpmgr_find_local_addr2(tpmgr, pool, &tfla2_prm);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    addr->host = tfla2_prm.ret_addr;
+    addr->port = tfla2_prm.ret_port;
+
+    if (p_tp_type)
+	*p_tp_type = tp_type;
+
+    if (secure) {
+	*secure = (flag & PJSIP_TRANSPORT_SECURE) != 0;
+    }
+
+    if (p_tp)
+	*p_tp = tfla2_prm.ret_tp;
+
+    return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pjsua_acc_create_uac_contact( pj_pool_t *pool,
+						  pj_str_t *contact,
+						  pjsua_acc_id acc_id,
+						  const pj_str_t *suri)
+{
+    pjsua_acc *acc;
+    pj_status_t status;
+    pjsip_transport_type_e tp_type;
+    pjsip_host_port addr;
+    int secure;
+    const char *beginquote, *endquote;
+    char transport_param[32];
+    const char *ob = ";ob";
+
+    
+    PJ_ASSERT_RETURN(pjsua_acc_is_valid(acc_id), PJ_EINVAL);
+    acc = &pjsua_var.acc[acc_id];
+
+    /* If force_contact is configured, then use use it */
+    if (acc->cfg.force_contact.slen) {
+	*contact = acc->cfg.force_contact;
+	return PJ_SUCCESS;
+    }
+
+    status = pjsua_acc_get_uac_addr(acc_id, pool, suri, &addr,
+                                    &tp_type, &secure, NULL);
     if (status != PJ_SUCCESS)
 	return status;
@@ -2726,8 +2869,8 @@
 				     (acc->user_part.slen?"@":""),
 				     beginquote,
-				     (int)local_addr.slen,
-				     local_addr.ptr,
+				     (int)addr.host.slen,
+				     addr.host.ptr,
 				     endquote,
-				     local_port,
+				     addr.port,
 				     transport_param,
 				     (int)acc->cfg.contact_uri_params.slen,
@@ -2761,4 +2904,6 @@
     pj_str_t local_addr;
     pjsip_tpselector tp_sel;
+    pjsip_tpmgr *tpmgr;
+    pjsip_tpmgr_fla2_param tfla2_prm;
     unsigned flag;
     int secure;
@@ -2848,9 +2993,19 @@
 
     /* Get local address suitable to send request from */
-    status = pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(pjsua_var.endpt),
-					 pool, tp_type, &tp_sel,
-					 &local_addr, &local_port);
+    pjsip_tpmgr_fla2_param_default(&tfla2_prm);
+    tfla2_prm.tp_type = tp_type;
+    tfla2_prm.tp_sel = &tp_sel;
+    tfla2_prm.dst_host = sip_uri->host;
+    tfla2_prm.local_if = (!pjsua_sip_acc_is_using_stun(acc_id) ||
+	                  (flag & PJSIP_TRANSPORT_RELIABLE));
+
+    tpmgr = pjsip_endpt_get_tpmgr(pjsua_var.endpt);
+    status = pjsip_tpmgr_find_local_addr2(tpmgr, pool, &tfla2_prm);
     if (status != PJ_SUCCESS)
 	return status;
+
+    local_addr = tfla2_prm.ret_addr;
+    local_port = tfla2_prm.ret_port;
+
 
     /* Enclose IPv6 address in square brackets */
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 4217)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 4218)
@@ -1183,5 +1183,5 @@
     if (pjsua_var.acc[acc_id].cfg.require_100rel == PJSUA_100REL_MANDATORY)
 	options |= PJSIP_INV_REQUIRE_100REL;
-    if (pjsua_var.media_cfg.enable_ice)
+    if (pjsua_var.acc[acc_id].cfg.ice_cfg.enable_ice)
 	options |= PJSIP_INV_SUPPORT_ICE;
     if (pjsua_var.acc[acc_id].cfg.use_timer == PJSUA_SIP_TIMER_REQUIRED)
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4217)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4218)
@@ -197,10 +197,62 @@
 					const pjsua_transport_config *src)
 {
+    pj_memcpy(dst, src, sizeof(*src));
+    pj_strdup(pool, &dst->public_addr, &src->public_addr);
+    pj_strdup(pool, &dst->bound_addr, &src->bound_addr);
+}
+
+PJ_DEF(void) pjsua_ice_config_from_media_config( pj_pool_t *pool,
+                                           pjsua_ice_config *dst,
+                                           const pjsua_media_config *src)
+{
+    PJ_UNUSED_ARG(pool);
+
+    dst->enable_ice = src->enable_ice;
+    dst->ice_max_host_cands = src->ice_max_host_cands;
+    dst->ice_opt = src->ice_opt;
+    dst->ice_no_rtcp = src->ice_no_rtcp;
+}
+
+PJ_DEF(void) pjsua_ice_config_dup( pj_pool_t *pool,
+                                pjsua_ice_config *dst,
+                                const pjsua_ice_config *src)
+{
     PJ_UNUSED_ARG(pool);
     pj_memcpy(dst, src, sizeof(*src));
 }
 
+PJ_DEF(void) pjsua_turn_config_from_media_config(pj_pool_t *pool,
+                                                 pjsua_turn_config *dst,
+                                                 const pjsua_media_config *src)
+{
+    dst->enable_turn = src->enable_turn;
+    dst->turn_conn_type = src->turn_conn_type;
+    if (pool == NULL) {
+	dst->turn_server = src->turn_server;
+	dst->turn_auth_cred = src->turn_auth_cred;
+    } else {
+	if (pj_stricmp(&dst->turn_server, &src->turn_server))
+	    pj_strdup(pool, &dst->turn_server, &src->turn_server);
+	pj_stun_auth_cred_dup(pool, &dst->turn_auth_cred,
+	                      &src->turn_auth_cred);
+    }
+}
+
+PJ_DEF(void) pjsua_turn_config_dup(pj_pool_t *pool,
+                                   pjsua_turn_config *dst,
+                                   const pjsua_turn_config *src)
+{
+    pj_memcpy(dst, src, sizeof(*src));
+    if (pool) {
+	pj_strdup(pool, &dst->turn_server, &src->turn_server);
+	pj_stun_auth_cred_dup(pool, &dst->turn_auth_cred,
+	                      &src->turn_auth_cred);
+    }
+}
+
 PJ_DEF(void) pjsua_acc_config_default(pjsua_acc_config *cfg)
 {
+    pjsua_media_config med_cfg;
+
     pj_bzero(cfg, sizeof(*cfg));
 
@@ -225,4 +277,9 @@
 #endif
     pjsua_transport_config_default(&cfg->rtp_cfg);
+
+    pjsua_media_config_default(&med_cfg);
+    pjsua_ice_config_from_media_config(NULL, &cfg->ice_cfg, &med_cfg);
+    pjsua_turn_config_from_media_config(NULL, &cfg->turn_cfg, &med_cfg);
+
     cfg->use_srtp = pjsua_var.ua_cfg.use_srtp;
     cfg->srtp_secure_signaling = pjsua_var.ua_cfg.srtp_secure_signaling;
@@ -2806,4 +2863,5 @@
     for (i=0; i<pjsua_var.ua_cfg.max_calls; ++i) {
 	pjsua_call *call = &pjsua_var.calls[i];
+	pjsua_acc_config *acc_cfg;
 	pjmedia_transport *tp[PJSUA_MAX_CALL_MEDIA*2];
 	unsigned tp_cnt = 0;
@@ -2831,4 +2889,6 @@
 	}
 
+	acc_cfg = &pjsua_var.acc[call->acc_id].cfg;
+
 	/* Dump the media transports in this call */
 	for (j = 0; j < tp_cnt; ++j) {
@@ -2839,5 +2899,5 @@
 	    pjmedia_transport_get_info(tp[j], &tpinfo);
 	    PJ_LOG(3,(THIS_FILE, " %s: %s",
-		      (pjsua_var.media_cfg.enable_ice ? "ICE" : "UDP"),
+		      (acc_cfg->ice_cfg.enable_ice ? "ICE" : "UDP"),
 		      pj_sockaddr_print(&tpinfo.sock_info.rtp_addr_name,
 					addr_buf,
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4217)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4218)
@@ -166,7 +166,9 @@
 
     /* Perform NAT detection */
-    status = pjsua_detect_nat_type();
-    if (status != PJ_SUCCESS) {
-	PJ_PERROR(1,(THIS_FILE, status, "NAT type detection failed"));
+    if (pjsua_var.ua_cfg.stun_srv_cnt) {
+	status = pjsua_detect_nat_type();
+	if (status != PJ_SUCCESS) {
+	    PJ_PERROR(1,(THIS_FILE, status, "NAT type detection failed"));
+	}
     }
 
@@ -227,5 +229,6 @@
  * address via STUN.
  */
-static pj_status_t create_rtp_rtcp_sock(const pjsua_transport_config *cfg,
+static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med,
+					const pjsua_transport_config *cfg,
 					pjmedia_sock_info *skinfo)
 {
@@ -241,8 +244,10 @@
 
     /* Make sure STUN server resolution has completed */
-    status = resolve_stun_server(PJ_TRUE);
-    if (status != PJ_SUCCESS) {
-	pjsua_perror(THIS_FILE, "Error resolving STUN server", status);
-	return status;
+    if (pjsua_sip_acc_is_using_stun(call_med->call->acc_id)) {
+	status = resolve_stun_server(PJ_TRUE);
+	if (status != PJ_SUCCESS) {
+	    pjsua_perror(THIS_FILE, "Error resolving STUN server", status);
+	    return status;
+	}
     }
 
@@ -319,5 +324,7 @@
 	 * and make sure that the mapped RTCP port is adjacent with the RTP.
 	 */
-	if (pjsua_var.stun_srv.addr.sa_family != 0) {
+	if (pjsua_sip_acc_is_using_stun(call_med->call->acc_id) &&
+	    pjsua_var.stun_srv.addr.sa_family != 0)
+	{
 	    char ip_addr[32];
 	    pj_str_t stun_srv;
@@ -441,5 +448,5 @@
     pj_status_t status;
 
-    status = create_rtp_rtcp_sock(cfg, &skinfo);
+    status = create_rtp_rtcp_sock(call_med, cfg, &skinfo);
     if (status != PJ_SUCCESS) {
 	pjsua_perror(THIS_FILE, "Unable to create RTP/RTCP socket",
@@ -661,4 +668,5 @@
 {
     char stunip[PJ_INET6_ADDRSTRLEN];
+    pjsua_acc_config *acc_cfg;
     pj_ice_strans_cfg ice_cfg;
     pjmedia_ice_cb ice_cb;
@@ -666,4 +674,6 @@
     unsigned comp_cnt;
     pj_status_t status;
+
+    acc_cfg = &pjsua_var.acc[call_med->call->acc_id].cfg;
 
     /* Make sure STUN server resolution has completed */
@@ -683,5 +693,5 @@
     ice_cfg.resolver = pjsua_var.resolver;
     
-    ice_cfg.opt = pjsua_var.media_cfg.ice_opt;
+    ice_cfg.opt = acc_cfg->ice_cfg.ice_opt;
 
     /* Configure STUN settings */
@@ -691,6 +701,6 @@
 	ice_cfg.stun.port = pj_sockaddr_get_port(&pjsua_var.stun_srv);
     }
-    if (pjsua_var.media_cfg.ice_max_host_cands >= 0)
-	ice_cfg.stun.max_host_cands = pjsua_var.media_cfg.ice_max_host_cands;
+    if (acc_cfg->ice_cfg.ice_max_host_cands >= 0)
+	ice_cfg.stun.max_host_cands = acc_cfg->ice_cfg.ice_max_host_cands;
 
     /* Copy QoS setting to STUN setting */
@@ -700,6 +710,6 @@
 
     /* Configure TURN settings */
-    if (pjsua_var.media_cfg.enable_turn) {
-	status = parse_host_port(&pjsua_var.media_cfg.turn_server,
+    if (acc_cfg->turn_cfg.enable_turn) {
+	status = parse_host_port(&acc_cfg->turn_cfg.turn_server,
 				 &ice_cfg.turn.server,
 				 &ice_cfg.turn.port);
@@ -710,7 +720,7 @@
 	if (ice_cfg.turn.port == 0)
 	    ice_cfg.turn.port = 3479;
-	ice_cfg.turn.conn_type = pjsua_var.media_cfg.turn_conn_type;
+	ice_cfg.turn.conn_type = acc_cfg->turn_cfg.turn_conn_type;
 	pj_memcpy(&ice_cfg.turn.auth_cred, 
-		  &pjsua_var.media_cfg.turn_auth_cred,
+		  &acc_cfg->turn_cfg.turn_auth_cred,
 		  sizeof(ice_cfg.turn.auth_cred));
 
@@ -731,5 +741,5 @@
 
     comp_cnt = 1;
-    if (PJMEDIA_ADVERTISE_RTCP && !pjsua_var.media_cfg.ice_no_rtcp)
+    if (PJMEDIA_ADVERTISE_RTCP && !acc_cfg->ice_cfg.ice_no_rtcp)
 	++comp_cnt;
 
@@ -859,5 +869,5 @@
 
     /* Create the transports */
-    if (pjsua_var.media_cfg.enable_ice) {
+    if (pjsua_var.ice_cfg.enable_ice) {
 	status = create_ice_media_transports(&cfg);
     } else {
@@ -1245,5 +1255,5 @@
         pjsua_set_media_tp_state(call_med, PJSUA_MED_TP_CREATING);
 
-	if (pjsua_var.media_cfg.enable_ice) {
+	if (pjsua_var.acc[call_med->call->acc_id].cfg.ice_cfg.enable_ice) {
 	    status = create_ice_media_transport(tcfg, call_med, async);
             if (async && status == PJ_EPENDING) {
