Index: pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 4261)
+++ pjproject/trunk/pjsip-apps/src/pjsua/pjsua_app.c	(revision 4262)
@@ -171,5 +171,4 @@
 static void stereo_demo();
 #endif
-static pj_status_t create_ipv6_media_transports(void);
 pj_status_t app_destroy(void);
 
@@ -877,6 +876,6 @@
 
 	case OPT_NO_UDP: /* no-udp */
-	    if (cfg->no_tcp) {
-	      PJ_LOG(1,(THIS_FILE,"Error: can not disable both TCP and UDP"));
+	    if (cfg->no_tcp && !cfg->use_tls) {
+	      PJ_LOG(1,(THIS_FILE,"Error: cannot disable both TCP and UDP"));
 	      return PJ_EINVAL;
 	    }
@@ -890,6 +889,6 @@
 
 	case OPT_NO_TCP: /* no-tcp */
-	    if (cfg->no_udp) {
-	      PJ_LOG(1,(THIS_FILE,"Error: can not disable both TCP and UDP"));
+	    if (cfg->no_udp && !cfg->use_tls) {
+	      PJ_LOG(1,(THIS_FILE,"Error: cannot disable both TCP and UDP"));
 	      return PJ_EINVAL;
 	    }
@@ -5908,4 +5907,6 @@
 	    pjsua_acc_get_config(aid, &acc_cfg);
 	    app_config_init_video(&acc_cfg);
+	    if (app_config.ipv6)
+		acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
 	    pjsua_acc_modify(aid, &acc_cfg);
 	}
@@ -5944,4 +5945,31 @@
 	pjsua_acc_set_online_status(current_acc, PJ_TRUE);
 
+    }
+
+    /* Add TCP IPv6 transport unless it's disabled. */
+    if (!app_config.no_tcp && app_config.ipv6) {
+	pjsua_acc_id aid;
+	pjsip_transport_type_e type = PJSIP_TRANSPORT_TCP6;
+
+	tcp_cfg.port += 10;
+
+	status = pjsua_transport_create(type,
+					&tcp_cfg,
+					&transport_id);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+	/* Add local account */
+	pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
+	if (PJMEDIA_HAS_VIDEO) {
+	    pjsua_acc_config acc_cfg;
+	    pjsua_acc_get_config(aid, &acc_cfg);
+	    app_config_init_video(&acc_cfg);
+	    if (app_config.ipv6)
+		acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
+	    pjsua_acc_modify(aid, &acc_cfg);
+	}
+	//pjsua_acc_set_transport(aid, transport_id);
+	pjsua_acc_set_online_status(current_acc, PJ_TRUE);
     }
 
@@ -5977,4 +6005,32 @@
 	pjsua_acc_set_online_status(acc_id, PJ_TRUE);
     }
+
+    /* Add TLS IPv6 transport unless it's disabled. */
+    if (app_config.use_tls && app_config.ipv6) {
+	pjsua_acc_id aid;
+	pjsip_transport_type_e type = PJSIP_TRANSPORT_TLS6;
+
+	tcp_cfg.port += 10;
+
+	status = pjsua_transport_create(type,
+					&tcp_cfg,
+					&transport_id);
+	if (status != PJ_SUCCESS)
+	    goto on_error;
+
+	/* Add local account */
+	pjsua_acc_add_local(transport_id, PJ_TRUE, &aid);
+	if (PJMEDIA_HAS_VIDEO) {
+	    pjsua_acc_config acc_cfg;
+	    pjsua_acc_get_config(aid, &acc_cfg);
+	    app_config_init_video(&acc_cfg);
+	    if (app_config.ipv6)
+		acc_cfg.ipv6_media_use = PJSUA_IPV6_ENABLED;
+	    pjsua_acc_modify(aid, &acc_cfg);
+	}
+	//pjsua_acc_set_transport(aid, transport_id);
+	pjsua_acc_set_online_status(current_acc, PJ_TRUE);
+    }
+
 #endif
 
@@ -6026,14 +6082,4 @@
 #endif
     }
-
-    /* Add RTP transports */
-    if (app_config.ipv6)
-	status = create_ipv6_media_transports();
-  #if DISABLED_FOR_TICKET_1185
-    else
-	status = pjsua_media_transports_create(&app_config.rtp_cfg);
-  #endif
-    if (status != PJ_SUCCESS)
-	goto on_error;
 
     /* Use null sound device? */
@@ -6252,93 +6298,2 @@
 #endif
 
-static pj_status_t create_ipv6_media_transports(void)
-{
-    pjsua_media_transport tp[PJSUA_MAX_CALLS];
-    pj_status_t status;
-    int port = app_config.rtp_cfg.port;
-    unsigned i;
-
-    for (i=0; i<app_config.cfg.max_calls; ++i) {
-	enum { MAX_RETRY = 10 };
-	pj_sock_t sock[2];
-	pjmedia_sock_info si;
-	unsigned j;
-
-	/* Get rid of uninitialized var compiler warning with MSVC */
-	status = PJ_SUCCESS;
-
-	for (j=0; j<MAX_RETRY; ++j) {
-	    unsigned k;
-
-	    for (k=0; k<2; ++k) {
-		pj_sockaddr bound_addr;
-
-		status = pj_sock_socket(pj_AF_INET6(), pj_SOCK_DGRAM(), 0, &sock[k]);
-		if (status != PJ_SUCCESS)
-		    break;
-
-		status = pj_sockaddr_init(pj_AF_INET6(), &bound_addr,
-					  &app_config.rtp_cfg.bound_addr, 
-					  (unsigned short)(port+k));
-		if (status != PJ_SUCCESS)
-		    break;
-
-		status = pj_sock_bind(sock[k], &bound_addr, 
-				      pj_sockaddr_get_len(&bound_addr));
-		if (status != PJ_SUCCESS)
-		    break;
-	    }
-	    if (status != PJ_SUCCESS) {
-		if (k==1)
-		    pj_sock_close(sock[0]);
-
-		if (port != 0)
-		    port += 10;
-		else
-		    break;
-
-		continue;
-	    }
-
-	    pj_bzero(&si, sizeof(si));
-	    si.rtp_sock = sock[0];
-	    si.rtcp_sock = sock[1];
-	
-	    pj_sockaddr_init(pj_AF_INET6(), &si.rtp_addr_name, 
-			     &app_config.rtp_cfg.public_addr, 
-			     (unsigned short)(port));
-	    pj_sockaddr_init(pj_AF_INET6(), &si.rtcp_addr_name, 
-			     &app_config.rtp_cfg.public_addr, 
-			     (unsigned short)(port+1));
-
-	    status = pjmedia_transport_udp_attach(pjsua_get_pjmedia_endpt(),
-						  NULL,
-						  &si,
-						  0,
-						  &tp[i].transport);
-	    if (port != 0)
-		port += 10;
-	    else
-		break;
-
-	    if (status == PJ_SUCCESS)
-		break;
-	}
-
-	if (status != PJ_SUCCESS) {
-	    pjsua_perror(THIS_FILE, "Error creating IPv6 UDP media transport", 
-			 status);
-	    for (j=0; j<i; ++j) {
-		pjmedia_transport_close(tp[j].transport);
-	    }
-	    return status;
-	}
-    }
-
-#if DISABLED_FOR_TICKET_1185
-    return pjsua_media_transports_attach(tp, i, PJ_TRUE);
-#else
-    return PJ_ENOTSUP;
-#endif
-}
-
Index: pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h	(revision 4261)
+++ pjproject/trunk/pjsip/include/pjsip/sip_transport_tls.h	(revision 4262)
@@ -262,4 +262,6 @@
  * instance of SIP TLS transport factory and register it to the
  * transport manager.
+ *
+ * See also #pjsip_tls_transport_start2() which supports IPv6.
  *
  * @param endpt		The SIP endpoint.
@@ -295,5 +297,41 @@
 					       pjsip_tpfactory **p_factory);
 
-
+/**
+ * Variant of #pjsip_tls_transport_start() that supports IPv6. To instantiate
+ * IPv6 listener, set the address family of the "local" argument to IPv6
+ * (the host and port part may be left unspecified if not desired, i.e. by
+ * filling them with zeroes).
+ *
+ * @param endpt		The SIP endpoint.
+ * @param opt		Optional TLS settings.
+ * @param local		Optional local address to bind, or specify the
+ *			address to bind the server socket to. Both IP
+ *			interface address and port fields are optional.
+ *			If IP interface address is not specified, socket
+ *			will be bound to any address. If port is not
+ *			specified, socket will be bound to any port
+ *			selected by the operating system.
+ * @param a_name	Optional published address, which is the address to be
+ *			advertised as the address of this SIP transport.
+ *			If this argument is NULL, then the bound address
+ *			will be used as the published address.
+ * @param async_cnt	Number of simultaneous asynchronous accept()
+ *			operations to be supported. It is recommended that
+ *			the number here corresponds to the number of
+ *			processors in the system (or the number of SIP
+ *			worker threads).
+ * @param p_factory	Optional pointer to receive the instance of the
+ *			SIP TLS transport factory just created.
+ *
+ * @return		PJ_SUCCESS when the transport has been successfully
+ *			started and registered to transport manager, or
+ *			the appropriate error code.
+ */
+PJ_DECL(pj_status_t) pjsip_tls_transport_start2(pjsip_endpoint *endpt,
+ 					        const pjsip_tls_setting *opt,
+					        const pj_sockaddr *local,
+					        const pjsip_host_port *a_name,
+					        unsigned async_cnt,
+					        pjsip_tpfactory **p_factory);
 
 PJ_END_DECL
Index: pjproject/trunk/pjsip/include/pjsip/sip_types.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_types.h	(revision 4261)
+++ pjproject/trunk/pjsip/include/pjsip/sip_types.h	(revision 4262)
@@ -93,5 +93,8 @@
 
     /** TCP over IPv6 */
-    PJSIP_TRANSPORT_TCP6 = PJSIP_TRANSPORT_TCP + PJSIP_TRANSPORT_IPV6
+    PJSIP_TRANSPORT_TCP6 = PJSIP_TRANSPORT_TCP + PJSIP_TRANSPORT_IPV6,
+
+    /** TLS over IPv6 */
+    PJSIP_TRANSPORT_TLS6 = PJSIP_TRANSPORT_TLS + PJSIP_TRANSPORT_IPV6
 
 } pjsip_transport_type_e;
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 4261)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 4262)
@@ -2691,4 +2691,21 @@
 
 /**
+ * Specify how IPv6 transport should be used in account config.
+ */
+typedef enum pjsua_ipv6_use
+{
+    /**
+     * IPv6 is not used.
+     */
+    PJSUA_IPV6_DISABLED,
+
+    /**
+     * IPv6 is enabled.
+     */
+    PJSUA_IPV6_ENABLED
+
+} pjsua_ipv6_use;
+
+/**
  * This structure describes account configuration to be specified when
  * adding a new account with #pjsua_acc_add(). Application MUST initialize
@@ -3089,4 +3106,9 @@
      */
     pjsua_transport_config rtp_cfg;
+
+    /**
+     * Specify whether IPv6 should be used on media.
+     */
+    pjsua_ipv6_use     		ipv6_media_use;
 
     /**
Index: pjproject/trunk/pjsip/src/pjsip/sip_transport.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 4261)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transport.c	(revision 4262)
@@ -199,4 +199,11 @@
 	PJSIP_TRANSPORT_RELIABLE
     },
+    {
+	PJSIP_TRANSPORT_TLS6,
+	5061,
+	{"TLS", 3},
+	"TLS IPv6 transport",
+	PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE
+    },
 };
 
@@ -1280,7 +1287,18 @@
 		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);
+		if (status == PJ_SUCCESS) {
+		    pj_strdup(pool, &prm->ret_addr, &tmp_str);
+		} else {
+		    /* It could fail "normally" on certain cases, e.g.
+		     * when connecting to IPv6 link local address, it
+		     * will wail with EINVAL.
+		     * In this case, fallback to use the default interface
+		     * rather than failing the call.
+		     */
+		    PJ_PERROR(5,(THIS_FILE, status, "Warning: unable to "
+			         "determine local interface"));
+		    pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
+		    status = PJ_SUCCESS;
+		}
 	    } else {
 		pj_strdup(pool, &prm->ret_addr, &f->addr_name.host);
Index: pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c	(revision 4261)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c	(revision 4262)
@@ -58,4 +58,5 @@
     pjsip_tpmgr		    *tpmgr;
     pj_activesock_t	    *asock;
+    pj_sockaddr		     bound_addr;
     pj_qos_type		     qos_type;
     pj_qos_params	     qos_params;
@@ -142,6 +143,6 @@
 			      pj_pool_t *pool,
 			      pj_sock_t sock, pj_bool_t is_server,
-			      const pj_sockaddr_in *local,
-			      const pj_sockaddr_in *remote,
+			      const pj_sockaddr *local,
+			      const pj_sockaddr *remote,
 			      struct tcp_transport **p_tcp);
 
@@ -160,8 +161,8 @@
 static void sockaddr_to_host_port( pj_pool_t *pool,
 				   pjsip_host_port *host_port,
-				   const pj_sockaddr_in *addr )
+				   const pj_sockaddr *addr )
 {
     host_port->host.ptr = (char*) pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+4);
-    pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 2);
+    pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 0);
     host_port->host.slen = pj_ansi_strlen(host_port->host.ptr);
     host_port->port = pj_sockaddr_get_port(addr);
@@ -268,8 +269,10 @@
     listener = PJ_POOL_ZALLOC_T(pool, struct tcp_listener);
     listener->factory.pool = pool;
-    listener->factory.type = PJSIP_TRANSPORT_TCP;
-    listener->factory.type_name = "tcp";
+    listener->factory.type = cfg->af==pj_AF_INET() ? PJSIP_TRANSPORT_TCP :
+						     PJSIP_TRANSPORT_TCP6;
+    listener->factory.type_name = (char*)
+		pjsip_transport_get_type_name(listener->factory.type);
     listener->factory.flag = 
-	pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TCP);
+	pjsip_transport_get_flag_from_type(listener->factory.type);
     listener->qos_type = cfg->qos_type;
     pj_memcpy(&listener->qos_params, &cfg->qos_params,
@@ -277,6 +280,8 @@
 
     pj_ansi_strcpy(listener->factory.obj_name, "tcplis");
-
-    status = pj_lock_create_recursive_mutex(pool, "tcplis", 
+    if (listener->factory.type==PJSIP_TRANSPORT_TCP6)
+	pj_ansi_strcat(listener->factory.obj_name, "6");
+
+    status = pj_lock_create_recursive_mutex(pool, listener->factory.obj_name,
 					    &listener->factory.lock);
     if (status != PJ_SUCCESS)
@@ -293,4 +298,9 @@
 				2, listener->factory.obj_name, 
 				"SIP TCP listener socket");
+
+    /* Bind address may be different than factory.local_addr because
+     * factory.local_addr will be resolved below.
+     */
+    pj_sockaddr_cp(&listener->bound_addr, &cfg->bind_addr);
 
     /* Bind socket */
@@ -328,11 +338,10 @@
 	    pj_sockaddr hostip;
 
-	    status = pj_gethostip(pj_AF_INET(), &hostip);
+	    status = pj_gethostip(listener->bound_addr.addr.sa_family,
+	                          &hostip);
 	    if (status != PJ_SUCCESS)
 		goto on_error;
 
-	    pj_memcpy(pj_sockaddr_get_addr(listener_addr),
-		      pj_sockaddr_get_addr(&hostip),
-		      pj_sockaddr_get_addr_len(&hostip));
+	    pj_sockaddr_copy_addr(listener_addr, &hostip);
 	}
 
@@ -340,5 +349,5 @@
 	sockaddr_to_host_port(listener->factory.pool, 
 			      &listener->factory.addr_name, 
-			      (pj_sockaddr_in*)listener_addr);
+			      listener_addr);
     }
 
@@ -537,6 +546,6 @@
 			       pj_pool_t *pool,
 			       pj_sock_t sock, pj_bool_t is_server,
-			       const pj_sockaddr_in *local,
-			       const pj_sockaddr_in *remote,
+			       const pj_sockaddr *local,
+			       const pj_sockaddr *remote,
 			       struct tcp_transport **p_tcp)
 {
@@ -546,4 +555,5 @@
     pj_activesock_cb tcp_callback;
     const pj_str_t ka_pkt = PJSIP_TCP_KEEP_ALIVE_DATA;
+    char print_addr[PJ_INET6_ADDRSTRLEN+10];
     pj_status_t status;
     
@@ -581,16 +591,18 @@
     }
 
-    tcp->base.key.type = PJSIP_TRANSPORT_TCP;
-    pj_memcpy(&tcp->base.key.rem_addr, remote, sizeof(pj_sockaddr_in));
-    tcp->base.type_name = "tcp";
-    tcp->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TCP);
+    tcp->base.key.type = listener->factory.type;
+    pj_sockaddr_cp(&tcp->base.key.rem_addr, remote);
+    tcp->base.type_name = (char*)
+			  pjsip_transport_get_type_name(tcp->base.key.type);
+    tcp->base.flag = pjsip_transport_get_flag_from_type(tcp->base.key.type);
 
     tcp->base.info = (char*) pj_pool_alloc(pool, 64);
-    pj_ansi_snprintf(tcp->base.info, 64, "TCP to %s:%d",
-		     pj_inet_ntoa(remote->sin_addr), 
-		     (int)pj_ntohs(remote->sin_port));
-
-    tcp->base.addr_len = sizeof(pj_sockaddr_in);
-    pj_memcpy(&tcp->base.local_addr, local, sizeof(pj_sockaddr_in));
+    pj_ansi_snprintf(tcp->base.info, 64, "%s to %s",
+                     tcp->base.type_name,
+                     pj_sockaddr_print(remote, print_addr,
+                                       sizeof(print_addr), 3));
+
+    tcp->base.addr_len = pj_sockaddr_get_len(remote);
+    pj_sockaddr_cp(&tcp->base.local_addr, local);
     sockaddr_to_host_port(pool, &tcp->base.local_name, local);
     sockaddr_to_host_port(pool, &tcp->base.remote_name, remote);
@@ -602,5 +614,4 @@
     tcp->base.do_shutdown = &tcp_shutdown;
     tcp->base.destroy = &tcp_destroy_transport;
-
 
     /* Create active socket */
@@ -802,5 +813,5 @@
     pj_pool_t *pool;
     pj_ssize_t size;
-    pj_sockaddr_in *rem_addr;
+    pj_sockaddr *rem_addr;
     void *readbuf[1];
     pj_status_t status;
@@ -825,9 +836,9 @@
 
     tcp->rdata.pkt_info.src_addr = tcp->base.key.rem_addr;
-    tcp->rdata.pkt_info.src_addr_len = sizeof(pj_sockaddr_in);
-    rem_addr = (pj_sockaddr_in*) &tcp->base.key.rem_addr;
-    pj_ansi_strcpy(tcp->rdata.pkt_info.src_name,
-		   pj_inet_ntoa(rem_addr->sin_addr));
-    tcp->rdata.pkt_info.src_port = pj_ntohs(rem_addr->sin_port);
+    tcp->rdata.pkt_info.src_addr_len = sizeof(tcp->rdata.pkt_info.src_addr);
+    rem_addr = &tcp->base.key.rem_addr;
+    pj_sockaddr_print(rem_addr, tcp->rdata.pkt_info.src_name,
+                      sizeof(tcp->rdata.pkt_info.src_name), 0);
+    tcp->rdata.pkt_info.src_port = pj_sockaddr_get_port(rem_addr);
 
     size = sizeof(tcp->rdata.pkt_info.packet);
@@ -859,5 +870,5 @@
     struct tcp_transport *tcp;
     pj_sock_t sock;
-    pj_sockaddr_in local_addr;
+    pj_sockaddr local_addr;
     pj_status_t status;
 
@@ -866,14 +877,16 @@
 		     addr_len && p_transport, PJ_EINVAL);
 
-    /* Check that address is a sockaddr_in */
-    PJ_ASSERT_RETURN(rem_addr->addr.sa_family == pj_AF_INET() &&
-		     addr_len == sizeof(pj_sockaddr_in), PJ_EINVAL);
+    /* Check that address is a sockaddr_in or sockaddr_in6*/
+    PJ_ASSERT_RETURN((rem_addr->addr.sa_family == pj_AF_INET() &&
+		      addr_len == sizeof(pj_sockaddr_in)) ||
+		     (rem_addr->addr.sa_family == pj_AF_INET6() &&
+		      addr_len == sizeof(pj_sockaddr_in6)), PJ_EINVAL);
 
 
     listener = (struct tcp_listener*)factory;
 
-    
     /* Create socket */
-    status = pj_sock_socket(pj_AF_INET(), pj_SOCK_STREAM(), 0, &sock);
+    status = pj_sock_socket(rem_addr->addr.sa_family, pj_SOCK_STREAM(),
+                            0, &sock);
     if (status != PJ_SUCCESS)
 	return status;
@@ -885,6 +898,11 @@
 				"outgoing SIP TCP socket");
 
-    /* Bind to any port */
-    status = pj_sock_bind_in(sock, 0, 0);
+    /* Bind to listener's address and any port */
+    pj_bzero(&local_addr, sizeof(local_addr));
+    pj_sockaddr_cp(&local_addr, &listener->bound_addr);
+    pj_sockaddr_set_port(&local_addr, 0);
+
+    status = pj_sock_bind(sock, &local_addr,
+                          pj_sockaddr_get_len(&local_addr));
     if (status != PJ_SUCCESS) {
 	pj_sock_close(sock);
@@ -893,5 +911,5 @@
 
     /* Get the local port */
-    addr_len = sizeof(pj_sockaddr_in);
+    addr_len = sizeof(local_addr);
     status = pj_sock_getsockname(sock, &local_addr, &addr_len);
     if (status != PJ_SUCCESS) {
@@ -901,10 +919,11 @@
 
     /* Initially set the address from the listener's address */
-    local_addr.sin_addr.s_addr = 
-	((pj_sockaddr_in*)&listener->factory.local_addr)->sin_addr.s_addr;
+    if (!pj_sockaddr_has_addr(&local_addr)) {
+	pj_sockaddr_copy_addr(&local_addr, &listener->factory.local_addr);
+    }
 
     /* Create the transport descriptor */
     status = tcp_create(listener, NULL, sock, PJ_FALSE, &local_addr, 
-			(pj_sockaddr_in*)rem_addr, &tcp);
+			rem_addr, &tcp);
     if (status != PJ_SUCCESS)
 	return status;
@@ -914,5 +933,5 @@
     tcp->has_pending_connect = PJ_TRUE;
     status = pj_activesock_start_connect(tcp->asock, tcp->base.pool, rem_addr,
-					 sizeof(pj_sockaddr_in));
+					 addr_len);
     if (status == PJ_SUCCESS) {
 	on_connect_complete(tcp->asock, PJ_SUCCESS);
@@ -926,16 +945,15 @@
 	 * set is different now that asynchronous connect() is started.
 	 */
-	addr_len = sizeof(pj_sockaddr_in);
+	addr_len = sizeof(local_addr);
 	if (pj_sock_getsockname(sock, &local_addr, &addr_len)==PJ_SUCCESS) {
-	    pj_sockaddr_in *tp_addr = (pj_sockaddr_in*)&tcp->base.local_addr;
+	    pj_sockaddr *tp_addr = &tcp->base.local_addr;
 
 	    /* Some systems (like old Win32 perhaps) may not set local address
 	     * properly before socket is fully connected.
 	     */
-	    if (tp_addr->sin_addr.s_addr != local_addr.sin_addr.s_addr &&
-		local_addr.sin_addr.s_addr != 0) 
+	    if (pj_sockaddr_cmp(tp_addr, &local_addr) &&
+		pj_sockaddr_get_port(&local_addr) != 0)
 	    {
-		tp_addr->sin_addr.s_addr = local_addr.sin_addr.s_addr;
-		tp_addr->sin_port = local_addr.sin_port;
+		pj_sockaddr_cp(tp_addr, &local_addr);
 		sockaddr_to_host_port(tcp->base.pool, &tcp->base.local_name,
 				      &local_addr);
@@ -973,4 +991,5 @@
     char addr[PJ_INET6_ADDRSTRLEN+10];
     pjsip_tp_state_callback state_cb;
+    pj_sockaddr tmp_src_addr;
     pj_status_t status;
 
@@ -996,4 +1015,10 @@
 				"incoming SIP TCP socket");
 
+    /* tcp_create() expect pj_sockaddr, so copy src_addr to temporary var,
+     * just in case.
+     */
+    pj_bzero(&tmp_src_addr, sizeof(tmp_src_addr));
+    pj_sockaddr_cp(&tmp_src_addr, src_addr);
+
     /* 
      * Incoming connection!
@@ -1001,6 +1026,6 @@
      */
     status = tcp_create( listener, NULL, sock, PJ_TRUE,
-			 (const pj_sockaddr_in*)&listener->factory.local_addr,
-			 (const pj_sockaddr_in*)src_addr, &tcp);
+			 &listener->factory.local_addr,
+			 &tmp_src_addr, &tcp);
     if (status == PJ_SUCCESS) {
 	status = tcp_start_read(tcp);
@@ -1106,7 +1131,7 @@
     
     /* Check the address is supported */
-    PJ_ASSERT_RETURN(rem_addr && addr_len==sizeof(pj_sockaddr_in), PJ_EINVAL);
-
-
+    PJ_ASSERT_RETURN(rem_addr && (addr_len==sizeof(pj_sockaddr_in) ||
+	                          addr_len==sizeof(pj_sockaddr_in6)),
+	             PJ_EINVAL);
 
     /* Init op key. */
@@ -1289,5 +1314,5 @@
 {
     struct tcp_transport *tcp;
-    pj_sockaddr_in addr;
+    pj_sockaddr addr;
     int addrlen;
     pjsip_tp_state_callback state_cb;
@@ -1334,13 +1359,12 @@
      * on some systems, like old Win32 probably?).
      */
-    addrlen = sizeof(pj_sockaddr_in);
+    addrlen = sizeof(addr);
     if (pj_sock_getsockname(tcp->sock, &addr, &addrlen)==PJ_SUCCESS) {
-	pj_sockaddr_in *tp_addr = (pj_sockaddr_in*)&tcp->base.local_addr;
+	pj_sockaddr *tp_addr = &tcp->base.local_addr;
 
 	if (pj_sockaddr_has_addr(&addr) &&
-	    tp_addr->sin_addr.s_addr != addr.sin_addr.s_addr) 
+	    pj_sockaddr_cmp(&addr, tp_addr) != 0)
 	{
-	    tp_addr->sin_addr.s_addr = addr.sin_addr.s_addr;
-	    tp_addr->sin_port = addr.sin_port;
+	    pj_sockaddr_cp(tp_addr, &addr);
 	    sockaddr_to_host_port(tcp->base.pool, &tcp->base.local_name,
 				  tp_addr);
Index: pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c	(revision 4261)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transport_tls.c	(revision 4262)
@@ -56,4 +56,5 @@
     pjsip_tpmgr		    *tpmgr;
     pj_ssl_sock_t	    *ssock;
+    pj_sockaddr		     bound_addr;
     pj_ssl_cert_t	    *cert;
     pjsip_tls_setting	     tls_setting;
@@ -148,6 +149,6 @@
 			      pj_ssl_sock_t *ssock, 
 			      pj_bool_t is_server,
-			      const pj_sockaddr_in *local,
-			      const pj_sockaddr_in *remote,
+			      const pj_sockaddr *local,
+			      const pj_sockaddr *remote,
 			      const pj_str_t *remote_name,
 			      struct tls_transport **p_tls);
@@ -167,8 +168,8 @@
 static void sockaddr_to_host_port( pj_pool_t *pool,
 				   pjsip_host_port *host_port,
-				   const pj_sockaddr_in *addr )
+				   const pj_sockaddr *addr )
 {
     host_port->host.ptr = (char*) pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN+4);
-    pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 2);
+    pj_sockaddr_print(addr, host_port->host.ptr, PJ_INET6_ADDRSTRLEN+4, 0);
     host_port->host.slen = pj_ansi_strlen(host_port->host.ptr);
     host_port->port = pj_sockaddr_get_port(addr);
@@ -236,13 +237,31 @@
 PJ_DEF(pj_status_t) pjsip_tls_transport_start (pjsip_endpoint *endpt,
 					       const pjsip_tls_setting *opt,
-					       const pj_sockaddr_in *local,
+					       const pj_sockaddr_in *local_in,
 					       const pjsip_host_port *a_name,
 					       unsigned async_cnt,
 					       pjsip_tpfactory **p_factory)
 {
+    pj_sockaddr local;
+
+    if (local_in)
+	pj_sockaddr_cp(&local, local_in);
+
+    return pjsip_tls_transport_start2(endpt, opt, (local_in? &local : NULL),
+                                      a_name, async_cnt, p_factory);
+}
+
+PJ_DEF(pj_status_t) pjsip_tls_transport_start2( pjsip_endpoint *endpt,
+ 					        const pjsip_tls_setting *opt,
+					        const pj_sockaddr *local,
+					        const pjsip_host_port *a_name,
+					        unsigned async_cnt,
+					        pjsip_tpfactory **p_factory)
+{
     pj_pool_t *pool;
+    pj_bool_t is_ipv6;
+    int af;
     struct tls_listener *listener;
     pj_ssl_sock_param ssock_param;
-    pj_sockaddr_in *listener_addr;
+    pj_sockaddr *listener_addr;
     pj_bool_t has_listener;
     pj_status_t status;
@@ -251,12 +270,15 @@
     PJ_ASSERT_RETURN(endpt && async_cnt, PJ_EINVAL);
 
+    is_ipv6 = (local && local->addr.sa_family == pj_AF_INET6());
+    af = is_ipv6 ? pj_AF_INET6() : pj_AF_INET();
+
     /* Verify that address given in a_name (if any) is valid */
     if (a_name && a_name->host.slen) {
-	pj_sockaddr_in tmp;
-
-	status = pj_sockaddr_in_init(&tmp, &a_name->host, 
-				     (pj_uint16_t)a_name->port);
-	if (status != PJ_SUCCESS || tmp.sin_addr.s_addr == PJ_INADDR_ANY ||
-	    tmp.sin_addr.s_addr == PJ_INADDR_NONE)
+	pj_sockaddr tmp;
+
+	status = pj_sockaddr_init(af, &tmp, &a_name->host,
+				  (pj_uint16_t)a_name->port);
+	if (status != PJ_SUCCESS || !pj_sockaddr_has_addr(&tmp) ||
+	    (!is_ipv6 && tmp.ipv4.sin_addr.s_addr == PJ_INADDR_NONE))
 	{
 	    /* Invalid address */
@@ -271,10 +293,16 @@
     listener = PJ_POOL_ZALLOC_T(pool, struct tls_listener);
     listener->factory.pool = pool;
-    listener->factory.type = PJSIP_TRANSPORT_TLS;
-    listener->factory.type_name = "tls";
+    if (is_ipv6)
+	listener->factory.type = PJSIP_TRANSPORT_TLS6;
+    else
+	listener->factory.type = PJSIP_TRANSPORT_TLS;
+    listener->factory.type_name = (char*)
+		pjsip_transport_get_type_name(listener->factory.type);
     listener->factory.flag = 
-	pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TLS);
+	pjsip_transport_get_flag_from_type(listener->factory.type);
 
     pj_ansi_strcpy(listener->factory.obj_name, "tlslis");
+    if (is_ipv6)
+	pj_ansi_strcat(listener->factory.obj_name, "6");
 
     if (opt)
@@ -283,5 +311,5 @@
 	pjsip_tls_setting_default(&listener->tls_setting);
 
-    status = pj_lock_create_recursive_mutex(pool, "tlslis", 
+    status = pj_lock_create_recursive_mutex(pool, listener->factory.obj_name,
 					    &listener->factory.lock);
     if (status != PJ_SUCCESS)
@@ -293,4 +321,5 @@
     /* Build SSL socket param */
     pj_ssl_sock_param_default(&ssock_param);
+    ssock_param.sock_af = af;
     ssock_param.cb.on_accept_complete = &on_accept_complete;
     ssock_param.cb.on_data_read = &on_data_read;
@@ -339,10 +368,15 @@
 	goto on_error;
 
-    listener_addr = (pj_sockaddr_in*)&listener->factory.local_addr;
+    /* Bind address may be different than factory.local_addr because
+     * factory.local_addr will be resolved below.
+     */
+    listener_addr = &listener->factory.local_addr;
     if (local) {
 	pj_sockaddr_cp((pj_sockaddr_t*)listener_addr, 
 		       (const pj_sockaddr_t*)local);
+	pj_sockaddr_cp(&listener->bound_addr, local);
     } else {
-	pj_sockaddr_in_init(listener_addr, NULL, 0);
+	pj_sockaddr_init(af, listener_addr, NULL, 0);
+	pj_sockaddr_init(af, &listener->bound_addr, NULL, 0);
     }
 
@@ -402,12 +436,12 @@
 	 * interface address as the transport's address.
 	 */
-	if (listener_addr->sin_addr.s_addr == 0) {
+	if (!pj_sockaddr_has_addr(listener_addr)) {
 	    pj_sockaddr hostip;
 
-	    status = pj_gethostip(pj_AF_INET(), &hostip);
+	    status = pj_gethostip(af, &hostip);
 	    if (status != PJ_SUCCESS)
 		goto on_error;
 
-	    listener_addr->sin_addr.s_addr = hostip.ipv4.sin_addr.s_addr;
+	    pj_sockaddr_copy_addr(listener_addr, &hostip);
 	}
 
@@ -419,5 +453,5 @@
     /* If port is zero, get the bound port */
     if (listener->factory.addr_name.port == 0) {
-	listener->factory.addr_name.port = pj_ntohs(listener_addr->sin_port);
+	listener->factory.addr_name.port = pj_sockaddr_get_port(listener_addr);
     }
 
@@ -536,6 +570,6 @@
 			       pj_ssl_sock_t *ssock,
 			       pj_bool_t is_server,
-			       const pj_sockaddr_in *local,
-			       const pj_sockaddr_in *remote,
+			       const pj_sockaddr *local,
+			       const pj_sockaddr *remote,
 			       const pj_str_t *remote_name,
 			       struct tls_transport **p_tls)
@@ -543,4 +577,5 @@
     struct tls_transport *tls;
     const pj_str_t ka_pkt = PJSIP_TLS_KEEP_ALIVE_DATA;
+    char print_addr[PJ_INET6_ADDRSTRLEN+10];
     pj_status_t status;
     
@@ -580,15 +615,18 @@
 	pj_strdup(pool, &tls->remote_name, remote_name);
 
-    tls->base.key.type = PJSIP_TRANSPORT_TLS;
-    pj_memcpy(&tls->base.key.rem_addr, remote, sizeof(pj_sockaddr_in));
-    tls->base.type_name = "tls";
-    tls->base.flag = pjsip_transport_get_flag_from_type(PJSIP_TRANSPORT_TLS);
+    tls->base.key.type = listener->factory.type;
+    pj_sockaddr_cp(&tls->base.key.rem_addr, remote);
+    tls->base.type_name = (char*)
+			  pjsip_transport_get_type_name(tls->base.key.type);
+    tls->base.flag = pjsip_transport_get_flag_from_type(tls->base.key.type);
 
     tls->base.info = (char*) pj_pool_alloc(pool, 64);
-    pj_ansi_snprintf(tls->base.info, 64, "TLS to %s:%d",
-		     pj_inet_ntoa(remote->sin_addr), 
-		     (int)pj_ntohs(remote->sin_port));
-
-    tls->base.addr_len = sizeof(pj_sockaddr_in);
+    pj_ansi_snprintf(tls->base.info, 64, "%s to %s",
+                     tls->base.type_name,
+                     pj_sockaddr_print(remote, print_addr,
+                                       sizeof(print_addr), 3));
+
+
+    tls->base.addr_len = pj_sockaddr_get_len(remote);
     tls->base.dir = is_server? PJSIP_TP_DIR_INCOMING : PJSIP_TP_DIR_OUTGOING;
     
@@ -601,9 +639,8 @@
     }
     
-    sockaddr_to_host_port(pool, &tls->base.local_name, 
-			  (pj_sockaddr_in*)&tls->base.local_addr);
+    sockaddr_to_host_port(pool, &tls->base.local_name, &tls->base.local_addr);
     if (tls->remote_name.slen) {
 	tls->base.remote_name.host = tls->remote_name;
-	tls->base.remote_name.port = pj_sockaddr_in_get_port(remote);
+	tls->base.remote_name.port = pj_sockaddr_get_port(remote);
     } else {
 	sockaddr_to_host_port(pool, &tls->base.remote_name, remote);
@@ -795,5 +832,5 @@
     pj_pool_t *pool;
     pj_ssize_t size;
-    pj_sockaddr_in *rem_addr;
+    pj_sockaddr *rem_addr;
     void *readbuf[1];
     pj_status_t status;
@@ -818,9 +855,9 @@
 
     tls->rdata.pkt_info.src_addr = tls->base.key.rem_addr;
-    tls->rdata.pkt_info.src_addr_len = sizeof(pj_sockaddr_in);
-    rem_addr = (pj_sockaddr_in*) &tls->base.key.rem_addr;
-    pj_ansi_strcpy(tls->rdata.pkt_info.src_name,
-		   pj_inet_ntoa(rem_addr->sin_addr));
-    tls->rdata.pkt_info.src_port = pj_ntohs(rem_addr->sin_port);
+    tls->rdata.pkt_info.src_addr_len = sizeof(tls->rdata.pkt_info.src_addr);
+    rem_addr = &tls->base.key.rem_addr;
+    pj_sockaddr_print(rem_addr, tls->rdata.pkt_info.src_name,
+                          sizeof(tls->rdata.pkt_info.src_name), 0);
+    tls->rdata.pkt_info.src_port = pj_sockaddr_get_port(rem_addr);
 
     size = sizeof(tls->rdata.pkt_info.packet);
@@ -855,5 +892,5 @@
     pj_ssl_sock_t *ssock;
     pj_ssl_sock_param ssock_param;
-    pj_sockaddr_in local_addr;
+    pj_sockaddr local_addr;
     pj_str_t remote_name;
     pj_status_t status;
@@ -863,7 +900,9 @@
 		     addr_len && p_transport, PJ_EINVAL);
 
-    /* Check that address is a sockaddr_in */
-    PJ_ASSERT_RETURN(rem_addr->addr.sa_family == pj_AF_INET() &&
-		     addr_len == sizeof(pj_sockaddr_in), PJ_EINVAL);
+    /* Check that address is a sockaddr_in or sockaddr_in6*/
+    PJ_ASSERT_RETURN((rem_addr->addr.sa_family == pj_AF_INET() &&
+		      addr_len == sizeof(pj_sockaddr_in)) ||
+		     (rem_addr->addr.sa_family == pj_AF_INET6() &&
+		      addr_len == sizeof(pj_sockaddr_in6)), PJ_EINVAL);
 
 
@@ -882,4 +921,6 @@
     /* Build SSL socket param */
     pj_ssl_sock_param_default(&ssock_param);
+    ssock_param.sock_af = (factory->type & PJSIP_TRANSPORT_IPV6) ?
+			    pj_AF_INET6() : pj_AF_INET();
     ssock_param.cb.on_connect_complete = &on_connect_complete;
     ssock_param.cb.on_data_read = &on_data_read;
@@ -932,10 +973,12 @@
     }
 
-    /* Initially set bind address to PJ_INADDR_ANY port 0 */
-    pj_sockaddr_in_init(&local_addr, NULL, 0);
+    /* Initially set bind address to listener's bind address */
+    pj_sockaddr_init(listener->bound_addr.addr.sa_family,
+		     &local_addr, NULL, 0);
+    pj_sockaddr_copy_addr(&local_addr, &listener->bound_addr);
 
     /* Create the transport descriptor */
     status = tls_create(listener, pool, ssock, PJ_FALSE, &local_addr, 
-			(pj_sockaddr_in*)rem_addr, &remote_name, &tls);
+			rem_addr, &remote_name, &tls);
     if (status != PJ_SUCCESS)
 	return status;
@@ -984,5 +1027,5 @@
 
 	    sockaddr_to_host_port(tls->base.pool, &tls->base.local_name,
-				  (pj_sockaddr_in*)&tls->base.local_addr);
+				  &tls->base.local_addr);
 	}
 
@@ -1018,4 +1061,5 @@
     char addr[PJ_INET6_ADDRSTRLEN+10];
     pjsip_tp_state_callback state_cb;
+    pj_sockaddr tmp_src_addr;
     pj_bool_t is_shutdown;
     pj_status_t status;
@@ -1045,4 +1089,8 @@
     }
 
+    /* Copy to larger buffer, just in case */
+    pj_bzero(&tmp_src_addr, sizeof(tmp_src_addr));
+    pj_sockaddr_cp(&tmp_src_addr, src_addr);
+
     /* 
      * Incoming connection!
@@ -1050,6 +1098,6 @@
      */
     status = tls_create( listener, NULL, new_ssock, PJ_TRUE,
-			 (const pj_sockaddr_in*)&listener->factory.local_addr,
-			 (const pj_sockaddr_in*)src_addr, NULL, &tls);
+			 &listener->factory.local_addr,
+			 &tmp_src_addr, NULL, &tls);
     
     if (status != PJ_SUCCESS)
@@ -1201,7 +1249,7 @@
     
     /* Check the address is supported */
-    PJ_ASSERT_RETURN(rem_addr && addr_len==sizeof(pj_sockaddr_in), PJ_EINVAL);
-
-
+    PJ_ASSERT_RETURN(rem_addr && (addr_len==sizeof(pj_sockaddr_in) ||
+	                          addr_len==sizeof(pj_sockaddr_in6)),
+	             PJ_EINVAL);
 
     /* Init op key. */
@@ -1385,5 +1433,5 @@
     struct tls_transport *tls;
     pj_ssl_sock_info ssl_info;
-    pj_sockaddr_in addr, *tp_addr;
+    pj_sockaddr addr, *tp_addr;
     pjsip_tp_state_callback state_cb;
     pj_bool_t is_shutdown;
@@ -1423,10 +1471,9 @@
      * on some systems, like old Win32 probably?).
      */
-    tp_addr = (pj_sockaddr_in*)&tls->base.local_addr;
+    tp_addr = &tls->base.local_addr;
     pj_sockaddr_cp((pj_sockaddr_t*)&addr, 
 		   (pj_sockaddr_t*)&ssl_info.local_addr);
-    if (tp_addr->sin_addr.s_addr != addr.sin_addr.s_addr) {
-	tp_addr->sin_addr.s_addr = addr.sin_addr.s_addr;
-	tp_addr->sin_port = addr.sin_port;
+    if (pj_sockaddr_cmp(tp_addr, &addr) != 0) {
+	pj_sockaddr_cp(tp_addr, &addr);
 	sockaddr_to_host_port(tls->base.pool, &tls->base.local_name,
 			      tp_addr);
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 4261)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_acc.c	(revision 4262)
@@ -1190,4 +1190,6 @@
 	acc->cfg.rtp_cfg =  cfg->rtp_cfg;
     }
+
+    acc->cfg.ipv6_media_use = cfg->ipv6_media_use;
 
     /* STUN and Media customization */
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4261)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4262)
@@ -2068,6 +2068,8 @@
 	pjsip_tpfactory *tcp;
 	pjsip_tcp_transport_cfg tcp_cfg;
-
-	pjsip_tcp_transport_cfg_default(&tcp_cfg, pj_AF_INET());
+	int af;
+
+	af = (type==PJSIP_TRANSPORT_TCP6) ? pj_AF_INET6() : pj_AF_INET();
+	pjsip_tcp_transport_cfg_default(&tcp_cfg, af);
 
 	/* Supply default config if it's not specified */
@@ -2119,5 +2121,5 @@
 
 #if defined(PJSIP_HAS_TLS_TRANSPORT) && PJSIP_HAS_TLS_TRANSPORT!=0
-    } else if (type == PJSIP_TRANSPORT_TLS) {
+    } else if (type == PJSIP_TRANSPORT_TLS || type == PJSIP_TRANSPORT_TLS6) {
 	/*
 	 * Create TLS transport.
@@ -2126,5 +2128,6 @@
 	pjsip_host_port a_name;
 	pjsip_tpfactory *tls;
-	pj_sockaddr_in local_addr;
+	pj_sockaddr local_addr;
+	int af;
 
 	/* Supply default config if it's not specified */
@@ -2136,11 +2139,13 @@
 
 	/* Init local address */
-	pj_sockaddr_in_init(&local_addr, 0, 0);
+	af = (type==PJSIP_TRANSPORT_TLS) ? pj_AF_INET() : pj_AF_INET6();
+	pj_sockaddr_init(af, &local_addr, NULL, 0);
 
 	if (cfg->port)
-	    local_addr.sin_port = pj_htons((pj_uint16_t)cfg->port);
+	    pj_sockaddr_set_port(&local_addr, (pj_uint16_t)cfg->port);
 
 	if (cfg->bound_addr.slen) {
-	    status = pj_sockaddr_in_set_str_addr(&local_addr,&cfg->bound_addr);
+	    status = pj_sockaddr_set_str_addr(af, &local_addr,
+	                                      &cfg->bound_addr);
 	    if (status != PJ_SUCCESS) {
 		pjsua_perror(THIS_FILE, 
@@ -2156,7 +2161,7 @@
 	    a_name.host = cfg->public_addr;
 
-	status = pjsip_tls_transport_start(pjsua_var.endpt, 
-					   &cfg->tls_setting, 
-					   &local_addr, &a_name, 1, &tls);
+	status = pjsip_tls_transport_start2(pjsua_var.endpt,
+					    &cfg->tls_setting,
+					    &local_addr, &a_name, 1, &tls);
 	if (status != PJ_SUCCESS) {
 	    pjsua_perror(THIS_FILE, "Error creating SIP TLS listener", 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4261)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4262)
@@ -237,12 +237,18 @@
     };
     int i;
-    pj_sockaddr_in bound_addr;
-    pj_sockaddr_in mapped_addr[2];
+    pj_bool_t use_ipv6;
+    int af;
+    pj_sockaddr bound_addr;
+    pj_sockaddr mapped_addr[2];
     pj_status_t status = PJ_SUCCESS;
-    char addr_buf[PJ_INET6_ADDRSTRLEN+2];
+    char addr_buf[PJ_INET6_ADDRSTRLEN+10];
     pj_sock_t sock[2];
 
+    use_ipv6 = (pjsua_var.acc[call_med->call->acc_id].cfg.ipv6_media_use !=
+		PJSUA_IPV6_DISABLED);
+    af = use_ipv6 ? pj_AF_INET6() : pj_AF_INET();
+
     /* Make sure STUN server resolution has completed */
-    if (pjsua_sip_acc_is_using_stun(call_med->call->acc_id)) {
+    if (!use_ipv6 && pjsua_sip_acc_is_using_stun(call_med->call->acc_id)) {
 	status = resolve_stun_server(PJ_TRUE);
 	if (status != PJ_SUCCESS) {
@@ -261,7 +267,7 @@
 	sock[i] = PJ_INVALID_SOCKET;
 
-    bound_addr.sin_addr.s_addr = PJ_INADDR_ANY;
+    pj_sockaddr_init(af, &bound_addr, NULL, 0);
     if (cfg->bound_addr.slen) {
-	status = pj_sockaddr_in_set_str_addr(&bound_addr, &cfg->bound_addr);
+	status = pj_sockaddr_set_str_addr(af, &bound_addr, &cfg->bound_addr);
 	if (status != PJ_SUCCESS) {
 	    pjsua_perror(THIS_FILE, "Unable to resolve transport bind address",
@@ -275,5 +281,5 @@
 
 	/* Create RTP socket. */
-	status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock[0]);
+	status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock[0]);
 	if (status != PJ_SUCCESS) {
 	    pjsua_perror(THIS_FILE, "socket() error", status);
@@ -287,6 +293,7 @@
 
 	/* Bind RTP socket */
-	status=pj_sock_bind_in(sock[0], pj_ntohl(bound_addr.sin_addr.s_addr),
-			       next_rtp_port);
+	pj_sockaddr_set_port(&bound_addr, next_rtp_port);
+	status=pj_sock_bind(sock[0], &bound_addr,
+	                    pj_sockaddr_get_len(&bound_addr));
 	if (status != PJ_SUCCESS) {
 	    pj_sock_close(sock[0]);
@@ -296,5 +303,5 @@
 
 	/* Create RTCP socket. */
-	status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock[1]);
+	status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &sock[1]);
 	if (status != PJ_SUCCESS) {
 	    pjsua_perror(THIS_FILE, "socket() error", status);
@@ -309,6 +316,7 @@
 
 	/* Bind RTCP socket */
-	status=pj_sock_bind_in(sock[1], pj_ntohl(bound_addr.sin_addr.s_addr),
-			       (pj_uint16_t)(next_rtp_port+1));
+	pj_sockaddr_set_port(&bound_addr, (pj_uint16_t)(next_rtp_port+1));
+	status=pj_sock_bind(sock[1], &bound_addr,
+	                    pj_sockaddr_get_len(&bound_addr));
 	if (status != PJ_SUCCESS) {
 	    pj_sock_close(sock[0]);
@@ -324,9 +332,10 @@
 	 * and make sure that the mapped RTCP port is adjacent with the RTP.
 	 */
-	if (pjsua_sip_acc_is_using_stun(call_med->call->acc_id) &&
+	if (!use_ipv6 && 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;
+	    pj_sockaddr_in resolved_addr[2];
 	    pjstun_setting stun_opt;
 
@@ -341,5 +350,5 @@
 			     pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port);
 	    status=pjstun_get_mapped_addr2(&pjsua_var.cp.factory, &stun_opt,
-					   2, sock, mapped_addr);
+					   2, sock, resolved_addr);
 	    if (status != PJ_SUCCESS) {
 		pjsua_perror(THIS_FILE, "STUN resolve error", status);
@@ -347,7 +356,10 @@
 	    }
 
+	    pj_sockaddr_cp(&mapped_addr[0], &resolved_addr[0]);
+	    pj_sockaddr_cp(&mapped_addr[1], &resolved_addr[1]);
+
 #if PJSUA_REQUIRE_CONSECUTIVE_RTCP_PORT
-	    if (pj_ntohs(mapped_addr[1].sin_port) ==
-		pj_ntohs(mapped_addr[0].sin_port)+1)
+	    if (pj_sockaddr_get_port(&mapped_addr[1]) ==
+		pj_sockaddr_get_port(&mapped_addr[0])+1)
 	    {
 		/* Success! */
@@ -361,12 +373,12 @@
 	    sock[1] = PJ_INVALID_SOCKET;
 #else
-	    if (pj_ntohs(mapped_addr[1].sin_port) !=
-		pj_ntohs(mapped_addr[0].sin_port)+1)
+	    if (pj_sockaddr_get_port(&mapped_addr[1]) !=
+		pj_sockaddr_get_port(&mapped_addr[0])+1)
 	    {
 		PJ_LOG(4,(THIS_FILE,
 			  "Note: STUN mapped RTCP port %d is not adjacent"
 			  " to RTP port %d",
-			  pj_ntohs(mapped_addr[1].sin_port),
-			  pj_ntohs(mapped_addr[0].sin_port)));
+			  pj_sockaddr_get_port(&mapped_addr[1]),
+			  pj_sockaddr_get_port(&mapped_addr[0])));
 	    }
 	    /* Success! */
@@ -376,11 +388,11 @@
 	} else if (cfg->public_addr.slen) {
 
-	    status = pj_sockaddr_in_init(&mapped_addr[0], &cfg->public_addr,
-					 (pj_uint16_t)next_rtp_port);
+	    status = pj_sockaddr_init(af, &mapped_addr[0], &cfg->public_addr,
+				      (pj_uint16_t)next_rtp_port);
 	    if (status != PJ_SUCCESS)
 		goto on_error;
 
-	    status = pj_sockaddr_in_init(&mapped_addr[1], &cfg->public_addr,
-					 (pj_uint16_t)(next_rtp_port+1));
+	    status = pj_sockaddr_init(af, &mapped_addr[1], &cfg->public_addr,
+				      (pj_uint16_t)(next_rtp_port+1));
 	    if (status != PJ_SUCCESS)
 		goto on_error;
@@ -390,22 +402,22 @@
 	} else {
 
-	    if (bound_addr.sin_addr.s_addr == 0) {
+	    if (!pj_sockaddr_has_addr(&bound_addr)) {
 		pj_sockaddr addr;
 
 		/* Get local IP address. */
-		status = pj_gethostip(pj_AF_INET(), &addr);
+		status = pj_gethostip(af, &addr);
 		if (status != PJ_SUCCESS)
 		    goto on_error;
 
-		bound_addr.sin_addr.s_addr = addr.ipv4.sin_addr.s_addr;
+		pj_sockaddr_copy_addr(&bound_addr, &addr);
 	    }
 
 	    for (i=0; i<2; ++i) {
-		pj_sockaddr_in_init(&mapped_addr[i], NULL, 0);
-		mapped_addr[i].sin_addr.s_addr = bound_addr.sin_addr.s_addr;
-	    }
-
-	    mapped_addr[0].sin_port=pj_htons((pj_uint16_t)next_rtp_port);
-	    mapped_addr[1].sin_port=pj_htons((pj_uint16_t)(next_rtp_port+1));
+		pj_sockaddr_init(af, &mapped_addr[i], NULL, 0);
+		pj_sockaddr_copy_addr(&mapped_addr[i], &bound_addr);
+		pj_sockaddr_set_port(&mapped_addr[i],
+		                     (pj_uint16_t)(next_rtp_port+i));
+	    }
+
 	    break;
 	}
@@ -420,10 +432,8 @@
 
     skinfo->rtp_sock = sock[0];
-    pj_memcpy(&skinfo->rtp_addr_name,
-	      &mapped_addr[0], sizeof(pj_sockaddr_in));
+    pj_sockaddr_cp(&skinfo->rtp_addr_name, &mapped_addr[0]);
 
     skinfo->rtcp_sock = sock[1];
-    pj_memcpy(&skinfo->rtcp_addr_name,
-	      &mapped_addr[1], sizeof(pj_sockaddr_in));
+    pj_sockaddr_cp(&skinfo->rtcp_addr_name, &mapped_addr[1]);
 
     PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s",
@@ -1909,8 +1919,18 @@
 	    /* Add connection line, if none */
 	    if (m->conn == NULL && sdp->conn == NULL) {
+		pj_bool_t use_ipv6;
+
+		use_ipv6 = (pjsua_var.acc[call->acc_id].cfg.ipv6_media_use !=
+			    PJSUA_IPV6_DISABLED);
+
 		m->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
 		m->conn->net_type = pj_str("IN");
-		m->conn->addr_type = pj_str("IP4");
-		m->conn->addr = pj_str("127.0.0.1");
+		if (use_ipv6) {
+		    m->conn->addr_type = pj_str("IP6");
+		    m->conn->addr = pj_str("::1");
+		} else {
+		    m->conn->addr_type = pj_str("IP4");
+		    m->conn->addr = pj_str("127.0.0.1");
+		}
 	    }
 
