You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2014/09/22 19:44:20 UTC

git commit: TS-3093: More funcationlity for IpAddr.

Repository: trafficserver
Updated Branches:
  refs/heads/master 05cfba6a7 -> 2f6d6e0d0


TS-3093: More funcationlity for IpAddr.


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/2f6d6e0d
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/2f6d6e0d
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/2f6d6e0d

Branch: refs/heads/master
Commit: 2f6d6e0d0e1dc4104912ec5f051922f0df2414d0
Parents: 05cfba6
Author: Alan M. Carroll <am...@network-geographics.com>
Authored: Mon Sep 22 12:43:56 2014 -0500
Committer: Alan M. Carroll <am...@network-geographics.com>
Committed: Mon Sep 22 12:43:56 2014 -0500

----------------------------------------------------------------------
 lib/ts/ink_inet.cc | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/ts/ink_inet.h  | 58 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2f6d6e0d/lib/ts/ink_inet.cc
----------------------------------------------------------------------
diff --git a/lib/ts/ink_inet.cc b/lib/ts/ink_inet.cc
index da01ddb..b20633b 100644
--- a/lib/ts/ink_inet.cc
+++ b/lib/ts/ink_inet.cc
@@ -338,6 +338,15 @@ IpAddr::load(char const* text) {
   return zret;
 }
 
+int 
+IpAddr::load(ts::ConstBuffer const& text) 
+{
+  IpEndpoint ip;
+  int zret = ats_ip_pton(text, &ip.sa);
+  this->assign(&ip.sa);
+  return zret;
+}
+
 char*
 IpAddr::toString(char* dest, size_t len) const {
   IpEndpoint ip;
@@ -368,6 +377,61 @@ operator == (IpAddr const& lhs, sockaddr const* rhs) {
   return zret;
 }
 
+/** Compare two IP addresses.
+    This is useful for IPv4, IPv6, and the unspecified address type.
+    If the addresses are of different types they are ordered
+
+    Non-IP < IPv4 < IPv6
+
+     - all non-IP addresses are the same ( including @c AF_UNSPEC )
+     - IPv4 addresses are compared numerically (host order)
+     - IPv6 addresses are compared byte wise in network order (MSB to LSB)
+
+    @return
+      - -1 if @a lhs is less than @a rhs.
+      - 0 if @a lhs is identical to @a rhs.
+      - 1 if @a lhs is greater than @a rhs.
+
+    @internal This looks like a lot of code for an inline but I think it
+    should compile down to something reasonable.
+*/
+inline int
+IpAddr::cmp(self const& that) const {
+  int zret = 0;
+  uint16_t rtype = that._family;
+  uint16_t ltype = _family;
+
+  // We lump all non-IP addresses into a single equivalence class
+  // that is less than an IP address. This includes AF_UNSPEC.
+  if (AF_INET == ltype) {
+    if (AF_INET == rtype) {
+      in_addr_t la = ntohl(_addr._ip4);
+      in_addr_t ra = ntohl(that._addr._ip4);
+      if (la < ra) zret = -1;
+      else if (la > ra) zret = 1;
+      else zret = 0;
+    } else if (AF_INET6 == rtype) { // IPv4 < IPv6
+      zret = -1;
+    } else { // IP > not IP
+      zret = 1;
+    }
+  } else if (AF_INET6 == ltype) {
+    if (AF_INET6 == rtype) {
+      zret = memcmp(&_addr._ip6, &that._addr._ip6, TS_IP6_SIZE);
+    } else {
+      zret = 1; // IPv6 greater than any other type.
+    }
+  } else if (AF_INET == rtype || AF_INET6 == rtype) {
+    // ltype is non-IP so it's less than either IP type.
+    zret = -1;
+  } else {
+    // Both types are non-IP so they're equal.
+    zret = 0;
+  }
+
+  return zret;
+}
+
 int
 ats_ip_getbestaddrinfo(char const* host,
   IpEndpoint* ip4,

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/2f6d6e0d/lib/ts/ink_inet.h
----------------------------------------------------------------------
diff --git a/lib/ts/ink_inet.h b/lib/ts/ink_inet.h
index c5cd248..6c21e74 100644
--- a/lib/ts/ink_inet.h
+++ b/lib/ts/ink_inet.h
@@ -1103,6 +1103,16 @@ struct IpAddr {
   int load(
     char const* str ///< Nul terminated input string.
   );
+
+  /** Load from string.
+      The address is copied to this object if the conversion is successful,
+      otherwise this object is invalidated.
+      @return 0 on success, non-zero on failure.
+  */
+  int load(
+    ts::ConstBuffer const& str ///< Text of IP address.
+  );
+  
   /** Output to a string.
       @return The string @a dest.
   */
@@ -1128,6 +1138,25 @@ struct IpAddr {
     return ! (*this == that);
   }
 
+  /// Generic compare.
+  int cmp(self const& that) const;
+
+  /** Return a normalized hash value.
+      - Ipv4: the address in host order.
+      - Ipv6: folded 32 bit of the address.
+      - Else: 0.
+  */
+  uint32_t hash() const;
+
+  /** The hashing function embedded in a functor.
+      @see hash
+  */
+  struct Hasher {
+    uint32_t operator() (self const& ip) const {
+      return ip.hash();
+    }
+  };
+
   /// Test for same address family.
   /// @c return @c true if @a that is the same address family as @a this.
   bool isCompatibleWith(self const& that);
@@ -1153,6 +1182,8 @@ struct IpAddr {
     in_addr_t _ip4; ///< IPv4 address storage.
     in6_addr  _ip6; ///< IPv6 address storage.
     uint8_t   _byte[TS_IP6_SIZE]; ///< As raw bytes.
+    uint32_t  _u32[TS_IP6_SIZE/(sizeof(uint32_t)/sizeof(uint8_t))]; ///< As 32 bit chunks.
+    uint64_t  _u64[TS_IP6_SIZE/(sizeof(uint64_t)/sizeof(uint8_t))]; ///< As 64 bit chunks.
   } _addr;
 
   ///< Pre-constructed invalid instance.
@@ -1224,6 +1255,33 @@ inline bool operator != (IpEndpoint const& lhs, IpAddr const& rhs) {
   return ! (rhs == &lhs.sa);
 }
 
+inline bool operator < (IpAddr const& lhs, IpAddr const& rhs) {
+  return -1 == lhs.cmp(rhs);
+}
+
+inline bool operator >= (IpAddr const& lhs, IpAddr const& rhs) {
+  return lhs.cmp(rhs) >= 0;
+}
+
+inline bool operator > (IpAddr const& lhs, IpAddr const& rhs) {
+  return 1 == lhs.cmp(rhs);
+}
+
+inline bool operator <= (IpAddr const& lhs, IpAddr const& rhs) {
+  return  lhs.cmp(rhs) <= 0;
+}
+
+inline uint32_t
+IpAddr::hash() const {
+  uint32_t zret = 0;
+  if (this->isIp4()) {
+    zret = ntohl(_addr._ip4);
+  } else if (this->isIp6()) {
+    zret = _addr._u32[0] ^ _addr._u32[1] ^ _addr._u32[2] ^ _addr._u32[3];
+  }
+  return zret;
+}
+
 /// Write IP @a addr to storage @a dst.
 /// @return @s dst.
 sockaddr* ats_ip_set(