#ifndef NETWORK_ADDRESS_H
#define NETWORK_ADDRESS_H
/**
* @file
*
* Binary NetworkAddress
*/
#include "Platform.hh"
#include "Endpoint.hh"
/**
* A NetworkAddress represents a single network address in the form of a `struct sockaddr`, as used by the OS's socket
* API. A NetworkAddress's value may only be constructed/manipulated in sockaddr form, and the class then emulates the
* get_addrinfo (by building our own addrinfo struct value) and get_hostname()/get_service() (by using libc's
* getnameinfo() when the address is updated).
*
* This means that a NetworkAddress can be used like a NetworkEndpoint (like a literal IP address), but can also be
* used in a more specifc fashion like NetworkSocket::send or NetworkSocket::accept, where a definitive address is
* required.
*
* XXX: currently, there is no way to form a NetworkAddress from a NetworkEndpoint for e.g. sending UDP packets without
* an associated TCP connection.
*/
class NetworkAddress : public NetworkEndpoint {
protected:
/**
* The machine-readable address
*/
sockaddr_storage address;
/**
* The address length
*/
socklen_t address_length;
public:
/**
* Construct an empty SockAddr for later update()
*/
NetworkAddress (void);
/**
* Construct a NetworkAddress from a machine-readable address of the given length
*/
NetworkAddress (const sockaddr *addr, socklen_t len);
/**
* Get a const sockaddr* in this address
*
* @return read-only sockaddr pointer
*/
const sockaddr* get_sockaddr (void) const { return (const sockaddr *) &address; }
/**
* Get a mutable sockaddr* in this address
*
* @return writeable sockaddr pointer
*/
sockaddr* get_sockaddr (void) { return (sockaddr *) &address; }
/**
* Get the current address length
*
* @return address length
*/
socklen_t get_socklen (void) const { return address_length; }
/**
* Get a the address length pointer, initialized to the size of our sockaddr_storage.
*
* @return address length pointer
*/
socklen_t* get_socklen_ptr (void) { address_length = sizeof(address); return &address_length; }
/**
* Copy given sockaddr/len + update
*/
void set_sockaddr (const sockaddr *addr, socklen_t len);
/**
* Update internal state for NetworkAddress after sockaddr/socklen_ptr have been modified.
*/
void update (void);
/**
* Returns a "fake" addrinfo
*/
virtual addrinfo* get_addrinfo (int family, int socktype, int protocol = 0, int flags = 0) const;
/**
* Free an addrinfo returned by get_addrinfo
*/
virtual void free_addrinfo (addrinfo *info) const;
/**
* Equal-to comparison operator. Invalid addresses compare equal and are always smaller.
*
* XXX: use of memcmp is broken... there's garbage in the padding
*/
bool operator== (const NetworkAddress &other) const {
return (address_length == other.address_length) && memcmp(&address, &other.address, address_length) == 0;
}
/**
* Not-equal-to comparison operator. Invalid addresses compare equal and are always smaller.
*/
bool operator!= (const NetworkAddress &other) const {
return (address_length != other.address_length) || memcmp(&address, &other.address, address_length) != 0;
}
/**
* Less-than comparison operator. Smaller addresses are always lesser.
*/
bool operator< (const NetworkAddress &other) const {
return (address_length < other.address_length) || memcmp(&address, &other.address, other.address_length) < 0;
}
/**
* Greater-than comparison operator. Bigger addresses are always greater.
*/
bool operator> (const NetworkAddress &other) const {
return (address_length > other.address_length) || memcmp(&address, &other.address, address_length) > 0;
}
};
#endif