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 <[email protected]> Authored: Mon Sep 22 12:43:56 2014 -0500 Committer: Alan M. Carroll <[email protected]> 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(
