More ticket #415: Added pj_sockaddr_cmp(), pj_sockaddr_copy_addr(), and pj_sockaddr_print()

git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@1613 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h
index 4adfbd6..4f54dbf 100644
--- a/pjlib/include/pj/sock.h
+++ b/pjlib/include/pj/sock.h
@@ -595,7 +595,8 @@
 /**
  * This function converts a numeric address into a text string suitable
  * for presentation. It supports both IPv4 and IPv6 address
- * conversion.
+ * conversion. 
+ * @see pj_sockaddr_print()
  *
  * @param af	Specify the family of the address. This can be PJ_AF_INET
  *		or PJ_AF_INET6.
@@ -615,6 +616,7 @@
 
 /**
  * Converts numeric address into its text string representation.
+ * @see pj_sockaddr_print()
  *
  * @param af	Specify the family of the address. This can be PJ_AF_INET
  *		or PJ_AF_INET6.
@@ -632,6 +634,21 @@
 PJ_DECL(char*) pj_inet_ntop2(int af, const void *src,
 			     char *dst, int size);
 
+/**
+ * Print socket address.
+ *
+ * @param addr	The socket address.
+ * @param buf	Text buffer.
+ * @param size	Size of buffer.
+ * @param flags	Bitmask combination of these value:
+ *		  - 1: port number is included.
+ *		  - 2: square bracket is included for IPv6 address.
+ *
+ * @return	The address string.
+ */
+PJ_DECL(char*) pj_sockaddr_print(const pj_sockaddr_t *addr,
+				 char *buf, int size,
+				 unsigned flags);
 
 /**
  * Convert address string with numbers and dots to binary IP address.
@@ -702,6 +719,18 @@
 				      pj_uint16_t port);
 
 /**
+ * Compare two socket addresses.
+ *
+ * @param addr1	    First address.
+ * @param addr2	    Second address.
+ *
+ * @return	    Zero on equal, -1 if addr1 is less than addr2,
+ *		    and +1 if addr1 is more than addr2.
+ */
+PJ_DECL(int) pj_sockaddr_cmp(const pj_sockaddr_t *addr1,
+			     const pj_sockaddr_t *addr2);
+
+/**
  * Get pointer to the address part of a socket address.
  * 
  * @param addr	    Socket address.
@@ -742,6 +771,14 @@
  */
 PJ_DECL(unsigned) pj_sockaddr_get_len(const pj_sockaddr_t *addr);
 
+/** 
+ * Copy only the address part (sin_addr/sin6_addr) of a socket address.
+ *
+ * @param dst	    Destination socket address.
+ * @param src	    Source socket address.
+ */
+PJ_DECL(void) pj_sockaddr_copy_addr(pj_sockaddr *dst,
+				    const pj_sockaddr *src);
 /**
  * Get the IP address of an IPv4 socket address.
  * The address is returned as 32bit value in host byte order.
diff --git a/pjlib/src/pj/ip_helper_generic.c b/pjlib/src/pj/ip_helper_generic.c
index 3e1d832..7d4c6fc 100644
--- a/pjlib/src/pj/ip_helper_generic.c
+++ b/pjlib/src/pj/ip_helper_generic.c
@@ -273,9 +273,6 @@
 
     PJ_ASSERT_RETURN(p_cnt && *p_cnt > 0 && ifs, PJ_EINVAL);
 
-    PJ_UNUSED_ARG(&get_addr);
-    PJ_UNUSED_ARG(&get_os_errmsg);
-
     pj_bzero(ifs, sizeof(ifs[0]) * (*p_cnt));
 
     /* Just get one default route */
diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c
index 1c10833..5bf19d0 100644
--- a/pjlib/src/pj/sock_common.c
+++ b/pjlib/src/pj/sock_common.c
@@ -59,6 +59,48 @@
 }
 
 /*
+ * Print socket address.
+ */
+PJ_DEF(char*) pj_sockaddr_print( const pj_sockaddr_t *addr,
+				 char *buf, int size,
+				 unsigned flags)
+{
+    enum {
+	WITH_PORT = 1,
+	WITH_BRACKETS = 2
+    };
+
+    char txt[PJ_INET6_ADDRSTRLEN];
+    char port[32];
+    const pj_addr_hdr *h = (const pj_addr_hdr*)addr;
+    char *bquote, *equote;
+    pj_status_t status;
+
+    status = pj_inet_ntop(h->sa_family, pj_sockaddr_get_addr(addr),
+			  txt, sizeof(txt));
+    if (status != PJ_SUCCESS)
+	return "";
+
+    if (h->sa_family != PJ_AF_INET6 || (flags & WITH_BRACKETS)==0) {
+	bquote = ""; equote = "";
+    } else {
+	bquote = "["; equote = "]";
+    }
+
+    if (flags & WITH_PORT) {
+	pj_ansi_snprintf(port, sizeof(port), ":%d",
+			 pj_sockaddr_get_port(addr));
+    } else {
+	port[0] = '\0';
+    }
+
+    pj_ansi_snprintf(buf, size, "%s%s%s%s",
+		     bquote, txt, equote, port);
+
+    return buf;
+}
+
+/*
  * Set the IP address of an IP socket address from string address, 
  * with resolving the host if necessary. The string address may be in a
  * standard numbers and dots notation or may be a hostname. If hostname
@@ -184,6 +226,47 @@
 }
 
 /*
+ * Compare two socket addresses.
+ */
+PJ_DEF(int) pj_sockaddr_cmp( const pj_sockaddr_t *addr1,
+			     const pj_sockaddr_t *addr2)
+{
+    const pj_sockaddr *a1 = (const pj_sockaddr*) addr1;
+    const pj_sockaddr *a2 = (const pj_sockaddr*) addr2;
+    int port1, port2;
+    int result;
+
+    /* Compare address family */
+    if (a1->addr.sa_family < a2->addr.sa_family)
+	return -1;
+    else if (a1->addr.sa_family > a2->addr.sa_family)
+	return 1;
+
+    /* Compare addresses */
+    result = pj_memcmp(pj_sockaddr_get_addr(a1),
+		       pj_sockaddr_get_addr(a2),
+		       pj_sockaddr_get_addr_len(a1));
+    if (result != 0)
+	return result;
+
+    /* Compare port number */
+    port1 = pj_sockaddr_get_port(a1);
+    port2 = pj_sockaddr_get_port(a2);
+
+    if (port1 < port2)
+	return -1;
+    else if (port1 > port2)
+	return 1;
+
+    /* TODO:
+     *	Do we need to compare flow label and scope id in IPv6? 
+     */
+    
+    /* Looks equal */
+    return 0;
+}
+
+/*
  * Get first IP address associated with the hostname.
  */
 PJ_DEF(pj_in_addr) pj_gethostaddr(void)
@@ -277,6 +360,17 @@
 }
 
 /*
+ * Copy only the address part (sin_addr/sin6_addr) of a socket address.
+ */
+PJ_DEF(void) pj_sockaddr_copy_addr( pj_sockaddr *dst,
+				    const pj_sockaddr *src)
+{
+    pj_memcpy(pj_sockaddr_get_addr(dst),
+	      pj_sockaddr_get_addr(src),
+	      pj_sockaddr_get_addr_len(src));
+}
+
+/*
  * Set port number of pj_sockaddr_in
  */
 PJ_DEF(void) pj_sockaddr_in_set_port(pj_sockaddr_in *addr,