Index: pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c
===================================================================
--- pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c	(revision 1053)
+++ pjproject/trunk/pjlib-util/src/pjlib-util/stun_msg.c	(revision 1054)
@@ -90,8 +90,11 @@
 };
 
-static pj_status_t decode_ip_addr_attr(pj_pool_t *pool, 
+static pj_status_t decode_sockaddr_attr(pj_pool_t *pool, 
 				       const pj_uint8_t *buf, 
 				       void **p_attr);
-static pj_status_t encode_ip_addr_attr(const void *a, pj_uint8_t *buf, 
+static pj_status_t decode_xored_sockaddr_attr(pj_pool_t *pool, 
+					      const pj_uint8_t *buf, 
+					      void **p_attr);
+static pj_status_t encode_sockaddr_attr(const void *a, pj_uint8_t *buf, 
 				       unsigned len, 
 				       unsigned *printed);
@@ -144,12 +147,12 @@
 	/* PJ_STUN_ATTR_MAPPED_ADDR, */
 	"MAPPED-ADDRESS",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
 	/* PJ_STUN_ATTR_RESPONSE_ADDR, */
 	"RESPONSE-ADDRESS",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
@@ -162,12 +165,12 @@
 	/* PJ_STUN_ATTR_SOURCE_ADDR, */
 	"SOURCE-ADDRESS",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
 	/* PJ_STUN_ATTR_CHANGED_ADDR, */
 	"CHANGED-ADDRESS",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
@@ -204,6 +207,6 @@
 	/* PJ_STUN_ATTR_REFLECTED_FROM, */
 	"REFLECTED-FROM",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
@@ -246,6 +249,6 @@
 	/* PJ_STUN_ATTR_REMOTE_ADDRESS, */
 	"REMOTE-ADDRESS",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
@@ -270,6 +273,6 @@
 	/* PJ_STUN_ATTR_RELAY_ADDRESS, */
 	"RELAY-ADDRESS",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
@@ -330,6 +333,6 @@
 	/* PJ_STUN_ATTR_XOR_MAPPED_ADDRESS, */
 	"XOR-MAPPED-ADDRESS",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_xored_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
@@ -342,12 +345,12 @@
 	/* PJ_STUN_ATTR_REQUESTED_IP, */
 	"REQUESTED-IP",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
 	/* PJ_STUN_ATTR_XOR_REFLECTED_FROM, */
 	"XOR-REFLECTED-FROM",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_xored_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
@@ -366,6 +369,6 @@
 	/* PJ_STUN_ATTR_XOR_INTERNAL_ADDR, */
 	"XOR-INTERNAL-ADDRESS",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_xored_sockaddr_attr,
+	&encode_sockaddr_attr
     },
 
@@ -396,6 +399,6 @@
 	/* PJ_STUN_ATTR_ALTERNATE_SERVER, */
 	"ALTERNATE-SERVER",
-	&decode_ip_addr_attr,
-	&encode_ip_addr_attr
+	&decode_sockaddr_attr,
+	&encode_sockaddr_attr
     },
     {
@@ -540,12 +543,12 @@
  */
 PJ_DEF(pj_status_t) 
-pj_stun_ip_addr_attr_create(pj_pool_t *pool,
-			    int attr_type,
-			    pj_bool_t xor_ed,
-			    const pj_sockaddr_t *addr,
-			    unsigned addr_len,
-			    pj_stun_ip_addr_attr **p_attr)
-{
-    pj_stun_ip_addr_attr *attr;
+pj_stun_sockaddr_attr_create(pj_pool_t *pool,
+			     int attr_type,
+			     pj_bool_t xor_ed,
+			     const pj_sockaddr_t *addr,
+			     unsigned addr_len,
+			     pj_stun_sockaddr_attr **p_attr)
+{
+    pj_stun_sockaddr_attr *attr;
 
     PJ_ASSERT_RETURN(pool && addr_len && addr && p_attr, PJ_EINVAL);
@@ -553,21 +556,9 @@
 		     addr_len == sizeof(pj_sockaddr_in6), PJ_EINVAL);
 
-    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_ip_addr_attr);
+    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr);
     INIT_ATTR(attr, attr_type, STUN_GENERIC_IP_ADDR_LEN);
 
-    if (!xor_ed) {
-	pj_memcpy(&attr->addr, addr, addr_len);
-    } else if (addr_len == sizeof(pj_sockaddr_in)) {
-	const pj_sockaddr_in *addr4 = (const pj_sockaddr_in*) addr;
-
-	pj_sockaddr_in_init(&attr->addr.ipv4, NULL, 0);
-	attr->addr.ipv4.sin_port = (pj_uint16_t)(addr4->sin_port ^ 0x2112);
-	attr->addr.ipv4.sin_addr.s_addr = (addr4->sin_addr.s_addr ^ 
-					   pj_htonl(0x2112A442));
-    } else if (addr_len == sizeof(pj_sockaddr_in6)) {
-	return PJLIB_UTIL_ESTUNIPV6NOTSUPP;
-    } else {
-	return PJLIB_UTIL_ESTUNINADDRLEN;
-    }
+    pj_memcpy(&attr->addr, addr, addr_len);
+    attr->xor_ed = xor_ed;
 
     *p_attr = attr;
@@ -581,15 +572,15 @@
  */
 PJ_DEF(pj_status_t) 
-pj_stun_msg_add_ip_addr_attr(pj_pool_t *pool,
-			     pj_stun_msg *msg,
-			     int attr_type, 
-			     pj_bool_t xor_ed,
-			     const pj_sockaddr_t *addr,
-			     unsigned addr_len)
-{
-    pj_stun_ip_addr_attr *attr;
+pj_stun_msg_add_sockaddr_attr(pj_pool_t *pool,
+			      pj_stun_msg *msg,
+			      int attr_type, 
+			      pj_bool_t xor_ed,
+			      const pj_sockaddr_t *addr,
+			      unsigned addr_len)
+{
+    pj_stun_sockaddr_attr *attr;
     pj_status_t status;
 
-    status = pj_stun_ip_addr_attr_create(pool, attr_type, xor_ed,
+    status = pj_stun_sockaddr_attr_create(pool, attr_type, xor_ed,
 					         addr, addr_len, &attr);
     if (status != PJ_SUCCESS)
@@ -599,13 +590,13 @@
 }
 
-static pj_status_t decode_ip_addr_attr(pj_pool_t *pool, 
-				       const pj_uint8_t *buf, 
-				       void **p_attr)
-{
-    pj_stun_ip_addr_attr *attr;
+static pj_status_t decode_sockaddr_attr(pj_pool_t *pool, 
+				        const pj_uint8_t *buf, 
+				        void **p_attr)
+{
+    pj_stun_sockaddr_attr *attr;
     pj_uint32_t val;
 
     /* Create the attribute */
-    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_ip_addr_attr);
+    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr);
     pj_memcpy(attr, buf, ATTR_HDR_LEN);
 
@@ -627,5 +618,5 @@
     /* Get port and address */
     pj_sockaddr_in_init(&attr->addr.ipv4, NULL, 0);
-    attr->addr.ipv4.sin_port = getval16(buf, ATTR_HDR_LEN + 2);
+    pj_memcpy(&attr->addr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2);
     pj_memcpy(&attr->addr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4);
 
@@ -637,6 +628,47 @@
 
 
-static pj_status_t encode_ip_addr_attr(const void *a, pj_uint8_t *buf, 
-				       unsigned len, unsigned *printed)
+static pj_status_t decode_xored_sockaddr_attr(pj_pool_t *pool, 
+					      const pj_uint8_t *buf, 
+					      void **p_attr)
+{
+    pj_stun_sockaddr_attr *attr;
+    pj_uint32_t val;
+
+    /* Create the attribute */
+    attr = PJ_POOL_ZALLOC_T(pool, pj_stun_sockaddr_attr);
+    pj_memcpy(attr, buf, ATTR_HDR_LEN);
+
+    /* Convert to host byte order */
+    attr->hdr.type = pj_ntohs(attr->hdr.type);
+    attr->hdr.length = pj_ntohs(attr->hdr.length);
+
+    /* Check that the attribute length is valid */
+    if (attr->hdr.length != STUN_GENERIC_IP_ADDR_LEN)
+	return PJLIB_UTIL_ESTUNINATTRLEN;
+
+    /* Check address family */
+    val = *(pj_uint8_t*)(buf + ATTR_HDR_LEN + 1);
+
+    /* Check address family is valid (only supports ipv4 for now) */
+    if (val != 1)
+	return PJLIB_UTIL_ESTUNIPV6NOTSUPP;
+
+    /* Get port and address */
+    pj_sockaddr_in_init(&attr->addr.ipv4, NULL, 0);
+    pj_memcpy(&attr->addr.ipv4.sin_port, buf+ATTR_HDR_LEN+2, 2);
+    pj_memcpy(&attr->addr.ipv4.sin_addr, buf+ATTR_HDR_LEN+4, 4);
+
+    attr->addr.ipv4.sin_port ^= 0x2112;
+    attr->addr.ipv4.sin_addr.s_addr ^= pj_htonl(0x2112A442);
+
+    /* Done */
+    *p_attr = attr;
+
+    return PJ_SUCCESS;
+}
+
+
+static pj_status_t encode_sockaddr_attr(const void *a, pj_uint8_t *buf, 
+				        unsigned len, unsigned *printed)
 {
     enum {
@@ -644,7 +676,7 @@
     };
     pj_uint8_t *start_buf = buf;
-    const pj_stun_ip_addr_attr *ca = 
-	(const pj_stun_ip_addr_attr *)a;
-    pj_stun_ip_addr_attr *attr;
+    const pj_stun_sockaddr_attr *ca = 
+	(const pj_stun_sockaddr_attr *)a;
+    pj_stun_sockaddr_attr *attr;
 
     if (len < ATTR_LEN) 
@@ -653,5 +685,5 @@
     /* Copy and convert headers to network byte order */
     pj_memcpy(buf, a, ATTR_HDR_LEN);
-    attr = (pj_stun_ip_addr_attr*) buf;
+    attr = (pj_stun_sockaddr_attr*) buf;
     attr->hdr.type = pj_htons(attr->hdr.type);
     attr->hdr.length = pj_htons((pj_uint16_t)STUN_GENERIC_IP_ADDR_LEN);
@@ -665,11 +697,31 @@
     *buf++ = 1;
 
-    /* Port */
-    pj_memcpy(buf, &ca->addr.ipv4.sin_port, 2);
-    buf += 2;
-
-    /* Address */
-    pj_memcpy(buf, &ca->addr.ipv4.sin_addr, 4);
-    buf += 4;
+    if (ca->xor_ed) {
+	pj_uint32_t addr;
+	pj_uint16_t port;
+
+	addr = ca->addr.ipv4.sin_addr.s_addr;
+	port = ca->addr.ipv4.sin_port;
+
+	port ^= 0x2112;
+	addr ^= pj_htonl(0x2112A442);
+
+	/* Port */
+	pj_memcpy(buf, &port, 2);
+	buf += 2;
+
+	/* Address */
+	pj_memcpy(buf, &addr, 4);
+	buf += 4;
+
+    } else {
+	/* Port */
+	pj_memcpy(buf, &ca->addr.ipv4.sin_port, 2);
+	buf += 2;
+
+	/* Address */
+	pj_memcpy(buf, &ca->addr.ipv4.sin_addr, 4);
+	buf += 4;
+    }
 
     pj_assert(buf - start_buf == ATTR_LEN);
