#ifndef NETWORK_ADDRESS_HH
#define NETWORK_ADDRESS_HH
#include "../Error.hh"
/*
* Platform-specific includes
*/
#ifndef WIN32
// linux
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#else
#error "This network code won't compile on win32 :)"
#endif
#include <string>
// assume...
#if INET6_ADDRSTRLEN < INET_ADDRSTRLEN
#error INET6_ADDRSTRLEN is smaller than INET_ADDRSTRLEN
#endif
/**
* Length of a network address
*/
const socklen_t NETWORK_ADDRESS_LENGTH = INET6_ADDRSTRLEN;
/**
* We use ClanLib's IPAddress API, but with our own name
*/
class NetworkAddress {
private:
/**
* Our human-readable hostname
*/
std::string hostname;
/**
* Our human-readable service
*/
std::string service;
/**
* Our machine-readable address and its length
*/
sockaddr_storage address;
socklen_t address_length;
public:
/**
* Construct an empty NetworkAddress
*/
NetworkAddress (void);
/**
* Construct a NetworkAddress with a NULL hostname, and a specific service
*/
NetworkAddress (std::string service);
/**
* Construct a NetworkAddress on a specific hostname and service
*/
NetworkAddress (std::string hostname, std::string service);
/**
* Construct a NetworkAddress from a machine-readable address of the given length
*/
NetworkAddress (const sockaddr *addr, socklen_t len);
/*
* We can use the default copy-constructor and assignment operator
*/
public:
/**
* Get a addrinfo* for this address using the given family/type/protocol/flags.
*
* Remember to free the returned pointer using freeaddrinfo() after use.
*
* @param family the socket family for hints.ai_family
* @param socktype the socket type for hints.ai_socktype
* @param protoocl the socket protocol for hints.ai_protocol
* @param flags the flags for hints.ai_flags
* @return linked list of addrinfo's
* @throw NetworkAddressError if resolving this address fails
*/
addrinfo* get_addrinfo (int family, int socktype, int protocol = 0, int flags = 0) const;
/**
* Get a sockaddr* for this address. This is only valid for NetworkAddress's which have had set_sockaddr called
* on them.
*
* @param len_ref updated to the sockaddr length
* @return borrowed sockaddr pointer
*/
const sockaddr* get_sockaddr (socklen_t &len_ref) const;
/**
* Set a sockaddr for this address
*
* @param addr the address to copy, of len bytes
* @param len the size of the sockaddr
*/
void set_sockaddr (const sockaddr *addr, socklen_t len);
/**
* Get the human-readable hostname
*/
std::string get_hostname (void) const { return hostname; }
/**
* Get the human-readable service name
*/
std::string get_service (void) const { return service; }
/**
* Equal-to comparison operator. This requires that the machine-readable address be available.
*/
bool operator== (const NetworkAddress &other) const {
return (address_length == other.address_length) && memcmp(&address, &other.address, address_length) == 0;
}
/**
* Not-qqual-to comparison operator. This requires that the machine-readable address be available.
*/
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;
}
};
/**
* Formatted as [<addr>:<port>]
*/
std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr);
/**
*
*/
class NetworkAddressError : public Error {
protected:
static std::string build_str (const NetworkAddress &addr, const char *op, const char *msg);
public:
NetworkAddressError (const NetworkAddress &addr, const char *op, const char *msg);
};
#endif /* NETWORK_ADDRESS_HH */