The Address concept represents a communication end point. As far as the socket library is concerned, the follow are the three functions required.
Too enable the user to use the address in containers, etc, the following are requirements
All name lookup and resolution (gethostbyname, inet_addr, et al) is address family specific.
It would be worth specifiying an IpAddress? concept to get interoperability between Ip4 and Ip6. This would specify port, hostname conversions, etc
class addressinfo { public:
addressinfo() : m_addrinfo(NULL), m_begin(NULL), m_engaged(false) { }
~addressinfo() { if (m_engaged) ::freeaddrinfo(m_begin); }
/* * flags AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST * family PF_UNSPEC, PF_INET, PF_INET6 * socktype SOCK_STREAM, SOCK_DGRAM, 0 * protocol IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, IPPROTO_UDP, 0 */ void getaddrinfo( const char* service, const char* name, const int flags = 0, const int family = PF_UNSPEC, const int socktype = 0, const int protocol = 0 ) { int result; if(m_engaged) { m_engaged = false; ::freeaddrinfo(m_begin); } ::addrinfo hint; memset(&hint, 0, sizeof(hint)); hint.ai_flags = flags; hint.ai_family = family; hint.ai_socktype = socktype; hint.ai_protocol = protocol; m_engaged = true; result = ::getaddrinfo(name, service, &hint, &m_begin); if (result != 0) { //throw exception } rewind(); return; }
const int ai_flags() { return m_addrinfo->ai_flags; } const int ai_family() { return m_addrinfo->ai_family; } const int ai_socktype() { return m_addrinfo->ai_socktype; } const int ai_protocol() { return m_addrinfo->ai_protocol; } const ::sockaddr* ai_addr() { return m_addrinfo->ai_addr; } const size_t ai_addrlen() { return m_addrinfo->ai_addrlen; }
bool next() { if (m_addrinfo->ai_next != NULL) { m_addrinfo = m_addrinfo->ai_next; return true; } else { rewind(); return false; } }
private:
void rewind() { m_addrinfo = m_begin; }
private:
::addrinfo* m_addrinfo; ::addrinfo* m_begin; bool m_engaged;};
It can provide thread-safety, portablity and protocol-independence IMHO.
-- See BoostSocket/AddressInfoConcept -- Hugo
I would propose that we separate name resolving from the actual address class. Actually i would like to propose these interfaces for address and resolving (wraps addrinfo if present on platform). The interface below is an general ip4 and ip6 structure. I think that we should strive to make ip4/ip6 work compiletime polymorph and diff ip4/ip6 as little as possible so transition and supporting both ip4 and ip6 can be smooth and made easily configurable without having to have double hierarchies of addresses, protocols if possible. And I would propose enabling and detecting ipv6 via a config define BOOST_HAS_IPV6??
struct ip_address { enum family_t { family_ipv4 = 1, family_ipv6 = 2 };
enum special_address_t { no_special_address, special_address_any, special_address_broadcast, special_address_loopback, special_address_none };
/// construct an addres from a numeric string. Eg dotted IPv4 or numeric IPv6. /// @throws boost::socket::error on failure eg bad string format ip_address(const std::string& numeric);
/// construct an special address ip_address(special_address_t special, family_t family);
/// Copy and assignment for value semantics ip_address(const ip_address& address); ip_address& operator=(const ip_address& address);
/// Destructor ~ip_address();
/// String representation of address. const std::string& to_str() const;
/// octets of ip address. const std::vector<unsigned char> ip_address() const;
/// Fully Qualified Domain Name (FQDN) for address, /// if this represents a resolved addres empty if /// address isn't an resolved. const std::string& host_name() const;
family_t family() const; special_address_t special_address() const;
/// implementation defined default sorting order bool operator<(const ip_address& other) const; /// equality bool operator==(const ip_address& other) const; /// inequality bool operator!=(const ip_address& other) const { return !operator==(other); } }
struct ip_end_point { enum special_port { special_port_any = 0 };
typedef unsigned short port_t;
/// Copy constructor ip_end_point (const end_point& other);
/// Constructs an end point from address and port ip_end_point (const address& address, port_t port);
/// Constructs an end point from address string x.y.z.x:p ip_end_point (const std::string& address);
/// port port_t port() const; /// address const ip_end_point& ip_address() const;
family_t family() const; std::pair<void*,unsigned> representation(); // pointer to internal rep and size pointer // equality end_point& operator=(const end_point& other); /// implementation defined default sorting order bool operator<(const end_point& other); };
struct ip_resolver { /// ip_resolver (const std::string& host); typedef impl_def_iterator const_iterator;
/// do the actual resolving if not called /// throws on error. void resolve();
/// will call resolve if not called const_iterator begin() const; /// iterator pointing to const ip_address& const_iterator end() const; /// iterator pointing to const ip_address& size_t size() const; bool empty() const; };
I would propose a general definition of address concept like this:
constructors assignment:
Ordering and comparing