From 88edcc58feab7ef1b05f6aeb6d3d562604424ddd Mon Sep 17 00:00:00 2001 From: "Alan M. Carroll" Date: Wed, 9 Feb 2022 12:43:57 -0600 Subject: [PATCH] Fix clang build issue for libswoc --- include/tscpp/util/Makefile.am | 1 + lib/swoc/include/swoc/swoc_ip.h | 369 +++++++++++++++++---------- lib/swoc/include/swoc/swoc_version.h | 4 +- lib/swoc/src/swoc_ip.cc | 127 +++------ 4 files changed, 270 insertions(+), 231 deletions(-) diff --git a/include/tscpp/util/Makefile.am b/include/tscpp/util/Makefile.am index 6d073e61124..a60c6c1058f 100644 --- a/include/tscpp/util/Makefile.am +++ b/include/tscpp/util/Makefile.am @@ -22,5 +22,6 @@ library_include_HEADERS = \ IntrusiveDList.h \ LocalBuffer.h \ PostScript.h \ + string_view_util.h \ TextView.h \ TsSharedMutex.h diff --git a/lib/swoc/include/swoc/swoc_ip.h b/lib/swoc/include/swoc/swoc_ip.h index 572594f07db..ab45b13da0a 100644 --- a/lib/swoc/include/swoc/swoc_ip.h +++ b/lib/swoc/include/swoc/swoc_ip.h @@ -6,7 +6,7 @@ */ #pragma once -#include +#include #include #include #include @@ -39,7 +39,10 @@ class IP6Net; class IPNet; using ::std::string_view; -extern void *const pseudo_nullptr; + +namespace detail { + extern void *const pseudo_nullptr; +} /** A union to hold @c sockaddr compliant IP address structures. @@ -59,18 +62,21 @@ union IPEndpoint { /// Default construct invalid instance. IPEndpoint(); - - IPEndpoint(self_type const &that); + IPEndpoint(self_type const &that); ///< Copy constructor. + ~IPEndpoint() = default; /// Construct from the @a text representation of an address. IPEndpoint(string_view const &text); - // Construct from @a IPAddr + // Construct from @c IPAddr explicit IPEndpoint(IPAddr const &addr); // Construct from @c sockaddr IPEndpoint(sockaddr const *sa); + /// Copy assignment. + self_type &operator=(self_type const &that); + /** Break a string in to IP address relevant tokens. * * @param src Source text. [in] @@ -81,6 +87,8 @@ union IPEndpoint { * * Any of the out parameters can be @c nullptr in which case they are not updated. * This parses and discards the IPv6 brackets. + * + * @note This is intended for internal use to do address parsing, but it can be useful in other contexts. */ static bool tokenize(string_view src, string_view *host = nullptr, string_view *port = nullptr, string_view *rest = nullptr); @@ -99,9 +107,6 @@ union IPEndpoint { /// Invalidate this endpoint. self_type &invalidate(); - /// Copy constructor. - self_type &operator=(self_type const &that); - /** Copy (assign) the contents of @a src to @a dst. * * The caller must ensure @a dst is large enough to hold the contents of @a src, the size of which @@ -122,7 +127,7 @@ union IPEndpoint { self_type &assign(IPAddr const &addr, in_port_t port = 0); /// Copy to @a sa. - const self_type &fill(sockaddr *addr) const; + const self_type ©_to(sockaddr *addr) const; /// Test for valid IP address. bool is_valid() const; @@ -246,7 +251,7 @@ class IP4Addr { self_type &operator|=(IPMask const &mask); /// Write this adddress and @a port to the sockaddr @a sa. - sockaddr_in *fill(sockaddr_in *sa, in_port_t port = 0) const; + sockaddr_in *copy_to(sockaddr_in *sa, in_port_t port = 0) const; /// @return The address in network order. in_addr_t network_order() const; @@ -263,33 +268,21 @@ class IP4Addr { bool load(string_view const &text); /// Standard ternary compare. - int - cmp(self_type const &that) const { - return _addr < that._addr ? -1 : _addr > that._addr ? 1 : 0; - } + int cmp(self_type const &that) const; /// Get the IP address family. /// @return @c AF_INET /// @note Useful primarily for template classes. constexpr sa_family_t family(); - /// Test for ANY address. - bool - is_any() const { - return _addr == INADDR_ANY; - } + /// @return @c true if this is the "any" address, @c false if not. + bool is_any() const; - /// Test for multicast - bool - is_multicast() const { - return IN_MULTICAST(_addr); - } + /// @return @c true if this is a multicast address, @c false if not. + bool is_multicast() const; - /// Test for loopback - bool - is_loopback() const { - return (*this)[3] == IN_LOOPBACKNET; - } + /// @return @c true if this is a loopback address, @c false if not. + bool is_loopback() const; /** Left shift. * @@ -349,7 +342,9 @@ class IP4Addr { }; /** Storage for an IPv6 address. - This should be presumed to be in network order. + Internal storage is not necessarily network ordered. + @see network_order + @see copy_to */ class IP6Addr { using self_type = IP6Addr; ///< Self reference type. @@ -358,23 +353,23 @@ class IP6Addr { friend class IPMask; public: - static constexpr size_t WIDTH = 128; ///< Number of bits in the address. - static constexpr size_t SIZE = WIDTH / std::numeric_limits::digits; ///< Size of address in bytes. - static constexpr sa_family_t AF_value = AF_INET6; ///< Address family type. + static constexpr size_t WIDTH = 128; ///< Number of bits in the address. + static constexpr size_t SIZE = WIDTH / std::numeric_limits::digits; ///< Size of address in bytes. + static constexpr sa_family_t AF_value = AF_INET6; ///< Address family type. using quad_type = uint16_t; ///< Size of one segment of an IPv6 address. static constexpr size_t N_QUADS = SIZE / sizeof(quad_type); ///< # of quads in an IPv6 address. /// Direct access type for the address. /// Equivalent to the data type for data member @c s6_addr in @c in6_addr. - using raw_type = std::array; + using raw_type = std::array; /// Direct access type for the address by quads (16 bits). /// This corresponds to the elements of the text format of the address. using quad_store_type = std::array; /// Number of bits per quad. - static constexpr size_t QUAD_WIDTH = std::numeric_limits::digits * sizeof(quad_type); + static constexpr size_t QUAD_WIDTH = std::numeric_limits::digits * sizeof(quad_type); /// A bit mask of all 1 bits the size of a quad. static constexpr quad_type QUAD_MASK = ~quad_type{0}; @@ -385,10 +380,10 @@ class IP6Addr { static constexpr size_t WORD_SIZE = sizeof(word_type); /// Number of bits per word. - static constexpr size_t WORD_WIDTH = std::numeric_limits::digits * WORD_SIZE; + static constexpr size_t WORD_WIDTH = std::numeric_limits::digits * WORD_SIZE; /// Number of words used for basic address storage. - static constexpr size_t N_STORE = SIZE / sizeof(word_type); + static constexpr size_t N_STORE = SIZE / WORD_SIZE; /// Type used to store the address. using word_store_type = std::array; @@ -452,8 +447,10 @@ class IP6Addr { /// Decrement address. self_type &operator--(); + self_type & operator = (self_type const& that) = default; + /// Assign from IPv6 raw address. - self_type &operator=(in6_addr const &ip); + self_type &operator=(in6_addr const &addr); /// Set to the address in @a addr. self_type &operator=(sockaddr_in6 const *addr); @@ -476,44 +473,60 @@ class IP6Addr { */ bool load(string_view const &str); - /// Generic compare. + /// Generic three value compare. int cmp(self_type const &that) const; - /// Get the address family. /// @return The address family. - /// @note Useful primarily for templates. constexpr sa_family_t family(); - /// Test for ANY address. - bool - is_any() const { - return _addr._store[0] == 0 && _addr._store[1] == 0; - } + /// @return @c true if this is the "any" address, @c false if not. + bool is_any() const; - /// Test for loopback - bool - is_loopback() const { - return _addr._store[0] == 0 && _addr._store[1] == 1; - } + /// @return @c true if this is a loopback address, @c false if not. + bool is_loopback() const; - /// Test for multicast - bool - is_multicast() const { - return _addr._raw[7] == 0xFF; - } + /// @return @c true if this is a multicast address, @c false if not. + bool is_multicast() const; - self_type & - clear() { - _addr._store[0] = _addr._store[1] = 0; - return *this; - } + /// @return @c true if this is an IPv4 addressed mapped to IPv6, @c false if not. + bool is_mapped_ipv4() const; + /** Reset to default constructed state. + * + * @return @a this + */ + self_type & clear(); + + /** Bitwise AND. + * + * @param that Source address. + * @return @a this. + * + * The bits in @a this are set to the bitwise AND of the corresponding bits in @a this and @a that. + */ self_type &operator&=(IPMask const &mask); + /** Bitwise OR. + * + * @param that Source address. + * @return @a this. + * + * The bits in @a this are set to the bitwise OR of the corresponding bits in @a this and @a that. + */ self_type &operator|=(IPMask const &mask); + /** Convert between network and host ordering. + * + * @param dst Destination for re-ordered address. + * @param src Original address. + */ static void reorder(in6_addr &dst, raw_type const &src); + /** Convert between network and host ordering. + * + * @param dst Destination for re-ordered address. + * @param src Original address. + */ static void reorder(raw_type &dst, in6_addr const &src); protected: @@ -542,6 +555,10 @@ class IP6Addr { /// This converts from the position in the text format to the quads in the binary format. static constexpr std::array QUAD_IDX = {3, 2, 1, 0, 7, 6, 5, 4}; + /// Convert between network and host order. + /// The conversion is symmetric. + /// @param dst Output where reordered value is placed. + /// @param src Input value to resorder. static void reorder(unsigned char dst[WORD_SIZE], unsigned char const src[WORD_SIZE]); /** Construct from two 64 bit values. @@ -556,7 +573,9 @@ class IP6Addr { friend IP6Addr operator|(IP6Addr const &addr, IPMask const &mask); }; -/** Storage for an IP address. +/** An IPv4 or IPv6 address. + * + * The family type is stored. For comparisons, invalid < IPv4 < IPv6. All invalid instances are equal. */ class IPAddr { friend class IPRange; @@ -565,6 +584,7 @@ class IPAddr { public: IPAddr() = default; ///< Default constructor - invalid result. IPAddr(self_type const &that) = default; ///< Copy constructor. + self_type & operator = (self_type const& that) = default; ///< Copy assignment. /// Construct using IPv4 @a addr. explicit IPAddr(in_addr_t addr); @@ -597,10 +617,10 @@ class IPAddr { /// Set to the address in @a addr. self_type &assign(sockaddr_in6 const *addr); - /// Set to the address in @a addr. + /// Set to IPv4 @a addr. self_type &assign(in_addr_t addr); - /// Set to address in @a addr. + /// Set to IPv6 @a addr self_type &assign(in6_addr const &addr); /// Assign from end point. @@ -610,7 +630,7 @@ class IPAddr { self_type &operator=(in_addr_t ip); /// Assign from IPv6 raw address. - self_type &operator=(in6_addr const &ip); + self_type &operator=(in6_addr const &addr); bool operator==(self_type const &that) const; @@ -696,8 +716,6 @@ class IPAddr { union raw_addr_type { IP4Addr _ip4; ///< IPv4 address (host) IP6Addr _ip6; ///< IPv6 address (host) - uint8_t _octet[IP6Addr::SIZE]; ///< IPv4 octets. - uint64_t _u64[IP6Addr::SIZE / sizeof(uint64_t)]; ///< As 64 bit chunks. constexpr raw_addr_type(); @@ -726,9 +744,15 @@ class IPMask { public: using raw_type = uint8_t; ///< Storage for mask width. - IPMask() = default; + IPMask() = default; ///< Default construct to invalid mask. - explicit IPMask(raw_type count); + /** Construct a mask of @a width. + * + * @param width Number of bits in the mask. + * + * @note Because this is a network mask, it is always left justified. + */ + explicit IPMask(raw_type width); /// @return @c true if the mask is valid, @c false if not. bool is_valid() const; @@ -742,7 +766,7 @@ class IPMask { /** Copmute a mask for the network at @a addr. * @param addr Lower bound of network. - * @return The width of the largest network starting at @a addr. + * @return A mask with the width of the largest network starting at @a addr. */ static self_type mask_for(IPAddr const &addr); @@ -758,27 +782,29 @@ class IPMask { */ static self_type mask_for(IP6Addr const &addr); - /// Force @a this to an invalid state. - self_type & - clear() { - _cidr = INVALID; - return *this; - } + /// Change to default constructed state (invalid). + self_type & clear(); /// The width of the mask. raw_type width() const; - self_type & - operator<<=(raw_type n) { - _cidr -= n; - return *this; - } + /** Extend the mask (cover more addresses). + * + * @param n Number of bits to extend. + * @return @a this + * + * Effectively shifts the mask left, bringing in 0 bits on the right. + */ + self_type & operator<<=(raw_type n); - self_type & - operator>>=(raw_type n) { - _cidr += n; - return *this; - } + /** Narrow the mask (cover fewer addresses). + * + * @param n Number of bits to narrow. + * @return @a this + * + * Effectively shift the mask right, bringing in 1 bits on the left. + */ + self_type & operator>>=(raw_type n); /** The mask as an IPv4 address. * @@ -906,7 +932,7 @@ class IP4Range::NetSource { using const_iterator = iterator; iterator begin() const; ///< First network. - iterator end() const; ///< Past last network. + static iterator end() ; ///< Past last network. /// Return @c true if there are valid networks, @c false if not. bool empty() const; @@ -947,7 +973,7 @@ class IP4Range::NetSource { void search_narrower(); - bool is_valid(IP4Addr mask); + bool is_valid(IP4Addr mask) const; }; class IP6Range : public DiscreteRange { @@ -1043,7 +1069,7 @@ class IP6Range::NetSource { iterator begin() const; ///< First network. iterator end() const; ///< Past last network. - /// Return @c true if there are valid networks, @c false if not. + /// @return @c true if there are valid networks, @c false if not. bool empty() const; /// @return The current network. @@ -1052,19 +1078,12 @@ class IP6Range::NetSource { /// Access @a this as if it were an @c IP6Net. self_type *operator->(); - /// Iterator support. /// @return The current network address. - IP6Addr const & - addr() const { - return _range.min(); - } + IP6Addr const & addr() const; /// Iterator support. /// @return The current network mask. - IPMask - mask() const { - return _mask; - } + IPMask mask() const; /// Move to next network. self_type &operator++(); @@ -1114,18 +1133,7 @@ class IPRange { /// Equality bool - operator==(self_type const &that) const { - if (_family != that._family) { - return false; - } - if (this->is_ip4()) { - return _range._ip4 == that._range._ip4; - } - if (this->is_ip6()) { - return _range._ip6 == that._range._ip6; - } - return true; - } + operator==(self_type const &that) const; /// @return @c true if this is an IPv4 range, @c false if not. bool @@ -1583,18 +1591,11 @@ template class IPSpace { template self_type &blend(IPRange const &range, U const &color, F &&blender); template - self_type & - blend(IP4Range const &range, U const &color, F &&blender) { - _ip4.blend(range, color, blender); - return *this; - } + self_type & blend(IP4Range const &range, U const &color, F &&blender); template self_type & - blend(IP6Range const &range, U const &color, F &&blender) { - _ip6.blend(range, color, blender); - return *this; - } + blend(IP6Range const &range, U const &color, F &&blender); /// @return The number of distinct ranges. size_t @@ -1690,7 +1691,7 @@ template class IPSpace { bool operator!=(self_type const &that) const; protected: - // These are stored non-const to make implementing @c iterator easier. This class provides the + // These are stored non-const to make implementing @c iterator easier. The containing class provides the // required @c const protection. This is basic a tuple of iterators - for forward iteration if // the primary (ipv4) iterator is at the end, then use the secondary (ipv6) iterator. The reverse // is done for reverse iteration. This depends on the extra support @c IntrusiveDList iterators @@ -1698,11 +1699,7 @@ template class IPSpace { typename IP4Space::iterator _iter_4; ///< IPv4 sub-space iterator. typename IP6Space::iterator _iter_6; ///< IPv6 sub-space iterator. /// Current value. - value_type _value{IPRange{}, *static_cast(pseudo_nullptr)}; - - /// Dummy payload. - /// @internal Used to initialize @c value_type for invalid iterators. - // static constexpr PAYLOAD * const null_payload = nullptr; + value_type _value{IPRange{}, *static_cast(detail::pseudo_nullptr)}; /** Internal constructor. * @@ -1905,7 +1902,7 @@ IPSpace::const_iterator::operator++() -> self_type & { return *this; } } - new (&_value) value_type{IPRange{}, *static_cast(pseudo_nullptr)}; + new (&_value) value_type{IPRange{}, *static_cast(detail::pseudo_nullptr)}; return *this; } @@ -1930,7 +1927,7 @@ IPSpace::const_iterator::operator--() -> self_type & { new (&_value) value_type{_iter_4->range(), _iter_4->payload()}; return *this; } - new (&_value) value_type{IPRange{}, *static_cast(pseudo_nullptr)}; + new (&_value) value_type{IPRange{}, *static_cast(detail::pseudo_nullptr)}; return *this; } @@ -2090,7 +2087,7 @@ IPAddr::isCompatibleWith(self_type const &that) { inline bool IPAddr::is_loopback() const { - return (AF_INET == _family && 0x7F == _addr._octet[0]) || (AF_INET6 == _family && _addr._ip6.is_loopback()); + return (AF_INET == _family && _addr._ip4.is_loopback()) || (AF_INET6 == _family && _addr._ip6.is_loopback()); } inline IPAddr & @@ -2233,7 +2230,7 @@ IPEndpoint::assign(sockaddr const *src) { } inline IPEndpoint const & -IPEndpoint::fill(sockaddr *addr) const { +IPEndpoint::copy_to(sockaddr *addr) const { self_type::assign(addr, &sa); return *this; } @@ -2281,8 +2278,8 @@ IPEndpoint::port(sockaddr *sa) { } inline in_port_t -IPEndpoint::port(sockaddr const *addr) { - return self_type::port(const_cast(addr)); +IPEndpoint::port(sockaddr const *sa) { + return self_type::port(const_cast(sa)); } inline in_port_t @@ -2396,12 +2393,32 @@ IP4Addr::operator|=(IPMask const &mask) { return *this; } +inline bool +IP4Addr::is_any() const { + return _addr == INADDR_ANY; +} + +inline bool +IP4Addr::is_loopback() const { + return (*this)[3] == IN_LOOPBACKNET; +} + +inline bool +IP4Addr::is_multicast() const { + return IN_MULTICAST(_addr); +} + +inline int +IP4Addr::cmp(IP4Addr::self_type const &that) const { + return _addr < that._addr ? -1 : _addr > that._addr ? 1 : 0; +} + constexpr in_addr_t IP4Addr::reorder(in_addr_t src) { return ((src & 0xFF) << 24) | (((src >> 8) & 0xFF) << 16) | (((src >> 16) & 0xFF) << 8) | ((src >> 24) & 0xFF); } -// --- +// +++ IP6Addr +++ inline IP6Addr::IP6Addr(in6_addr const &addr) { *this = addr; @@ -2415,18 +2432,52 @@ inline IP6Addr::IP6Addr(std::string_view const &text) { inline IP6Addr::IP6Addr(IPAddr const &addr) : _addr{addr._addr._ip6._addr} {} +inline bool +IP6Addr::is_loopback() const { + return _addr._store[0] == 0 && _addr._store[1] == 1; +} + +inline bool +IP6Addr::is_multicast() const { + return _addr._raw[7] == 0xFF; +} + +inline bool +IP6Addr::is_any() const { + return _addr._store[0] == 0 && _addr._store[1] == 0; +} + +inline bool +IP6Addr::is_mapped_ipv4() const { + return 0 == _addr._store[0] && (_addr._quad[7] == 0 && _addr._quad[6] == 0xFFFF); +} + inline in6_addr & IP6Addr::copy_to(in6_addr &addr) const { self_type::reorder(addr, _addr._raw); return addr; } +inline sockaddr * +IP6Addr::copy_to(sockaddr *sa, in_port_t port) const { + IPEndpoint addr(sa); + self_type::reorder(addr.sa6.sin6_addr, _addr._raw); + addr.network_order_port() = port; + return sa; +} + inline in6_addr IP6Addr::network_order() const { in6_addr zret; return this->copy_to(zret); } +inline auto +IP6Addr::clear() -> self_type & { + _addr._store[0] = _addr._store[1] = 0; + return *this; +} + inline auto IP6Addr::operator=(in6_addr const &addr) -> self_type & { self_type::reorder(_addr._raw, addr); @@ -2530,7 +2581,7 @@ IPAddr::operator==(self_type const &that) const { case AF_INET6: return that._family == AF_INET6 && _addr._ip6 == that._addr._ip6; default: - return false; + return ! that.is_valid(); } } @@ -2677,6 +2728,24 @@ IPMask::as_ip4() const { return IP4Addr{addr}; } +inline auto +IPMask::clear() -> self_type & { + _cidr = INVALID; + return *this; +} + +inline auto +IPMask::operator<<=(raw_type n) -> self_type & { + _cidr -= n; + return *this; +} + +inline auto +IPMask::operator>>=(IPMask::raw_type n) -> self_type & { + _cidr += n; + return *this; +} + // +++ mixed mask operators +++ inline IP4Addr @@ -2875,7 +2944,7 @@ operator==(IP6Net const &lhs, IPNet const &rhs) { // +++ Range -> Network classes +++ inline bool -IP4Range::NetSource::is_valid(swoc::IP4Addr mask) { +IP4Range::NetSource::is_valid(swoc::IP4Addr mask) const { return ((mask._addr & _range._min._addr) == _range._min._addr) && ((_range._min._addr | ~mask._addr) <= _range._max._addr); } @@ -2890,7 +2959,7 @@ IP4Range::NetSource::begin() const { } inline IP4Range::NetSource::iterator -IP4Range::NetSource::end() const { +IP4Range::NetSource::end() { return self_type{range_type{}}; } @@ -2964,6 +3033,16 @@ IP6Range::NetSource::operator!=(IP6Range::NetSource::self_type const &that) cons return !(*this == that); } +inline IP6Addr const & +IP6Range::NetSource::addr() const { + return _range.min(); +} + +inline IPMask +IP6Range::NetSource::mask() const { + return _mask; +} + inline IPRange::NetSource::NetSource(IPRange::NetSource::range_type const &range) { if (range.is_ip4()) { new (&_ip4) decltype(_ip4)(range.ip4()); @@ -3091,6 +3170,22 @@ IPSpace::blend(IPRange const &range, U const &color, F &&blender) -> se return *this; } +template +template +auto +IPSpace::blend(IP4Range const &range, U const &color, F &&blender) -> self_type & { + _ip4.blend(range, color, std::forward(blender)); + return *this; +} + +template +template +auto +IPSpace::blend(IP6Range const &range, U const &color, F &&blender) -> self_type & { + _ip6.blend(range, color, std::forward(blender)); + return *this; +} + template void IPSpace::clear() { @@ -3122,14 +3217,14 @@ template auto IPSpace::end_ip4() const -> const_iterator { auto nc_this = const_cast(this); - return iterator(nc_this->_ip4.end(), nc_this->_ip6.begin()); + return { nc_this->_ip4.end(), nc_this->_ip6.begin() }; } template auto IPSpace::begin_ip6() const -> const_iterator { auto nc_this = const_cast(this); - return iterator(nc_this->_ip4.end(), nc_this->_ip6.begin()); + return { nc_this->_ip4.end(), nc_this->_ip6.begin() }; } template diff --git a/lib/swoc/include/swoc/swoc_version.h b/lib/swoc/include/swoc/swoc_version.h index 06af531f030..8dce2b4d394 100644 --- a/lib/swoc/include/swoc/swoc_version.h +++ b/lib/swoc/include/swoc/swoc_version.h @@ -23,11 +23,11 @@ #pragma once #if !defined(SWOC_VERSION_NS) -#define SWOC_VERSION_NS _1_3_5 +#define SWOC_VERSION_NS _1_3_6 #endif namespace swoc { inline namespace SWOC_VERSION_NS { static constexpr unsigned MAJOR_VERSION = 1; static constexpr unsigned MINOR_VERSION = 3; -static constexpr unsigned POINT_VERSION = 5; +static constexpr unsigned POINT_VERSION = 6; }} // namespace swoc::SWOC_VERSION_NS diff --git a/lib/swoc/src/swoc_ip.cc b/lib/swoc/src/swoc_ip.cc index 7198d7bbbf6..dc39df5b6fe 100644 --- a/lib/swoc/src/swoc_ip.cc +++ b/lib/swoc/src/swoc_ip.cc @@ -43,7 +43,7 @@ IP6Addr const IP6Addr::MAX{std::numeric_limits::max(), std::numeric_li // The Intel compiler won't let me directly use @c nullptr to construct a reference, so I need // to fake it out by using this psuedo-nullptr. -void *const pseudo_nullptr = 0; +void *const detail::pseudo_nullptr = nullptr; bool IPEndpoint::assign(sockaddr *dst, sockaddr const *src) { @@ -289,7 +289,7 @@ IP4Addr::operator=(sockaddr_in const *sa) -> self_type & { } sockaddr_in * -IP4Addr::fill(sockaddr_in *sa, in_port_t port) const { +IP4Addr::copy_to(sockaddr_in *sa, in_port_t port) const { sa->sin_addr.s_addr = this->network_order(); sa->sin_port = port; return sa; @@ -491,9 +491,9 @@ IPAddr::operator<(self_type const &that) const { case AF_INET: return _addr._ip4 < that._addr._ip4; case AF_INET6: - return false; - default: return true; + default: + return false; } } else if (AF_INET6 == _family) { switch (that._family) { @@ -502,10 +502,10 @@ IPAddr::operator<(self_type const &that) const { case AF_INET6: return _addr._ip6 < that._addr._ip6; default: - return true; + return false; } } - return false; + return that.is_valid(); } int @@ -529,7 +529,7 @@ IPAddr::cmp(self_type const &that) const { return 1; } } - return 0; + return that.is_valid() ? -1 : 0; } IPAddr::self_type & @@ -552,84 +552,9 @@ IPAddr::operator|=(IPMask const &mask) { return *this; } -#if 0 -bool -operator==(IPAddr const &lhs, sockaddr const *rhs) -{ - bool zret = false; - if (lhs._family == rhs->sa_family) { - if (AF_INET == lhs._family) { - zret = lhs._addr._ip4 == ats_ip4_addr_cast(rhs); - } else if (AF_INET6 == lhs._family) { - zret = 0 == memcmp(&lhs._addr._ip6, &ats_ip6_addr_cast(rhs), sizeof(in6_addr)); - } else { // map all non-IP to the same thing. - zret = true; - } - } // else different families, not equal. - 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. -*/ -int -IPAddr::cmp(self_type 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; -} - -#endif - bool IPAddr::is_multicast() const { - return (AF_INET == _family && 0xe == (_addr._octet[0] >> 4)) || (AF_INET6 == _family && _addr._ip6.is_multicast()); + return (AF_INET == _family && _addr._ip4.is_multicast()) || (AF_INET6 == _family && _addr._ip6.is_multicast()); } IPEndpoint::IPEndpoint(string_view const &text) { @@ -678,7 +603,7 @@ IPMask::mask_for(IP4Addr const &addr) { raw_type cidr = 0; if (auto q = (n & IP6Addr::QUAD_MASK); q != 0) { cidr = IP6Addr::QUAD_WIDTH + self_type::mask_for_quad(q); - } else if (auto q = ((n >> IP6Addr::QUAD_WIDTH) & IP6Addr::QUAD_MASK); q != 0) { + } else if (q = ((n >> IP6Addr::QUAD_WIDTH) & IP6Addr::QUAD_MASK); q != 0) { cidr = self_type::mask_for_quad(q); } return self_type(cidr); @@ -755,15 +680,14 @@ IP6Net::load(TextView text) { bool IPNet::load(TextView text) { - auto mask_text = text.split_suffix_at('/'); - if (!mask_text.empty()) { + if ( auto mask_text = text.split_suffix_at('/') ; !mask_text.empty() ) { IPMask mask; if (mask.load(mask_text)) { - if (IP6Addr addr; addr.load(text)) { // load the address - this->assign(addr, mask); + if (IP6Addr a6; a6.load(text)) { // load the address + this->assign(a6, mask); return true; - } else if (IP4Addr addr; addr.load(text)) { - this->assign(addr, mask); + } else if (IP4Addr a4; a4.load(text)) { + this->assign(a4, mask); return true; } } @@ -856,6 +780,12 @@ IP4Range::NetSource::operator++() -> self_type & { return *this; } +auto IP4Range::NetSource::operator++(int) -> self_type { + auto zret { *this }; + ++*this; + return zret; +} + void IP4Range::NetSource::search_wider() { while (_cidr > 0) { @@ -950,8 +880,7 @@ IPRange::IPRange(IPAddr const &min, IPAddr const &max) { bool IPRange::load(std::string_view const &text) { static const string_view CHARS{".:"}; - auto idx = text.find_first_of(CHARS); - if (idx != text.npos) { + if ( auto idx = text.find_first_of(CHARS) ; idx != text.npos ) { if (text[idx] == '.') { if (_range._ip4.load(text)) { _family = AF_INET; @@ -1019,6 +948,20 @@ IPRange::network_mask() const { return {}; } +bool +IPRange::operator==(self_type const &that) const { + if (_family != that._family) { + return false; + } + if (this->is_ip4()) { + return _range._ip4 == that._range._ip4; + } + if (this->is_ip6()) { + return _range._ip6 == that._range._ip6; + } + return true; +} + IPMask IP6Range::network_mask() const { NetSource nets{*this};