src/Network/Address.cc
changeset 382 190f81d30624
parent 381 9b35bc329d23
equal deleted inserted replaced
381:9b35bc329d23 382:190f81d30624
     1 
     1 
     2 #include "Address.hh"
     2 #include "Address.hh"
     3 
     3 
     4 #include <sstream>
     4 #include <cstdlib>
     5 
     5 
     6 NetworkEndpoint::NetworkEndpoint (void) :
     6 NetworkAddress::NetworkAddress (void) :
     7     hostname(), service()
     7     NetworkEndpoint(), address_length(0)
     8 {
     8 {
     9 
     9 
    10 }
    10 }
    11 
    11 
    12 NetworkEndpoint::NetworkEndpoint (std::string service) :
    12 NetworkAddress::NetworkAddress (const sockaddr *addr, socklen_t len) :
    13     hostname(), service(service)
    13     NetworkEndpoint(), address_length(0)
    14 {
    14 {
       
    15     // proxy to set_sockaddr
       
    16     set_sockaddr(addr, len);
       
    17 }
       
    18  
       
    19 void NetworkAddress::set_sockaddr (const sockaddr *addr, socklen_t len) {
       
    20     // invalid length?
       
    21     if (len <= 0 || len > sizeof(address))
       
    22         throw NetworkAddressError(*this, "set_sockaddr", "invalid sockaddr length");
    15 
    23 
    16 }
    24     // copy over to address
    17         
    25     memcpy(&address, addr, len);
    18 NetworkEndpoint::NetworkEndpoint (std::string hostname, std::string service) :
       
    19     hostname(hostname), service(service)
       
    20 {
       
    21 
       
    22 }
       
    23        
       
    24 addrinfo* NetworkEndpoint::get_addrinfo (int family, int socktype, int protocol, int flags) const {
       
    25     addrinfo hints, *results;
       
    26     int err;
       
    27     
    26     
    28     // initialize flags
    27     // set address_length
    29     hints.ai_flags = flags;
    28     address_length = len;
    30     hints.ai_family = family;
    29     
    31     hints.ai_socktype = socktype;
    30    // update
    32     hints.ai_protocol = protocol;
    31    update();
    33     hints.ai_addrlen = 0;
       
    34     hints.ai_canonname = NULL;
       
    35     hints.ai_next = NULL;
       
    36 
       
    37     // hostname + service may be NULL
       
    38     const char *hostname = this->hostname.empty() ? NULL : this->hostname.c_str();
       
    39     const char *service = this->service.empty() ? NULL : this->service.c_str();
       
    40 
       
    41     // do getaddrinfo()
       
    42     if ((err = getaddrinfo(hostname, service, &hints, &results)))
       
    43         throw NetworkAddressError(*this, "getaddrinfo", gai_strerror(err));
       
    44 
       
    45     // done
       
    46     return results;
       
    47 }
       
    48         
       
    49 void NetworkEndpoint::free_addrinfo (addrinfo *info) const {
       
    50     freeaddrinfo(info);
       
    51 }
    32 }
    52 
    33 
    53 std::ostream& operator<< (std::ostream &s, const NetworkEndpoint &addr) {
    34 void NetworkAddress::update (void) {
    54     s << "[" << addr.get_hostname() << ":" << addr.get_service() << "]";
    35     char host_buf[NI_MAXHOST], serv_buf[NI_MAXSERV];
       
    36     int err;
    55 
    37 
    56     return s;
    38     // do getnameinfo()
    57 
    39     if ((err = getnameinfo((sockaddr *) &address, address_length, host_buf, NI_MAXHOST, serv_buf, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV)))
    58 }
    40         throw NetworkAddressError(*this, "getnameinfo", gai_strerror(err));
    59  
    41     
    60 std::string NetworkAddressError::build_str (const NetworkEndpoint &addr, const char *op, const char *msg) {
    42     // update hostname + service
    61     std::stringstream ss;
    43     hostname = host_buf;
    62 
    44     service = serv_buf;
    63     ss << op << ": " << addr << ": " << msg;
       
    64 
       
    65     return ss.str();
       
    66 }
    45 }
    67 
    46 
    68 NetworkAddressError::NetworkAddressError (const NetworkEndpoint &addr, const char *op, const char *msg) :
    47 addrinfo* NetworkAddress::get_addrinfo (int family, int socktype, int protocol, int flags) const {
    69     Error(build_str(addr, op, msg))
    48     (void) flags;
    70 {
       
    71 
    49 
       
    50     // get my family from address
       
    51     int my_family = address.ss_family;
       
    52     
       
    53     // right family?
       
    54     if (family && family != my_family)
       
    55         throw NetworkAddressError(*this, "fake_getaddrinfo", "ai_family mismatch");
       
    56     
       
    57     // alllocate new addrinfo
       
    58     addrinfo *r = new addrinfo;
       
    59 
       
    60     // set it up
       
    61     r->ai_flags = 0;
       
    62     r->ai_family = my_family;
       
    63     r->ai_socktype = socktype;
       
    64     r->ai_protocol = protocol;
       
    65     r->ai_addrlen = get_socklen();
       
    66     r->ai_addr = const_cast<sockaddr *>(get_sockaddr());
       
    67     r->ai_canonname = const_cast<char *>(get_hostname().c_str());
       
    68     r->ai_next = NULL;
       
    69 
       
    70     // return it
       
    71     return r;
    72 }
    72 }
    73 
    73 
       
    74 void NetworkAddress::free_addrinfo (addrinfo *info) const {
       
    75     delete info;
       
    76 }