Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4254)
+++ 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");
+		}
 	    }
 
