Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2004--2005, Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #ifdef POSIX
     29 #include <sys/types.h>
     30 #include <sys/socket.h>
     31 #include <netinet/in.h>
     32 #include <netinet/ip.h>
     33 #include <arpa/inet.h>
     34 #include <netdb.h>
     35 #include <unistd.h>
     36 #endif
     37 
     38 #include <sstream>
     39 
     40 #include "talk/base/byteorder.h"
     41 #include "talk/base/common.h"
     42 #include "talk/base/logging.h"
     43 #include "talk/base/nethelpers.h"
     44 #include "talk/base/socketaddress.h"
     45 
     46 #ifdef WIN32
     47 // Win32 doesn't provide inet_aton, so we add our own version here.
     48 // Since inet_addr returns 0xFFFFFFFF on error, if we get this value
     49 // we need to test the input to see if the address really was 255.255.255.255.
     50 // This is slightly fragile, but better than doing nothing.
     51 int inet_aton(const char* cp, struct in_addr* inp) {
     52   inp->s_addr = inet_addr(cp);
     53   return (inp->s_addr == INADDR_NONE &&
     54           strcmp(cp, "255.255.255.255") != 0) ? 0 : 1;
     55 }
     56 #endif  // WIN32
     57 
     58 namespace talk_base {
     59 
     60 SocketAddress::SocketAddress() {
     61   Clear();
     62 }
     63 
     64 SocketAddress::SocketAddress(const std::string& hostname, int port) {
     65   SetIP(hostname);
     66   SetPort(port);
     67 }
     68 
     69 SocketAddress::SocketAddress(uint32 ip, int port) {
     70   SetIP(ip);
     71   SetPort(port);
     72 }
     73 
     74 SocketAddress::SocketAddress(const SocketAddress& addr) {
     75   this->operator=(addr);
     76 }
     77 
     78 void SocketAddress::Clear() {
     79   hostname_.clear();
     80   ip_ = 0;
     81   port_ = 0;
     82 }
     83 
     84 bool SocketAddress::IsNil() const {
     85   return hostname_.empty() && (0 == ip_) && (0 == port_);
     86 }
     87 
     88 bool SocketAddress::IsComplete() const {
     89   return (0 != ip_) && (0 != port_);
     90 }
     91 
     92 SocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
     93   hostname_ = addr.hostname_;
     94   ip_ = addr.ip_;
     95   port_ = addr.port_;
     96   return *this;
     97 }
     98 
     99 void SocketAddress::SetIP(uint32 ip) {
    100   hostname_.clear();
    101   ip_ = ip;
    102 }
    103 
    104 void SocketAddress::SetIP(const std::string& hostname) {
    105   hostname_ = hostname;
    106   ip_ = StringToIP(hostname);
    107 }
    108 
    109 void SocketAddress::SetResolvedIP(uint32 ip) {
    110   ip_ = ip;
    111 }
    112 
    113 void SocketAddress::SetPort(int port) {
    114   ASSERT((0 <= port) && (port < 65536));
    115   port_ = port;
    116 }
    117 
    118 uint32 SocketAddress::ip() const {
    119   return ip_;
    120 }
    121 
    122 uint16 SocketAddress::port() const {
    123   return port_;
    124 }
    125 
    126 std::string SocketAddress::IPAsString() const {
    127   if (!hostname_.empty())
    128     return hostname_;
    129   return IPToString(ip_);
    130 }
    131 
    132 std::string SocketAddress::PortAsString() const {
    133   std::ostringstream ost;
    134   ost << port_;
    135   return ost.str();
    136 }
    137 
    138 std::string SocketAddress::ToString() const {
    139   std::ostringstream ost;
    140   ost << IPAsString();
    141   ost << ":";
    142   ost << port();
    143   return ost.str();
    144 }
    145 
    146 bool SocketAddress::FromString(const std::string& str) {
    147   std::string::size_type pos = str.find(':');
    148   if (std::string::npos == pos)
    149     return false;
    150   SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10));
    151   SetIP(str.substr(0, pos));
    152   return true;
    153 }
    154 
    155 std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
    156   os << addr.IPAsString() << ":" << addr.port();
    157   return os;
    158 }
    159 
    160 bool SocketAddress::IsAnyIP() const {
    161   return (ip_ == 0);
    162 }
    163 
    164 bool SocketAddress::IsLoopbackIP() const {
    165   if (0 == ip_) {
    166     return (0 == stricmp(hostname_.c_str(), "localhost"));
    167   } else {
    168     return ((ip_ >> 24) == 127);
    169   }
    170 }
    171 
    172 bool SocketAddress::IsLocalIP() const {
    173   if (IsLoopbackIP())
    174     return true;
    175 
    176   std::vector<uint32> ips;
    177   if (0 == ip_) {
    178     if (!hostname_.empty()
    179         && (0 == stricmp(hostname_.c_str(), GetHostname().c_str()))) {
    180       return true;
    181     }
    182   } else if (GetLocalIPs(ips)) {
    183     for (size_t i = 0; i < ips.size(); ++i) {
    184       if (ips[i] == ip_) {
    185         return true;
    186       }
    187     }
    188   }
    189   return false;
    190 }
    191 
    192 bool SocketAddress::IsPrivateIP() const {
    193   return ((ip_ >> 24) == 127) ||
    194          ((ip_ >> 24) == 10) ||
    195          ((ip_ >> 20) == ((172 << 4) | 1)) ||
    196          ((ip_ >> 16) == ((192 << 8) | 168)) ||
    197          ((ip_ >> 16) == ((169 << 8) | 254));
    198 }
    199 
    200 bool SocketAddress::IsUnresolvedIP() const {
    201   return IsAny() && !hostname_.empty();
    202 }
    203 
    204 bool SocketAddress::ResolveIP(bool force, int* error) {
    205   if (hostname_.empty()) {
    206     // nothing to resolve
    207   } else if (!force && !IsAny()) {
    208     // already resolved
    209   } else {
    210     LOG_F(LS_VERBOSE) << "(" << hostname_ << ")";
    211     int errcode = 0;
    212     if (hostent* pHost = SafeGetHostByName(hostname_.c_str(), &errcode)) {
    213       ip_ = NetworkToHost32(*reinterpret_cast<uint32*>(pHost->h_addr_list[0]));
    214       LOG_F(LS_VERBOSE) << "(" << hostname_ << ") resolved to: "
    215                         << IPToString(ip_);
    216       FreeHostEnt(pHost);
    217     } else {
    218       LOG_F(LS_ERROR) << "(" << hostname_ << ") err: " << errcode;
    219     }
    220     if (error) {
    221       *error = errcode;
    222     }
    223   }
    224   return (ip_ != 0);
    225 }
    226 
    227 bool SocketAddress::operator==(const SocketAddress& addr) const {
    228   return EqualIPs(addr) && EqualPorts(addr);
    229 }
    230 
    231 bool SocketAddress::operator<(const SocketAddress& addr) const {
    232   if (ip_ < addr.ip_)
    233     return true;
    234   else if (addr.ip_ < ip_)
    235     return false;
    236 
    237   // We only check hostnames if both IPs are zero.  This matches EqualIPs()
    238   if (addr.ip_ == 0) {
    239     if (hostname_ < addr.hostname_)
    240       return true;
    241     else if (addr.hostname_ < hostname_)
    242       return false;
    243   }
    244 
    245   return port_ < addr.port_;
    246 }
    247 
    248 bool SocketAddress::EqualIPs(const SocketAddress& addr) const {
    249   return (ip_ == addr.ip_) && ((ip_ != 0) || (hostname_ == addr.hostname_));
    250 }
    251 
    252 bool SocketAddress::EqualPorts(const SocketAddress& addr) const {
    253   return (port_ == addr.port_);
    254 }
    255 
    256 size_t SocketAddress::Hash() const {
    257   size_t h = 0;
    258   h ^= ip_;
    259   h ^= port_ | (port_ << 16);
    260   return h;
    261 }
    262 
    263 size_t SocketAddress::Size_() const {
    264   return sizeof(ip_) + sizeof(port_) + 2;
    265 }
    266 
    267 bool SocketAddress::Write_(char* buf, int len) const {
    268   if (len < static_cast<int>(Size_()))
    269     return false;
    270   buf[0] = 0;
    271   buf[1] = AF_INET;
    272   SetBE16(buf + 2, port_);
    273   SetBE32(buf + 4, ip_);
    274   return true;
    275 }
    276 
    277 bool SocketAddress::Read_(const char* buf, int len) {
    278   if (len < static_cast<int>(Size_()) || buf[1] != AF_INET)
    279     return false;
    280   port_ = GetBE16(buf + 2);
    281   ip_ = GetBE32(buf + 4);
    282   return true;
    283 }
    284 
    285 void SocketAddress::ToSockAddr(sockaddr_in* saddr) const {
    286   memset(saddr, 0, sizeof(*saddr));
    287   saddr->sin_family = AF_INET;
    288   saddr->sin_port = HostToNetwork16(port_);
    289   if (0 == ip_) {
    290     saddr->sin_addr.s_addr = INADDR_ANY;
    291   } else {
    292     saddr->sin_addr.s_addr = HostToNetwork32(ip_);
    293   }
    294 }
    295 
    296 bool SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
    297   if (saddr.sin_family != AF_INET)
    298     return false;
    299   SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
    300   SetPort(NetworkToHost16(saddr.sin_port));
    301   return true;
    302 }
    303 
    304 std::string SocketAddress::IPToString(uint32 ip) {
    305   std::ostringstream ost;
    306   ost << ((ip >> 24) & 0xff);
    307   ost << '.';
    308   ost << ((ip >> 16) & 0xff);
    309   ost << '.';
    310   ost << ((ip >> 8) & 0xff);
    311   ost << '.';
    312   ost << ((ip >> 0) & 0xff);
    313   return ost.str();
    314 }
    315 
    316 bool SocketAddress::StringToIP(const std::string& hostname, uint32* ip) {
    317   in_addr addr;
    318   if (inet_aton(hostname.c_str(), &addr) == 0)
    319     return false;
    320   *ip = NetworkToHost32(addr.s_addr);
    321   return true;
    322 }
    323 
    324 uint32 SocketAddress::StringToIP(const std::string& hostname) {
    325   uint32 ip = 0;
    326   StringToIP(hostname, &ip);
    327   return ip;
    328 }
    329 
    330 std::string SocketAddress::GetHostname() {
    331   char hostname[256];
    332   if (gethostname(hostname, ARRAY_SIZE(hostname)) == 0)
    333     return hostname;
    334   return "";
    335 }
    336 
    337 bool SocketAddress::GetLocalIPs(std::vector<uint32>& ips) {
    338   ips.clear();
    339 
    340   const std::string hostname = GetHostname();
    341   if (hostname.empty())
    342     return false;
    343 
    344   int errcode;
    345   if (hostent* pHost = SafeGetHostByName(hostname.c_str(), &errcode)) {
    346     for (size_t i = 0; pHost->h_addr_list[i]; ++i) {
    347       uint32 ip =
    348         NetworkToHost32(*reinterpret_cast<uint32 *>(pHost->h_addr_list[i]));
    349       ips.push_back(ip);
    350     }
    351     FreeHostEnt(pHost);
    352     return !ips.empty();
    353   }
    354   LOG(LS_ERROR) << "gethostbyname err: " << errcode;
    355   return false;
    356 }
    357 
    358 }  // namespace talk_base
    359