src/Network/Address.cc
author terom
Tue, 16 Dec 2008 20:30:35 +0000
changeset 379 2a8e780844d2
parent 378 5589abf5e61b
child 380 d193dd1d8a7e
permissions -rw-r--r--
fix some NetworkAddress omissions

#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 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))
{

}