Index: pjproject/trunk/build.symbian/pjmediaU.def
===================================================================
--- pjproject/trunk/build.symbian/pjmediaU.def	(revision 1614)
+++ pjproject/trunk/build.symbian/pjmediaU.def	(revision 1615)
@@ -175,15 +175,16 @@
 	pjmedia_transport_udp_create             @ 174 NONAME
 	pjmedia_transport_udp_create2            @ 175 NONAME
-	pjmedia_transport_udp_get_info           @ 176 NONAME
-	pjmedia_transport_udp_simulate_lost      @ 177 NONAME
-	pjmedia_wav_player_port_create           @ 178 NONAME
-	pjmedia_wav_player_port_get_pos          @ 179 NONAME
-	pjmedia_wav_player_port_set_pos          @ 180 NONAME
-	pjmedia_wav_player_set_eof_cb            @ 181 NONAME
-	pjmedia_wav_playlist_create              @ 182 NONAME
-	pjmedia_wav_playlist_set_eof_cb          @ 183 NONAME
-	pjmedia_wav_writer_port_create           @ 184 NONAME
-	pjmedia_wav_writer_port_get_pos          @ 185 NONAME
-	pjmedia_wav_writer_port_set_cb           @ 186 NONAME
-	pjmedia_wave_hdr_file_to_host            @ 187 NONAME
-	pjmedia_wave_hdr_host_to_file            @ 188 NONAME
+	pjmedia_transport_udp_create3            @ 176 NONAME
+	pjmedia_transport_udp_get_info           @ 177 NONAME
+	pjmedia_transport_udp_simulate_lost      @ 178 NONAME
+	pjmedia_wav_player_port_create           @ 179 NONAME
+	pjmedia_wav_player_port_get_pos          @ 180 NONAME
+	pjmedia_wav_player_port_set_pos          @ 181 NONAME
+	pjmedia_wav_player_set_eof_cb            @ 182 NONAME
+	pjmedia_wav_playlist_create              @ 183 NONAME
+	pjmedia_wav_playlist_set_eof_cb          @ 184 NONAME
+	pjmedia_wav_writer_port_create           @ 185 NONAME
+	pjmedia_wav_writer_port_get_pos          @ 186 NONAME
+	pjmedia_wav_writer_port_set_cb           @ 187 NONAME
+	pjmedia_wave_hdr_file_to_host            @ 188 NONAME
+	pjmedia_wave_hdr_host_to_file            @ 189 NONAME
Index: pjproject/trunk/pjmedia/include/pjmedia/stream.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/stream.h	(revision 1614)
+++ pjproject/trunk/pjmedia/include/pjmedia/stream.h	(revision 1615)
@@ -91,6 +91,6 @@
     pjmedia_type	type;	    /**< Media type (audio, video)	    */
     pjmedia_dir		dir;	    /**< Media direction.		    */
-    pj_sockaddr_in	rem_addr;   /**< Remote RTP address		    */
-    pj_sockaddr_in	rem_rtcp;   /**< Optional remote RTCP address. If
+    pj_sockaddr		rem_addr;   /**< Remote RTP address		    */
+    pj_sockaddr		rem_rtcp;   /**< Optional remote RTCP address. If
 					 sin_family is zero, the RTP address
 					 will be calculated from RTP.	    */
Index: pjproject/trunk/pjmedia/include/pjmedia/transport_udp.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/transport_udp.h	(revision 1614)
+++ pjproject/trunk/pjmedia/include/pjmedia/transport_udp.h	(revision 1615)
@@ -113,4 +113,30 @@
 
 /**
+ * Another variant of #pjmedia_transport_udp_create() which allows
+ * the creation of IPv6 transport.
+ *
+ * @param endpt	    The media endpoint instance.
+ * @param af	    Address family, which can be pj_AF_INET() for IPv4 or
+ *		    pj_AF_INET6() for IPv6.
+ * @param name	    Optional name to be assigned to the transport.
+ * @param addr	    Optional local address to bind the sockets to. If this
+ *		    argument is NULL or empty, the sockets will be bound
+ *		    to all interface.
+ * @param port	    UDP port number for the RTP socket. The RTCP port number
+ *		    will be set to one above RTP port.
+ * @param options   Options, bitmask of #pjmedia_transport_udp_options.
+ * @param p_tp	    Pointer to receive the transport instance.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_transport_udp_create3(pjmedia_endpt *endpt,
+						   int af,
+						   const char *name,
+						   const pj_str_t *addr,
+						   int port,
+						   unsigned options,
+						   pjmedia_transport **p_tp);
+
+/**
  * Get media socket info from the specified UDP transport.
  *
Index: pjproject/trunk/pjmedia/include/pjmedia/types.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/types.h	(revision 1614)
+++ pjproject/trunk/pjmedia/include/pjmedia/types.h	(revision 1615)
@@ -142,5 +142,5 @@
      *  with STUN).
      */
-    pj_sockaddr_in  rtp_addr_name;
+    pj_sockaddr	    rtp_addr_name;
 
     /** The RTCP socket handle. */
@@ -152,5 +152,5 @@
      *  with STUN).
      */
-    pj_sockaddr_in  rtcp_addr_name;
+    pj_sockaddr	    rtcp_addr_name;
 
 } pjmedia_sock_info;
Index: pjproject/trunk/pjmedia/src/pjmedia/endpoint.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/endpoint.c	(revision 1614)
+++ pjproject/trunk/pjmedia/src/pjmedia/endpoint.c	(revision 1615)
@@ -35,4 +35,5 @@
 static const pj_str_t STR_IN = { "IN", 2 };
 static const pj_str_t STR_IP4 = { "IP4", 3};
+static const pj_str_t STR_IP6 = { "IP6", 3};
 static const pj_str_t STR_RTP_AVP = { "RTP/AVP", 7 };
 static const pj_str_t STR_SDP_NAME = { "pjmedia", 7 };
@@ -290,4 +291,5 @@
     pj_time_val tv;
     unsigned i;
+    const pj_sockaddr *addr0;
     pjmedia_sdp_session *sdp;
     pjmedia_sdp_media *m;
@@ -303,4 +305,6 @@
     /* Create and initialize basic SDP session */
     sdp = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_session);
+
+    addr0 = &sock_info[0].rtp_addr_name;
 
     pj_gettimeofday(&tv);
@@ -308,7 +312,21 @@
     sdp->origin.version = sdp->origin.id = tv.sec + 2208988800UL;
     sdp->origin.net_type = STR_IN;
-    sdp->origin.addr_type = STR_IP4;
-    pj_strdup2(pool, &sdp->origin.addr, 
-	       pj_inet_ntoa(sock_info[0].rtp_addr_name.sin_addr));
+
+    if (addr0->addr.sa_family == pj_AF_INET()) {
+	sdp->origin.addr_type = STR_IP4;
+	pj_strdup2(pool, &sdp->origin.addr, 
+		   pj_inet_ntoa(addr0->ipv4.sin_addr));
+    } else if (addr0->addr.sa_family == pj_AF_INET6()) {
+	char tmp_addr[PJ_INET6_ADDRSTRLEN];
+
+	sdp->origin.addr_type = STR_IP6;
+	pj_strdup2(pool, &sdp->origin.addr, 
+		   pj_sockaddr_print(addr0, tmp_addr, sizeof(tmp_addr), 0));
+
+    } else {
+	pj_assert(!"Invalid address family");
+	return PJ_EAFNOTSUP;
+    }
+
     sdp->name = STR_SDP_NAME;
 
@@ -317,8 +335,7 @@
      */
     sdp->conn = PJ_POOL_ZALLOC_T(pool, pjmedia_sdp_conn);
-    sdp->conn->net_type = STR_IN;
-    sdp->conn->addr_type = STR_IP4;
-    pj_strdup2(pool, &sdp->conn->addr, 
-	       pj_inet_ntoa(sock_info[0].rtp_addr_name.sin_addr));
+    sdp->conn->net_type = sdp->origin.net_type;
+    sdp->conn->addr_type = sdp->origin.addr_type;
+    sdp->conn->addr = sdp->origin.addr;
 
 
@@ -335,5 +352,5 @@
     /* Standard media info: */
     pj_strdup(pool, &m->desc.media, &STR_AUDIO);
-    m->desc.port = pj_ntohs(sock_info[0].rtp_addr_name.sin_port);
+    m->desc.port = pj_sockaddr_get_port(addr0);
     m->desc.port_count = 1;
     pj_strdup (pool, &m->desc.transport, &STR_RTP_AVP);
@@ -345,13 +362,29 @@
     /* Add "rtcp" attribute */
 #if defined(PJMEDIA_HAS_RTCP_IN_SDP) && PJMEDIA_HAS_RTCP_IN_SDP!=0
-    if (sock_info->rtcp_addr_name.sin_family != 0) {
+    if (sock_info->rtcp_addr_name.addr.sa_family != 0) {
+	const pj_sockaddr *rtcp_addr = &sock_info->rtcp_addr_name;
+
 	attr = PJ_POOL_ALLOC_T(pool, pjmedia_sdp_attr);
 	attr->name = pj_str("rtcp");
 	attr->value.ptr = (char*) pj_pool_alloc(pool, 80);
-	attr->value.slen = 
-	    pj_ansi_snprintf(attr->value.ptr, 80,
-			    "%u IN IP4 %s",
-			    pj_ntohs(sock_info[0].rtcp_addr_name.sin_port),
-			    pj_inet_ntoa(sock_info[0].rtcp_addr_name.sin_addr));
+	if (rtcp_addr->addr.sa_family == pj_AF_INET()) {
+	    attr->value.slen = 
+		pj_ansi_snprintf(attr->value.ptr, 80,
+				"%u IN IP4 %s",
+				pj_ntohs(rtcp_addr->ipv4.sin_port),
+				pj_inet_ntoa(rtcp_addr->ipv4.sin_addr));
+	} else if (rtcp_addr->addr.sa_family == pj_AF_INET6()) {
+	    char tmp_addr[PJ_INET6_ADDRSTRLEN];
+	    attr->value.slen = 
+		pj_ansi_snprintf(attr->value.ptr, 80,
+				"%u IN IP6 %s",
+				pj_sockaddr_get_port(rtcp_addr),
+				pj_sockaddr_print(rtcp_addr, tmp_addr, 
+						  sizeof(tmp_addr), 0));
+
+	} else {
+	    pj_assert(!"Unsupported address family");
+	    return PJ_EAFNOTSUP;
+	}
 	pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);
     }
Index: pjproject/trunk/pjmedia/src/pjmedia/session.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/session.c	(revision 1614)
+++ pjproject/trunk/pjmedia/src/pjmedia/session.c	(revision 1615)
@@ -53,6 +53,7 @@
 static const pj_str_t ID_IN = { "IN", 2 };
 static const pj_str_t ID_IP4 = { "IP4", 3};
-static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };
-static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 };
+static const pj_str_t ID_IP6 = { "IP6", 3};
+/*static const pj_str_t ID_RTP_AVP = { "RTP/AVP", 7 };*/
+/*static const pj_str_t ID_SDP_NAME = { "pjmedia", 7 };*/
 static const pj_str_t ID_RTPMAP = { "rtpmap", 6 };
 static const pj_str_t ID_TELEPHONE_EVENT = { "telephone-event", 15 };
@@ -130,4 +131,6 @@
     const pjmedia_sdp_conn *local_conn;
     const pjmedia_sdp_conn *rem_conn;
+    int rem_af, local_af;
+    pj_sockaddr local_addr;
     pjmedia_sdp_rtpmap *rtpmap;
     int local_fmtp_mode = 0, rem_fmtp_mode = 0;
@@ -186,9 +189,59 @@
     }
 
+    /* Check address family in remote SDP */
+    rem_af = pj_AF_UNSPEC();
+    if (pj_stricmp(&rem_conn->net_type, &ID_IN)==0) {
+	if (pj_stricmp(&rem_conn->addr_type, &ID_IP4)==0) {
+	    rem_af = pj_AF_INET();
+	} else if (pj_stricmp(&rem_conn->addr_type, &ID_IP6)==0) {
+	    rem_af = pj_AF_UNSPEC();
+	}
+    }
+
+    if (rem_af==pj_AF_UNSPEC()) {
+	/* Unsupported address family */
+	return PJ_EAFNOTSUP;
+    }
+
+    /* Set remote address: */
+    status = pj_sockaddr_init(rem_af, &si->rem_addr, &rem_conn->addr, 
+			      rem_m->desc.port);
+    if (status != PJ_SUCCESS) {
+	/* Invalid IP address. */
+	return PJMEDIA_EINVALIDIP;
+    }
+
+    /* Check address family of local info */
+    local_af = pj_AF_UNSPEC();
+    if (pj_stricmp(&local_conn->net_type, &ID_IN)==0) {
+	if (pj_stricmp(&local_conn->addr_type, &ID_IP4)==0) {
+	    local_af = pj_AF_INET();
+	} else if (pj_stricmp(&local_conn->addr_type, &ID_IP6)==0) {
+	    local_af = pj_AF_UNSPEC();
+	}
+    }
+
+    if (local_af==pj_AF_UNSPEC()) {
+	/* Unsupported address family */
+	return PJ_EAFNOTSUP;
+    }
+
+    /* Set remote address: */
+    status = pj_sockaddr_init(local_af, &local_addr, &local_conn->addr, 
+			      local_m->desc.port);
+    if (status != PJ_SUCCESS) {
+	/* Invalid IP address. */
+	return PJMEDIA_EINVALIDIP;
+    }
+
+    /* Local and remote address family must match */
+    if (local_af != rem_af)
+	return PJ_EAFNOTSUP;
+
     /* Media direction: */
 
     if (local_m->desc.port == 0 || 
-	pj_inet_addr(&local_conn->addr).s_addr==0 ||
-	pj_inet_addr(&rem_conn->addr).s_addr==0 ||
+	pj_sockaddr_has_addr(&local_addr)==PJ_FALSE ||
+	pj_sockaddr_has_addr(&si->rem_addr)==PJ_FALSE ||
 	pjmedia_sdp_media_find_attr(local_m, &STR_INACTIVE, NULL)!=NULL)
     {
@@ -215,13 +268,4 @@
 	si->dir = PJMEDIA_DIR_ENCODING_DECODING;
 
-    }
-
-
-    /* Set remote address: */
-    status = pj_sockaddr_in_init(&si->rem_addr, &rem_conn->addr, 
-				 rem_m->desc.port);
-    if (status != PJ_SUCCESS) {
-	/* Invalid IP address. */
-	return PJMEDIA_EINVALIDIP;
     }
 
@@ -236,20 +280,22 @@
 	if (status == PJ_SUCCESS) {
 	    if (rtcp.addr.slen) {
-		status = pj_sockaddr_in_init(&si->rem_rtcp, &rtcp.addr,
-					     (pj_uint16_t)rtcp.port);
+		status = pj_sockaddr_init(rem_af, &si->rem_rtcp, &rtcp.addr,
+					  (pj_uint16_t)rtcp.port);
 	    } else {
-		pj_sockaddr_in_init(&si->rem_rtcp, NULL, 
-				    (pj_uint16_t)rtcp.port);
-		si->rem_rtcp.sin_addr.s_addr = si->rem_addr.sin_addr.s_addr;
+		pj_sockaddr_init(rem_af, &si->rem_rtcp, NULL, 
+				 (pj_uint16_t)rtcp.port);
+		pj_memcpy(pj_sockaddr_get_addr(&si->rem_rtcp),
+		          pj_sockaddr_get_addr(&si->rem_addr),
+			  pj_sockaddr_get_addr_len(&si->rem_addr));
 	    }
 	}
     }
     
-    if (si->rem_rtcp.sin_addr.s_addr == 0) {
+    if (!pj_sockaddr_has_addr(&si->rem_rtcp) == 0) {
 	int rtcp_port;
 
-	pj_memcpy(&si->rem_rtcp, &si->rem_addr, sizeof(pj_sockaddr_in));
-	rtcp_port = pj_ntohs(si->rem_addr.sin_port) + 1;
-	si->rem_rtcp.sin_port = pj_htons((pj_uint16_t)rtcp_port);
+	pj_memcpy(&si->rem_rtcp, &si->rem_addr, sizeof(pj_sockaddr));
+	rtcp_port = pj_sockaddr_get_port(&si->rem_addr) + 1;
+	pj_sockaddr_set_port(&si->rem_rtcp, (pj_uint16_t)rtcp_port);
     }
 
Index: pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c	(revision 1614)
+++ pjproject/trunk/pjmedia/src/pjmedia/transport_udp.c	(revision 1615)
@@ -52,6 +52,7 @@
     void	       *user_data;	/**< Only valid when attached	    */
     pj_bool_t		attached;	/**< Has attachment?		    */
-    pj_sockaddr_in	rem_rtp_addr;	/**< Remote RTP address		    */
-    pj_sockaddr_in	rem_rtcp_addr;	/**< Remote RTCP address	    */
+    pj_sockaddr		rem_rtp_addr;	/**< Remote RTP address		    */
+    pj_sockaddr		rem_rtcp_addr;	/**< Remote RTCP address	    */
+    int			addr_len;	/**< Length of addresses.	    */
     void  (*rtp_cb)(	void*,		/**< To report incoming RTP.	    */
 			const void*,
@@ -65,10 +66,10 @@
 
     pj_sock_t	        rtp_sock;	/**< RTP socket			    */
-    pj_sockaddr_in	rtp_addr_name;	/**< Published RTP address.	    */
+    pj_sockaddr		rtp_addr_name;	/**< Published RTP address.	    */
     pj_ioqueue_key_t   *rtp_key;	/**< RTP socket key in ioqueue	    */
     pj_ioqueue_op_key_t	rtp_read_op;	/**< Pending read operation	    */
     unsigned		rtp_write_op_id;/**< Next write_op to use	    */
     pending_write	rtp_pending_write[MAX_PENDING];  /**< Pending write */
-    pj_sockaddr_in	rtp_src_addr;	/**< Actual packet src addr.	    */
+    pj_sockaddr		rtp_src_addr;	/**< Actual packet src addr.	    */
     unsigned		rtp_src_cnt;	/**< How many pkt from this addr.   */
     int			rtp_addrlen;	/**< Address length.		    */
@@ -76,6 +77,6 @@
 
     pj_sock_t		rtcp_sock;	/**< RTCP socket		    */
-    pj_sockaddr_in	rtcp_addr_name;	/**< Published RTCP address.	    */
-    pj_sockaddr_in	rtcp_src_addr;	/**< Actual source RTCP address.    */
+    pj_sockaddr		rtcp_addr_name;	/**< Published RTCP address.	    */
+    pj_sockaddr		rtcp_src_addr;	/**< Actual source RTCP address.    */
     int			rtcp_addr_len;	/**< Length of RTCP src address.    */
     pj_ioqueue_key_t   *rtcp_key;	/**< RTCP socket key in ioqueue	    */
@@ -151,4 +152,19 @@
 						  pjmedia_transport **p_tp)
 {
+    return pjmedia_transport_udp_create3(endpt, pj_AF_INET(), name,
+					 addr, port, options, p_tp);
+}
+
+/**
+ * Create UDP stream transport.
+ */
+PJ_DEF(pj_status_t) pjmedia_transport_udp_create3(pjmedia_endpt *endpt,
+						  int af,
+						  const char *name,
+						  const pj_str_t *addr,
+						  int port,
+						  unsigned options,
+						  pjmedia_transport **p_tp)
+{
     pjmedia_sock_info si;
     pj_status_t status;
@@ -163,10 +179,13 @@
 
     /* Create RTP socket */
-    status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &si.rtp_sock);
+    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &si.rtp_sock);
     if (status != PJ_SUCCESS)
 	goto on_error;
 
     /* Bind RTP socket */
-    pj_sockaddr_in_init(&si.rtp_addr_name, addr, (pj_uint16_t)port);
+    status = pj_sockaddr_init(af, &si.rtp_addr_name, addr, (pj_uint16_t)port);
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
     status = pj_sock_bind(si.rtp_sock, &si.rtp_addr_name, 
 			  sizeof(si.rtp_addr_name));
@@ -176,10 +195,14 @@
 
     /* Create RTCP socket */
-    status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &si.rtcp_sock);
+    status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &si.rtcp_sock);
     if (status != PJ_SUCCESS)
 	goto on_error;
 
     /* Bind RTCP socket */
-    pj_sockaddr_in_init(&si.rtcp_addr_name, addr, (pj_uint16_t)(port+1));
+    status = pj_sockaddr_init(af, &si.rtcp_addr_name, addr, 
+			      (pj_uint16_t)(port+1));
+    if (status != PJ_SUCCESS)
+	goto on_error;
+
     status = pj_sock_bind(si.rtcp_sock, &si.rtcp_addr_name,
 			  sizeof(si.rtcp_addr_name));
@@ -222,11 +245,6 @@
     PJ_ASSERT_RETURN(endpt && si && p_tp, PJ_EINVAL);
 
-    /* Check name */
-    if (!name)
-	name = "udpmedia";
-
     /* Get ioqueue instance */
     ioqueue = pjmedia_endpt_get_ioqueue(endpt);
-
 
     /* Create transport structure */
@@ -235,8 +253,11 @@
 	return PJ_ENOMEM;
 
+    if (!name)
+	name = pool->obj_name;
+
     tp = PJ_POOL_ZALLOC_T(pool, struct transport_udp);
     tp->pool = pool;
     tp->options = options;
-    pj_ansi_strcpy(tp->base.name, name);
+    pj_ansi_strncpy(tp->base.name, name, PJ_MAX_OBJ_NAME-1);
     tp->base.op = &transport_udp_op;
     tp->base.type = PJMEDIA_TRANSPORT_TYPE_UDP;
@@ -249,17 +270,21 @@
 
     /* If address is 0.0.0.0, use host's IP address */
-    if (tp->rtp_addr_name.sin_addr.s_addr == 0) {
+    if (!pj_sockaddr_has_addr(&tp->rtp_addr_name)) {
 	pj_sockaddr hostip;
 
-	status = pj_gethostip(pj_AF_INET(), &hostip);
+	status = pj_gethostip(tp->rtp_addr_name.addr.sa_family, &hostip);
 	if (status != PJ_SUCCESS)
 	    goto on_error;
 
-	tp->rtp_addr_name.sin_addr.s_addr = hostip.ipv4.sin_addr.s_addr;
+	pj_memcpy(pj_sockaddr_get_addr(&tp->rtp_addr_name), 
+		  pj_sockaddr_get_addr(&hostip),
+		  pj_sockaddr_get_addr_len(&hostip));
     }
 
     /* Same with RTCP */
-    if (tp->rtcp_addr_name.sin_addr.s_addr == 0) {
-	tp->rtcp_addr_name.sin_addr.s_addr = tp->rtp_addr_name.sin_addr.s_addr;
+    if (!pj_sockaddr_has_addr(&tp->rtcp_addr_name)) {
+	pj_memcpy(pj_sockaddr_get_addr(&tp->rtcp_addr_name),
+		  pj_sockaddr_get_addr(&tp->rtp_addr_name),
+		  pj_sockaddr_get_addr_len(&tp->rtp_addr_name));
     }
 
@@ -349,4 +374,5 @@
 	pj_ioqueue_unregister(udp->rtp_key);
 	udp->rtp_key = NULL;
+	udp->rtp_sock = PJ_INVALID_SOCKET;
     } else if (udp->rtp_sock != PJ_INVALID_SOCKET) {
 	pj_sock_close(udp->rtp_sock);
@@ -357,4 +383,5 @@
 	pj_ioqueue_unregister(udp->rtcp_key);
 	udp->rtcp_key = NULL;
+	udp->rtcp_sock = PJ_INVALID_SOCKET;
     } else if (udp->rtcp_sock != PJ_INVALID_SOCKET) {
 	pj_sock_close(udp->rtcp_sock);
@@ -409,15 +436,15 @@
 	    (udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0) 
 	{
-	    if ((udp->rem_rtp_addr.sin_addr.s_addr != 
-		 udp->rtp_src_addr.sin_addr.s_addr) ||
-		(udp->rem_rtp_addr.sin_port != 
-		 udp->rtp_src_addr.sin_port))
-	    {
+	    if (pj_sockaddr_cmp(&udp->rem_rtp_addr, &udp->rtp_src_addr) != 0) {
+
 		udp->rtp_src_cnt++;
 
 		if (udp->rtp_src_cnt >= PJMEDIA_RTP_NAT_PROBATION_CNT) {
 		
+		    char addr_text[80];
+
 		    /* Set remote RTP address to source address */
-		    udp->rem_rtp_addr = udp->rtp_src_addr;
+		    pj_memcpy(&udp->rem_rtp_addr, &udp->rtp_src_addr,
+			      sizeof(pj_sockaddr));
 
 		    /* Reset counter */
@@ -425,27 +452,30 @@
 
 		    PJ_LOG(4,(udp->base.name,
-			      "Remote RTP address switched to %s:%d",
-			      pj_inet_ntoa(udp->rtp_src_addr.sin_addr),
-			      pj_ntohs(udp->rtp_src_addr.sin_port)));
+			      "Remote RTP address switched to %s",
+			      pj_sockaddr_print(&udp->rtp_src_addr, addr_text,
+						sizeof(addr_text), 3)));
 
 		    /* Also update remote RTCP address if actual RTCP source
 		     * address is not heard yet.
 		     */
-		    if (udp->rtcp_src_addr.sin_addr.s_addr == 0) {
+		    if (!pj_sockaddr_has_addr(&udp->rtcp_src_addr)) {
 			pj_uint16_t port;
 
 			pj_memcpy(&udp->rem_rtcp_addr, &udp->rem_rtp_addr, 
-				  sizeof(pj_sockaddr_in));
+				  sizeof(pj_sockaddr));
+			pj_sockaddr_copy_addr(&udp->rem_rtcp_addr,
+					      &udp->rem_rtp_addr);
 			port = (pj_uint16_t)
-			       (pj_ntohs(udp->rem_rtp_addr.sin_port)+1);
-			udp->rem_rtcp_addr.sin_port = pj_htons(port);
+			       (pj_sockaddr_get_port(&udp->rem_rtp_addr)+1);
+			pj_sockaddr_set_port(&udp->rem_rtcp_addr, port);
 
 			pj_memcpy(&udp->rtcp_src_addr, &udp->rem_rtcp_addr, 
-				  sizeof(pj_sockaddr_in));
+				  sizeof(pj_sockaddr));
 
 			PJ_LOG(4,(udp->base.name,
-				  "Remote RTCP address switched to %s:%d",
-				  pj_inet_ntoa(udp->rtcp_src_addr.sin_addr),
-				  pj_ntohs(udp->rtcp_src_addr.sin_port)));
+				  "Remote RTCP address switched to %s",
+				  pj_sockaddr_print(&udp->rtcp_src_addr, 
+						    addr_text,
+						    sizeof(addr_text), 3)));
 
 		    }
@@ -456,5 +486,5 @@
 read_next_packet:
 	bytes_read = sizeof(udp->rtp_pkt);
-	udp->rtp_addrlen = sizeof(pj_sockaddr_in);
+	udp->rtp_addrlen = sizeof(udp->rtp_src_addr);
 	status = pj_ioqueue_recvfrom(udp->rtp_key, &udp->rtp_read_op,
 				     udp->rtp_pkt, &bytes_read, 0,
@@ -497,15 +527,15 @@
 	if (bytes_read>0 &&
 	    (udp->options & PJMEDIA_UDP_NO_SRC_ADDR_CHECKING)==0 &&
-	    ((udp->rem_rtcp_addr.sin_addr.s_addr != 
-	       udp->rtcp_src_addr.sin_addr.s_addr) ||
-	     (udp->rem_rtcp_addr.sin_port != 
-	       udp->rtcp_src_addr.sin_port)))
+	    pj_sockaddr_cmp(&udp->rem_rtcp_addr, &udp->rtcp_src_addr) != 0)
 	{
+	    char addr_text[80];
+
 	    pj_memcpy(&udp->rem_rtcp_addr, &udp->rtcp_src_addr,
-		      sizeof(pj_sockaddr_in));
+		      sizeof(pj_sockaddr));
+
 	    PJ_LOG(4,(udp->base.name,
-		      "Remote RTCP address switched to %s:%d",
-		      pj_inet_ntoa(udp->rtcp_src_addr.sin_addr),
-		      pj_ntohs(udp->rtcp_src_addr.sin_port)));
+		      "Remote RTCP address switched to %s",
+		      pj_sockaddr_print(&udp->rtcp_src_addr, addr_text,
+					sizeof(addr_text), 3)));
 	}
 
@@ -553,5 +583,5 @@
 {
     struct transport_udp *udp = (struct transport_udp*) tp;
-    const pj_sockaddr_in *rtcp_addr;
+    const pj_sockaddr *rtcp_addr;
 
     /* Validate arguments */
@@ -564,18 +594,18 @@
 
     /* Copy remote RTP address */
-    pj_memcpy(&udp->rem_rtp_addr, rem_addr, sizeof(pj_sockaddr_in));
+    pj_memcpy(&udp->rem_rtp_addr, rem_addr, addr_len);
 
     /* Copy remote RTP address, if one is specified. */
-    rtcp_addr = (const pj_sockaddr_in*) rem_rtcp;
-    if (rtcp_addr && rtcp_addr->sin_addr.s_addr != 0) {
-	pj_memcpy(&udp->rem_rtcp_addr, rem_rtcp, sizeof(pj_sockaddr_in));
+    rtcp_addr = (const pj_sockaddr*) rem_rtcp;
+    if (rtcp_addr && pj_sockaddr_has_addr(rtcp_addr)) {
+	pj_memcpy(&udp->rem_rtcp_addr, rem_rtcp, addr_len);
 
     } else {
-	int rtcp_port;
+	unsigned rtcp_port;
 
 	/* Otherwise guess the RTCP address from the RTP address */
-	pj_memcpy(&udp->rem_rtcp_addr, rem_addr, sizeof(pj_sockaddr_in));
-	rtcp_port = pj_ntohs(udp->rem_rtp_addr.sin_port) + 1;
-	udp->rem_rtcp_addr.sin_port = pj_htons((pj_uint16_t)rtcp_port);
+	pj_memcpy(&udp->rem_rtcp_addr, rem_addr, addr_len);
+	rtcp_port = pj_sockaddr_get_port(&udp->rem_rtp_addr) + 1;
+	pj_sockaddr_set_port(&udp->rem_rtcp_addr, (pj_uint16_t)rtcp_port);
     }
 
@@ -584,4 +614,7 @@
     udp->rtcp_cb = rtcp_cb;
     udp->user_data = user_data;
+
+    /* Save address length */
+    udp->addr_len = addr_len;
 
     /* Last, mark transport as attached */
@@ -660,5 +693,5 @@
 				pw->buffer, &sent, 0,
 				&udp->rem_rtp_addr, 
-				sizeof(pj_sockaddr_in));
+				udp->addr_len);
 
     udp->rtp_write_op_id = (udp->rtp_write_op_id + 1) %
@@ -685,5 +718,5 @@
     status = pj_ioqueue_sendto( udp->rtcp_key, &udp->rtcp_write_op,
 				pkt, &sent, 0,
-				&udp->rem_rtcp_addr, sizeof(pj_sockaddr_in));
+				&udp->rem_rtcp_addr, udp->addr_len);
 
     if (status==PJ_SUCCESS || status==PJ_EPENDING)
Index: pjproject/trunk/pjsip-apps/src/samples/siprtp.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/siprtp.c	(revision 1614)
+++ pjproject/trunk/pjsip-apps/src/samples/siprtp.c	(revision 1615)
@@ -1028,5 +1028,5 @@
     /* Standard media info: */
     m->desc.media = pj_str("audio");
-    m->desc.port = pj_ntohs(tpinfo.skinfo.rtp_addr_name.sin_port);
+    m->desc.port = pj_ntohs(tpinfo.skinfo.rtp_addr_name.ipv4.sin_port);
     m->desc.port_count = 1;
     m->desc.transport = pj_str("RTP/AVP");
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 1614)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 1615)
@@ -1825,6 +1825,6 @@
     for (i=0; i<info.stream_cnt; ++i) {
 	pjmedia_rtcp_stat stat;
+	char rem_addr_buf[80];
 	const char *rem_addr;
-	int rem_port;
 	const char *dir;
 	char last_update[64];
@@ -1833,6 +1833,6 @@
 
 	pjmedia_session_get_stream_stat(session, i, &stat);
-	rem_addr = pj_inet_ntoa(info.stream_info[i].rem_addr.sin_addr);
-	rem_port = pj_ntohs(info.stream_info[i].rem_addr.sin_port);
+	rem_addr = pj_sockaddr_print(&info.stream_info[i].rem_addr,
+				     rem_addr_buf, sizeof(rem_addr_buf), 3);
 
 	if (info.stream_info[i].dir == PJMEDIA_DIR_ENCODING)
@@ -1847,5 +1847,5 @@
 	
 	len = pj_ansi_snprintf(buf, end-p, 
-		  "%s  #%d %.*s @%dKHz, %s, peer=%s:%d",
+		  "%s  #%d %.*s @%dKHz, %s, peer=%s",
 		  indent, i,
 		  (int)info.stream_info[i].fmt.encoding_name.slen,
@@ -1853,5 +1853,5 @@
 		  info.stream_info[i].fmt.clock_rate / 1000,
 		  dir,
-		  rem_addr, rem_port);
+		  rem_addr);
 	if (len < 1 || len > end-p) {
 	    *p = '\0';
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 1614)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 1615)
@@ -2015,4 +2015,5 @@
 	pjsua_call *call = &pjsua_var.calls[i];
 	pjmedia_sock_info skinfo;
+	char addr_buf[80];
 
 	/* MSVC complains about skinfo not being initialized */
@@ -2021,8 +2022,8 @@
 	pjmedia_transport_get_info(call->med_tp, &skinfo);
 
-	PJ_LOG(3,(THIS_FILE, " %s: %s:%d",
+	PJ_LOG(3,(THIS_FILE, " %s: %s",
 		  (pjsua_var.media_cfg.enable_ice ? "ICE" : "UDP"),
-		  pj_inet_ntoa(skinfo.rtp_addr_name.sin_addr),
-		  (int)pj_ntohs(skinfo.rtp_addr_name.sin_port)));
+		  pj_sockaddr_print(&skinfo.rtp_addr_name, addr_buf,
+				    sizeof(addr_buf), 3)));
     }
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 1614)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 1615)
@@ -221,4 +221,5 @@
     pj_sockaddr_in mapped_addr[2];
     pj_status_t status = PJ_SUCCESS;
+    char addr_buf[80];
     pj_sock_t sock[2];
 
@@ -229,5 +230,4 @@
 	return status;
     }
-
 
     if (next_rtp_port == 0)
@@ -379,9 +379,9 @@
 
     PJ_LOG(4,(THIS_FILE, "RTP socket reachable at %s:%d",
-	      pj_inet_ntoa(skinfo->rtp_addr_name.sin_addr), 
-	      pj_ntohs(skinfo->rtp_addr_name.sin_port)));
+	      pj_sockaddr_print(&skinfo->rtp_addr_name, addr_buf,
+				sizeof(addr_buf), 3)));
     PJ_LOG(4,(THIS_FILE, "RTCP socket reachable at %s:%d",
-	      pj_inet_ntoa(skinfo->rtcp_addr_name.sin_addr), 
-	      pj_ntohs(skinfo->rtcp_addr_name.sin_port)));
+	      pj_sockaddr_print(&skinfo->rtcp_addr_name, addr_buf,
+				sizeof(addr_buf), 3)));
 
     next_rtp_port += 2;
