Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 95 additions & 18 deletions lib/swoc/include/swoc/IPAddr.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class IP4Addr {
explicit IP4Addr(sockaddr_in const *s);

/// Construct from text representation.
/// If the @a text is invalid the result is an invalid instance.
/// If the @a text is invalid the result is @c INADDR_ANY
IP4Addr(string_view const &text);

/// Self assignment.
Expand Down Expand Up @@ -83,20 +83,35 @@ class IP4Addr {
/// Apply @a mask to address, creating the broadcast address.
self_type &operator|=(IPMask const &mask);

/// Write this adddress and @a host_order_port to the sockaddr @a sa.
sockaddr_in *copy_to(sockaddr_in *sa, in_port_t port = 0) const;
/** Update socket address with this address.
*
* @param sa Socket address.
* @return @sa
*
* @a sa is assumed to be large enough to hold an IPv4 address.
*/
sockaddr *copy_to(sockaddr *sa) const;

/** Update socket address with this address.
*
* @param sin IPv4 socket address.
* @return @sin
*/
sockaddr_in *copy_to(sockaddr_in *sin) const;

/// @return The address in network order.
in_addr_t network_order() const;

/// @return The address in host order.
in_addr_t host_order() const;

/** Parse @a text as IPv4 address.
The address resulting from the parse is copied to this object if the conversion is successful,
otherwise this object is invalidated.

@return @c true on success, @c false otherwise.
/** Parse IPv4 address.
*
* @param text Text to parse.
*
* @return @c true if @a text is a valid IPv4 address, @c false otherwise.
*
* Whitespace is trimmed from @text before parsing. If the parse fails @a this is set to @c INADDR_ANY.
*/
bool load(string_view const &text);

Expand Down Expand Up @@ -281,15 +296,42 @@ class IP6Addr {
*/
constexpr uint8_t operator [] (int idx) const;

/// Write to @c sockaddr using network order and @a host_order_port.
sockaddr *copy_to(sockaddr *sa, in_port_t port = 0) const;
/** Update socket address with this address.
*
* @param sin IPv6 socket address.
* @return @sin
*/
sockaddr_in6 *copy_to(sockaddr_in6 *sin6) const;

/** Update socket address with this address.
*
* @param sa Socket address.
* @return @sin
*
* @a sa is assumed to be large enough to hold an IPv6 address.
*/
sockaddr *copy_to(sockaddr *sa) const;

/// Copy address to @a addr in network order.
in6_addr &copy_to(in6_addr &addr) const;
/// Return the address in host order.
in6_addr host_order() const;

/** Copy the address in host order.
*
* @param dst Destination for host order address.
* @return @a dst
*/
in6_addr& host_order(in6_addr & dst) const;

/// Return the address in network order.
in6_addr network_order() const;

/** Copy the address in network order.
*
* @param dst Destination for network order address.
* @return @a dst
*/
in6_addr &network_order(in6_addr &dst) const;

/** Parse a string for an IP address.

The address resuling from the parse is copied to this object if the conversion is successful,
Expand Down Expand Up @@ -403,11 +445,13 @@ class IP6Addr {
/// These are in sort of host order - @a _store elements are host order, but the
/// MSW and LSW are swapped (big-endian). This makes various bits of the implementation
/// easier. Conversion to and from network order is via the @c reorder method.
union {
union Addr {
word_store_type _store = {0}; ///< 0 is MSW, 1 is LSW.
quad_store_type _quad; ///< By quad.
raw_type _raw; ///< By byte.
in6_addr _in6; ///< By networking type (but in host order!)
} _addr;
static_assert(sizeof(in6_addr) == sizeof(raw_type));

static constexpr unsigned LSW = 1; ///< Least significant word index.
static constexpr unsigned MSW = 0; ///< Most significant word index.
Expand All @@ -417,7 +461,7 @@ class IP6Addr {
static constexpr std::array<unsigned, N_QUADS> QUAD_IDX = {3, 2, 1, 0, 7, 6, 5, 4};

/// Index of bytes in @a _addr._raw
/// This converts MSB (0) to LSB (15) indicies to the bytes in the binary format.
/// This converts MSB (0) to LSB (15) indices to the bytes in the binary format.
static constexpr std::array<unsigned, SIZE> RAW_IDX = { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8 };

/// Convert between network and host order.
Expand Down Expand Up @@ -516,6 +560,13 @@ class IPAddr {

self_type &operator|=(IPMask const &mask);

/** Copy the address to a socket address.
*
* @param sa Destination.
* @return @a sa
*/
sockaddr * copy_to(sockaddr * sa);

/** Parse a string and load the result in @a this.
*
* @param text Text to parse.
Expand Down Expand Up @@ -764,6 +815,12 @@ IP4Addr::operator=(in_addr_t ip) -> self_type & {
return *this;
}

inline sockaddr *
IP4Addr::copy_to(sockaddr *sa) const {
this->copy_to(reinterpret_cast<sockaddr_in*>(sa));
return sa;
}

/// Equality.
inline bool
operator==(IP4Addr const &lhs, IP4Addr const &rhs) {
Expand Down Expand Up @@ -909,16 +966,30 @@ inline bool IP6Addr::is_private() const {
return (_addr._raw[RAW_IDX[0]]& 0xFE) == 0xFC; // fc00::/7
}

inline in6_addr
IP6Addr::host_order() const {
Addr zret { {_addr._store[LSW], _addr._store[MSW] }};
return zret._in6;
}

inline in6_addr &
IP6Addr::copy_to(in6_addr &addr) const {
self_type::reorder(addr, _addr._raw);
return addr;
IP6Addr::host_order(in6_addr & dst) const {
Addr * addr = reinterpret_cast<Addr*>(&dst);
addr->_store[0] = _addr._store[LSW];
addr->_store[1] = _addr._store[MSW];
return dst;
}

inline in6_addr
IP6Addr::network_order() const {
in6_addr zret;
return this->copy_to(zret);
return this->network_order(zret);
}

inline in6_addr &
IP6Addr::network_order(in6_addr & dst) const {
self_type::reorder(dst, _addr._raw);
return dst;
}

inline auto
Expand Down Expand Up @@ -1004,6 +1075,12 @@ operator>=(IP6Addr const &lhs, IP6Addr const &rhs) {
return rhs <= lhs;
}

inline sockaddr *
IP6Addr::copy_to(sockaddr *sa) const {
this->copy_to(reinterpret_cast<sockaddr_in6*>(sa));
return sa;
}

inline IP6Addr &
IP6Addr::operator&=(IPMask const &mask) {
if (mask._cidr < WORD_WIDTH) {
Expand Down
102 changes: 93 additions & 9 deletions lib/swoc/include/swoc/IPEndpoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@
#include "swoc/swoc_version.h"
#include "swoc/MemSpan.h"
#include "swoc/TextView.h"
#include "swoc/string_view_util.h"

namespace swoc { inline namespace SWOC_VERSION_NS {

using ::std::string_view;

class IPAddr;
class IP4Addr;
class IP6Addr;

class IPSrv;
class IP4Srv;
class IP6Srv;

namespace detail {
extern void *const pseudo_nullptr;
}
Expand All @@ -38,6 +41,7 @@ extern void *const pseudo_nullptr;
*/
union IPEndpoint {
using self_type = IPEndpoint; ///< Self reference type.
using string_view = std::string_view;

struct sockaddr sa; ///< Generic address.
struct sockaddr_in sa4; ///< IPv4
Expand All @@ -51,11 +55,20 @@ union IPEndpoint {
/// Construct from the @a text representation of an address.
explicit IPEndpoint(string_view const &text);

// Construct from @c IPAddr
/// Construct from an address.
explicit IPEndpoint(IPAddr const &addr);

// Construct from @c sockaddr
IPEndpoint(sockaddr const *sa);
/// Construct from address and port.
explicit IPEndpoint(IPSrv const& srv);

/// Construct from generic socket address.
IPEndpoint(sockaddr const *addr);

/// Construct from @a sockaddr_in
IPEndpoint(sockaddr_in const* sin);

/// Construct from @a sockaddr_in6
IPEndpoint(sockaddr_in6 const * sin6);

/// Copy assignment.
self_type &operator=(self_type const &that);
Expand Down Expand Up @@ -106,8 +119,31 @@ union IPEndpoint {
*/
self_type &assign(sockaddr const *addr);

/// Assign from an @a addr and @a host_order_port.
self_type &assign(IPAddr const &addr, in_port_t port = 0);
/** Assign from IPv4 socket address.
*
* @param sin IPv4 socket address.
* @return @a this
*/
self_type &assign(sockaddr_in const * sin);

/** Assign from IPv6 socket address.
*
* @param sin6 IPv6 socket address.
* @return @a this
*/
self_type &assign(sockaddr_in6 const * sin6);

/// Assign from IP address.
self_type &assign(IPAddr const &addr);

/// Assign from IPv4 address.
self_type &assign(IP4Addr const& addr);

/// Assign from IPv4 address.
self_type &assign(IP6Addr const& addr);

/// Assign from IP service (address and port).
self_type &assign(IPSrv const& srv);

/// Copy to @a sa.
const self_type &copy_to(sockaddr *addr) const;
Expand All @@ -130,6 +166,18 @@ union IPEndpoint {
/// @return The IP address family.
sa_family_t family() const;

/// @return A pointer to a @c sockaddr_in or @c nullptr if not IPv4.
sockaddr_in * ip4();

/// @return A pointer to a @c sockaddr_in or @c nullptr if not IPv4.
sockaddr_in const * ip4() const;

/// @return A pointer to a @c sockaddr_in6 or @c nullptr if not IPv6.
sockaddr_in6 * ip6();

/// @return A pointer to a @c sockaddr_in6 or @c nullptr if not IPv6.
sockaddr_in6 const * ip6() const;

/// Set to be the ANY address for family @a family.
/// @a family must be @c AF_INET or @c AF_INET6.
/// @return This object.
Expand Down Expand Up @@ -190,8 +238,12 @@ inline IPEndpoint::IPEndpoint(IPAddr const &addr) {
this->assign(addr);
}

inline IPEndpoint::IPEndpoint(sockaddr const *socketaddr) {
this->assign(socketaddr);
inline IPEndpoint::IPEndpoint(IPSrv const& srv) {
this->assign(srv);
}

inline IPEndpoint::IPEndpoint(sockaddr const *addr) {
this->assign(addr);
}

inline IPEndpoint::IPEndpoint(IPEndpoint::self_type const &that) : self_type(&that.sa) {}
Expand All @@ -218,6 +270,18 @@ IPEndpoint::operator=(self_type const &that) {
return *this;
}

inline IPEndpoint &
IPEndpoint::assign(sockaddr_in const * sin) {
std::memcpy(&sa4, sin, sizeof(sockaddr_in));
return *this;
}

inline IPEndpoint &
IPEndpoint::assign(sockaddr_in6 const * sin6) {
std::memcpy(&sa6, sin6, sizeof(sockaddr_in6));
return *this;
}

inline IPEndpoint &
IPEndpoint::assign(sockaddr const *src) {
self_type::assign(&sa, src);
Expand Down Expand Up @@ -245,6 +309,26 @@ IPEndpoint::family() const {
return sa.sa_family;
}

inline sockaddr_in *
IPEndpoint::ip4() {
return this->is_ip4() ? &sa4 : nullptr;
}

inline sockaddr_in const *
IPEndpoint::ip4() const {
return this->is_ip4() ? &sa4 : nullptr;
}

inline sockaddr_in6 *
IPEndpoint::ip6() {
return this->is_ip6() ? &sa6 : nullptr;
}

inline sockaddr_in6 const *
IPEndpoint::ip6() const {
return this->is_ip6() ? &sa6 : nullptr;
}

inline in_port_t &
IPEndpoint::network_order_port() {
return self_type::port(&sa);
Expand Down
3 changes: 3 additions & 0 deletions lib/swoc/include/swoc/IPRange.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

#pragma once

#include <string_view>
#include <variant> // for std::monostate

#include <swoc/DiscreteRange.h>
#include <swoc/IPAddr.h>

Expand Down
Loading