#include "Address.hh"
#include <sstream>
NetworkAddress::NetworkAddress (void) :
hostname(), service(), address_length(0)
{
}
NetworkAddress::NetworkAddress (std::string service) :
hostname(), service(service), address_length(0)
{
}
NetworkAddress::NetworkAddress (std::string hostname, std::string service) :
hostname(hostname), service(service), address_length(0)
{
}
NetworkAddress::NetworkAddress (const sockaddr *addr, socklen_t len) :
hostname(), service(), address_length(0)
{
// proxy to set_sockaddr
set_sockaddr(addr, len);
}
addrinfo* NetworkAddress::get_addrinfo (int family, int socktype, int protocol, int flags) const {
addrinfo hints, *results;
int err;
// initialize flags
hints.ai_flags = flags;
hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = protocol;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_next = NULL;
// hostname + service may be NULL
const char *hostname = this->hostname.empty() ? NULL : this->hostname.c_str();
const char *service = this->service.empty() ? NULL : this->service.c_str();
// do getaddrinfo()
if ((err = getaddrinfo(hostname, service, &hints, &results)))
throw NetworkAddressError(*this, "getaddrinfo", gai_strerror(err));
// done
return results;
}
const sockaddr* NetworkAddress::get_sockaddr (socklen_t &len_ref) const {
// we can't figure this out ourselves...
if (address_length == 0)
throw Error("NetworkAddress::get_sockaddr called without a valid sockaddr set");
// update len
len_ref = address_length;
// and return a pointer to our internal address
return (const sockaddr*) &address;
}
void NetworkAddress::set_sockaddr (const sockaddr *addr, socklen_t len) {
char host_buf[NI_MAXHOST], serv_buf[NI_MAXSERV];
int err;
// invalid length?
if (len > sizeof(this->address))
throw NetworkAddressError(*this, "set_sockaddr", "invalid sockaddr length");
// do getnameinfo()
if ((err = getnameinfo(addr, len, host_buf, NI_MAXHOST, serv_buf, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV)))
throw NetworkAddressError(*this, "getnameinfo", gai_strerror(err));
// copy over to address
memcpy(&this->address, addr, len);
// and update address_length
this->address_length = len;
// and the hostname + service
hostname = host_buf;
service = serv_buf;
}
std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr) {
s << "[" << addr.get_hostname() << ":" << addr.get_service() << "]";
return s;
}
std::string NetworkAddressError::build_str (const NetworkAddress &addr, const char *op, const char *msg) {
std::stringstream ss;
ss << op << ": " << addr << ": " << msg;
return ss.str();
}
NetworkAddressError::NetworkAddressError (const NetworkAddress &addr, const char *op, const char *msg) :
Error(build_str(addr, op, msg))
{
}