diff --git a/code/include/swoc/IPSrv.h b/code/include/swoc/IPSrv.h index de2f5e8..d4f245b 100644 --- a/code/include/swoc/IPSrv.h +++ b/code/include/swoc/IPSrv.h @@ -85,29 +85,29 @@ class IP4Srv { */ bool load(swoc::TextView text); - /** Change the address. + /** Assign an IPv4 address. * * @param addr Address to assign. * @return @a this */ self_type &assign(IP4Addr const &addr); - /** Change the host_order_port. + /** Assign a port. * - * @param port Port to assign. + * @param port Port to assign (host order) * @return @a this. */ self_type &assign(in_port_t port); - /** Change the address and port. + /** Assign an address and port. * * @param addr Address to assign. - * @param port Port to assign. + * @param port Port to assign (host order). * @return @a this */ self_type &assign(IP4Addr const &addr, in_port_t port); - /** Change the address and port. + /** Assign an address and port from an IPv4 socket address. * * @param s A socket address. * @return @a this @@ -116,7 +116,7 @@ class IP4Srv { protected: IP4Addr _addr; ///< Address. - in_port_t _port = 0; ///< Port. + in_port_t _port = 0; ///< Port [host order]. }; /// An IPv6 address and host_order_port, modeled on an SRV type for DNS. @@ -193,17 +193,17 @@ class IP6Srv { */ self_type &assign(IP6Addr const &addr); - /** Change the host_order_port. + /** Assign a port. * - * @param port Port to assign. + * @param port Port [host order]. * @return @a this. */ self_type &assign(in_port_t port); - /** Change the address and host_order_port. + /** Assign an address and port. * - * @param addr Address to assign. - * @param port Port to assign. + * @param addr Address. + * @param port Port [host order]. * @return @a this */ self_type &assign(IP6Addr const &addr, in_port_t port); @@ -217,7 +217,7 @@ class IP6Srv { protected: IP6Addr _addr; ///< Address. - in_port_t _port = 0; ///< Port. + in_port_t _port = 0; ///< Port [host order] }; /// An IP address and host_order_port, modeled on an SRV type for DNS. @@ -228,11 +228,17 @@ class IPSrv { public: IPSrv() = default; ///< Default constructor. explicit IPSrv(IP4Addr addr, in_port_t port = 0) : _srv(IP4Srv{addr, port}), _family(addr.family()) {} + /// Construct for IPv6 address and port. explicit IPSrv(IP6Addr addr, in_port_t port = 0) : _srv(IP6Srv{addr, port}), _family(addr.family()) {} + /// Construct from generic address and port. explicit IPSrv(IPAddr addr, in_port_t port = 0); + /// Construct from socket address. explicit IPSrv(sockaddr const *sa); + /// Construct IPv4 service from socket address. explicit IPSrv(sockaddr_in const *s); + /// Construct IPv6 service from socket address. explicit IPSrv(sockaddr_in6 const *s); + /// Construct from Endpoint. explicit IPSrv(IPEndpoint const &ep); /** Construct from a string. @@ -259,21 +265,17 @@ class IPSrv { /// @return The protocol of the current value. constexpr sa_family_t family() const; + /// @return @c true if this is a valid service, @c false if not. + bool is_valid() const; /// @return @c true if the data is IPv4, @c false if not. bool is_ip4() const; /// @return @c true if hte data is IPv6, @c false if not. bool is_ip6() const; /// @return The IPv4 data. - IP4Srv const & - ip4() const { - return _srv._ip4; - } + IP4Srv const & ip4() const; /// @return The IPv6 data. - IP6Srv const & - ip6() const { - return _srv._ip6; - } + IP6Srv const & ip6() const; /** Change the address. * @@ -289,88 +291,91 @@ class IPSrv { */ self_type &assign(IP6Addr const &addr); - /** Change the address. + /** Assign an address. * - * @param addr Address to assign. + * @param addr Address. * @return @a this * - * If @a addr isn't valid then no assignment is made. + * If @a addr isn't valid then no assignment is made, otherwise the family is changed to that of + * @a addr. */ self_type &assign(IPAddr const &addr); - /** Change the host_order_port. + /** Assign port. * - * @param port Port in host order. + * @param port Port [host order]. * @return @a this. */ self_type &assign(in_port_t port); - /** Change the address and port. + /** Assign an IPv4 address and port. * - * @param addr Address to assign. - * @param port Port to assign. + * @param addr Address. + * @param port Port [host order]. * @return @a this */ self_type &assign(IP4Addr const &addr, in_port_t port); - /** Change the address and port. + /** Assign an IPv6 address and port. * - * @param addr Address to assign. - * @param port Port to assign. + * @param addr Address. + * @param port Port [host order]. * @return @a this */ self_type &assign(IP6Addr const &addr, in_port_t port); - /** Change the address and port. + /** Assogm address amd [prt/ * * @param sa Socket address. * @return @a this + * + * The assignment is ignored if @a sa is not a valid IP family, otherwise the family is changed + * to that of @a sa. */ self_type &assign(sockaddr const *sa); - /** Change the address and port. + /** Assign an IPv4 address and port. * * @param s Socket address. * @return @a this */ self_type &assign(sockaddr_in const *s); - /** Change the address and port. + /** Assign an IPv6 address and port. * * @param s Socket address. * @return @a this */ self_type &assign(sockaddr_in6 const *s); - /** Change the address and host_order_port. + /** Assign an address and port. * - * @param addr Address to assign. - * @param port Port to assign. + * @param addr Address. + * @param port Port [host order]. * @return @a this * - * If @a addr isn't valid then no assignment is made. + * If @a addr isn't valid then no assignment is made, otherwise the family is changed to match + * @a addr. */ self_type &assign(IPAddr const &addr, in_port_t port); + /// Copy assignment. self_type &operator=(self_type const &that) = default; + /// Assign from IPv4. self_type &operator=(IP4Srv const &that); + /// Assign from IPv6. self_type &operator=(IP6Srv const &that); - self_type & - operator=(sockaddr const *sa) { - return this->assign(sa); - } - self_type & - operator=(sockaddr_in const *s) { - return this->assign(s); - } - self_type & - operator=(sockaddr_in6 const *s) { - return this->assign(s); - } + /// Assign from generic socket address. + self_type & operator=(sockaddr const *sa); + /// Assign from IPv4 socket address. + self_type & operator=(sockaddr_in const *s); + /// Assign from IPv6 socket address. + self_type & operator=(sockaddr_in6 const *s); protected: /// Family specialized data. union data { + std::monostate _nil; ///< Nil / invalid state. IP4Srv _ip4; ///< IPv4 address (host) IP6Srv _ip6; ///< IPv6 address (host) @@ -555,19 +560,42 @@ inline IPAddr IPSrv::addr() const { return _srv.addr(_family); } + inline constexpr sa_family_t IPSrv::family() const { return _family; } + +inline bool IPSrv::is_valid() const { return AF_INET == _family || AF_INET6 == _family; } + inline bool IPSrv::is_ip4() const { return _family == AF_INET; } + inline bool IPSrv::is_ip6() const { return _family == AF_INET6; } +inline IP4Srv const& IPSrv::ip4() const { + return _srv._ip4; +} + +inline IP6Srv const& IPSrv::ip6() const { + return _srv._ip6; +} + +inline constexpr in_port_t +IPSrv::host_order_port() const { + return _srv.port(_family); +} + +inline in_port_t +IPSrv::network_order_port() const { + return ntohs(_srv.port(_family)); +} + inline auto IPSrv::assign(IP6Addr const &addr) -> self_type & { _srv._ip6.assign(addr, this->host_order_port()); @@ -656,14 +684,16 @@ IPSrv::assign(sockaddr_in6 const *s) -> self_type & { return *this; } -inline constexpr in_port_t -IPSrv::host_order_port() const { - return _srv.port(_family); +inline IPSrv::self_type & IPSrv::operator=(sockaddr const *sa) { + return this->assign(sa); } -inline in_port_t -IPSrv::network_order_port() const { - return ntohs(_srv.port(_family)); +inline IPSrv::self_type & IPSrv::operator=(sockaddr_in const *s) { + return this->assign(s); +} + +inline IPSrv::self_type & IPSrv::operator=(sockaddr_in6 const *s) { + return this->assign(s); } inline IPAddr @@ -675,6 +705,7 @@ constexpr inline in_port_t IPSrv::data::port(sa_family_t f) const { return (f == AF_INET) ? _ip4.host_order_port() : (f == AF_INET6) ? _ip6.host_order_port() : 0; } + // --- Independent comparisons. inline bool diff --git a/unit_tests/test_TextView.cc b/unit_tests/test_TextView.cc index 2f13dfb..ebeb6c2 100644 --- a/unit_tests/test_TextView.cc +++ b/unit_tests/test_TextView.cc @@ -545,7 +545,7 @@ TEST_CASE("TextView Conversions", "[libswoc][TextView]") { x.assign("-9223372036854775809"); CHECK(svtoi(x) == IMIN); - // floating point is never exact, so "good enough" is all that is measureable. This checks the + // floating point is never exact, so "good enough" is all that iisnts measureable. This checks the // value is within one epsilon (minimum change possible) of the compiler generated value. auto fcmp = [](double lhs, double rhs) { double tolerance = std::max({1.0, std::fabs(lhs), std::fabs(rhs)}) * std::numeric_limits::epsilon();