Home | History | Annotate | Download | only in base
      1 /*
      2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/base/socketaddress.h"
     12 
     13 #if defined(WEBRTC_POSIX)
     14 #include <sys/types.h>
     15 #include <sys/socket.h>
     16 #include <netinet/in.h>
     17 #if defined(OPENBSD)
     18 #include <netinet/in_systm.h>
     19 #endif
     20 #if !defined(__native_client__)
     21 #include <netinet/ip.h>
     22 #endif
     23 #include <arpa/inet.h>
     24 #include <netdb.h>
     25 #include <unistd.h>
     26 #endif
     27 
     28 #include <sstream>
     29 
     30 #include "webrtc/base/byteorder.h"
     31 #include "webrtc/base/common.h"
     32 #include "webrtc/base/logging.h"
     33 #include "webrtc/base/nethelpers.h"
     34 
     35 #if defined(WEBRTC_WIN)
     36 #include "webrtc/base/win32.h"
     37 #endif
     38 
     39 namespace rtc {
     40 
     41 SocketAddress::SocketAddress() {
     42   Clear();
     43 }
     44 
     45 SocketAddress::SocketAddress(const std::string& hostname, int port) {
     46   SetIP(hostname);
     47   SetPort(port);
     48 }
     49 
     50 SocketAddress::SocketAddress(uint32_t ip_as_host_order_integer, int port) {
     51   SetIP(IPAddress(ip_as_host_order_integer));
     52   SetPort(port);
     53 }
     54 
     55 SocketAddress::SocketAddress(const IPAddress& ip, int port) {
     56   SetIP(ip);
     57   SetPort(port);
     58 }
     59 
     60 SocketAddress::SocketAddress(const SocketAddress& addr) {
     61   this->operator=(addr);
     62 }
     63 
     64 void SocketAddress::Clear() {
     65   hostname_.clear();
     66   literal_ = false;
     67   ip_ = IPAddress();
     68   port_ = 0;
     69   scope_id_ = 0;
     70 }
     71 
     72 bool SocketAddress::IsNil() const {
     73   return hostname_.empty() && IPIsUnspec(ip_) && 0 == port_;
     74 }
     75 
     76 bool SocketAddress::IsComplete() const {
     77   return (!IPIsAny(ip_)) && (0 != port_);
     78 }
     79 
     80 SocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
     81   hostname_ = addr.hostname_;
     82   ip_ = addr.ip_;
     83   port_ = addr.port_;
     84   literal_ = addr.literal_;
     85   scope_id_ = addr.scope_id_;
     86   return *this;
     87 }
     88 
     89 void SocketAddress::SetIP(uint32_t ip_as_host_order_integer) {
     90   hostname_.clear();
     91   literal_ = false;
     92   ip_ = IPAddress(ip_as_host_order_integer);
     93   scope_id_ = 0;
     94 }
     95 
     96 void SocketAddress::SetIP(const IPAddress& ip) {
     97   hostname_.clear();
     98   literal_ = false;
     99   ip_ = ip;
    100   scope_id_ = 0;
    101 }
    102 
    103 void SocketAddress::SetIP(const std::string& hostname) {
    104   hostname_ = hostname;
    105   literal_ = IPFromString(hostname, &ip_);
    106   if (!literal_) {
    107     ip_ = IPAddress();
    108   }
    109   scope_id_ = 0;
    110 }
    111 
    112 void SocketAddress::SetResolvedIP(uint32_t ip_as_host_order_integer) {
    113   ip_ = IPAddress(ip_as_host_order_integer);
    114   scope_id_ = 0;
    115 }
    116 
    117 void SocketAddress::SetResolvedIP(const IPAddress& ip) {
    118   ip_ = ip;
    119   scope_id_ = 0;
    120 }
    121 
    122 void SocketAddress::SetPort(int port) {
    123   ASSERT((0 <= port) && (port < 65536));
    124   port_ = static_cast<uint16_t>(port);
    125 }
    126 
    127 uint32_t SocketAddress::ip() const {
    128   return ip_.v4AddressAsHostOrderInteger();
    129 }
    130 
    131 const IPAddress& SocketAddress::ipaddr() const {
    132   return ip_;
    133 }
    134 
    135 uint16_t SocketAddress::port() const {
    136   return port_;
    137 }
    138 
    139 std::string SocketAddress::HostAsURIString() const {
    140   // If the hostname was a literal IP string, it may need to have square
    141   // brackets added (for SocketAddress::ToString()).
    142   if (!literal_ && !hostname_.empty())
    143     return hostname_;
    144   if (ip_.family() == AF_INET6) {
    145     return "[" + ip_.ToString() + "]";
    146   } else {
    147     return ip_.ToString();
    148   }
    149 }
    150 
    151 std::string SocketAddress::HostAsSensitiveURIString() const {
    152   // If the hostname was a literal IP string, it may need to have square
    153   // brackets added (for SocketAddress::ToString()).
    154   if (!literal_ && !hostname_.empty())
    155     return hostname_;
    156   if (ip_.family() == AF_INET6) {
    157     return "[" + ip_.ToSensitiveString() + "]";
    158   } else {
    159     return ip_.ToSensitiveString();
    160   }
    161 }
    162 
    163 std::string SocketAddress::PortAsString() const {
    164   std::ostringstream ost;
    165   ost << port_;
    166   return ost.str();
    167 }
    168 
    169 std::string SocketAddress::ToString() const {
    170   std::ostringstream ost;
    171   ost << *this;
    172   return ost.str();
    173 }
    174 
    175 std::string SocketAddress::ToSensitiveString() const {
    176   std::ostringstream ost;
    177   ost << HostAsSensitiveURIString() << ":" << port();
    178   return ost.str();
    179 }
    180 
    181 bool SocketAddress::FromString(const std::string& str) {
    182   if (str.at(0) == '[') {
    183     std::string::size_type closebracket = str.rfind(']');
    184     if (closebracket != std::string::npos) {
    185       std::string::size_type colon = str.find(':', closebracket);
    186       if (colon != std::string::npos && colon > closebracket) {
    187         SetPort(strtoul(str.substr(colon + 1).c_str(), NULL, 10));
    188         SetIP(str.substr(1, closebracket - 1));
    189       } else {
    190         return false;
    191       }
    192     }
    193   } else {
    194     std::string::size_type pos = str.find(':');
    195     if (std::string::npos == pos)
    196       return false;
    197     SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10));
    198     SetIP(str.substr(0, pos));
    199   }
    200   return true;
    201 }
    202 
    203 std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
    204   os << addr.HostAsURIString() << ":" << addr.port();
    205   return os;
    206 }
    207 
    208 bool SocketAddress::IsAnyIP() const {
    209   return IPIsAny(ip_);
    210 }
    211 
    212 bool SocketAddress::IsLoopbackIP() const {
    213   return IPIsLoopback(ip_) || (IPIsAny(ip_) &&
    214                                0 == strcmp(hostname_.c_str(), "localhost"));
    215 }
    216 
    217 bool SocketAddress::IsPrivateIP() const {
    218   return IPIsPrivate(ip_);
    219 }
    220 
    221 bool SocketAddress::IsUnresolvedIP() const {
    222   return IPIsUnspec(ip_) && !literal_ && !hostname_.empty();
    223 }
    224 
    225 bool SocketAddress::operator==(const SocketAddress& addr) const {
    226   return EqualIPs(addr) && EqualPorts(addr);
    227 }
    228 
    229 bool SocketAddress::operator<(const SocketAddress& addr) const {
    230   if (ip_ != addr.ip_)
    231     return ip_ < addr.ip_;
    232 
    233   // We only check hostnames if both IPs are ANY or unspecified.  This matches
    234   // EqualIPs().
    235   if ((IPIsAny(ip_) || IPIsUnspec(ip_)) && hostname_ != addr.hostname_)
    236     return hostname_ < addr.hostname_;
    237 
    238   return port_ < addr.port_;
    239 }
    240 
    241 bool SocketAddress::EqualIPs(const SocketAddress& addr) const {
    242   return (ip_ == addr.ip_) &&
    243       ((!IPIsAny(ip_) && !IPIsUnspec(ip_)) || (hostname_ == addr.hostname_));
    244 }
    245 
    246 bool SocketAddress::EqualPorts(const SocketAddress& addr) const {
    247   return (port_ == addr.port_);
    248 }
    249 
    250 size_t SocketAddress::Hash() const {
    251   size_t h = 0;
    252   h ^= HashIP(ip_);
    253   h ^= port_ | (port_ << 16);
    254   return h;
    255 }
    256 
    257 void SocketAddress::ToSockAddr(sockaddr_in* saddr) const {
    258   memset(saddr, 0, sizeof(*saddr));
    259   if (ip_.family() != AF_INET) {
    260     saddr->sin_family = AF_UNSPEC;
    261     return;
    262   }
    263   saddr->sin_family = AF_INET;
    264   saddr->sin_port = HostToNetwork16(port_);
    265   if (IPIsAny(ip_)) {
    266     saddr->sin_addr.s_addr = INADDR_ANY;
    267   } else {
    268     saddr->sin_addr = ip_.ipv4_address();
    269   }
    270 }
    271 
    272 bool SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
    273   if (saddr.sin_family != AF_INET)
    274     return false;
    275   SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
    276   SetPort(NetworkToHost16(saddr.sin_port));
    277   literal_ = false;
    278   return true;
    279 }
    280 
    281 static size_t ToSockAddrStorageHelper(sockaddr_storage* addr,
    282                                       IPAddress ip,
    283                                       uint16_t port,
    284                                       int scope_id) {
    285   memset(addr, 0, sizeof(sockaddr_storage));
    286   addr->ss_family = static_cast<unsigned short>(ip.family());
    287   if (addr->ss_family == AF_INET6) {
    288     sockaddr_in6* saddr = reinterpret_cast<sockaddr_in6*>(addr);
    289     saddr->sin6_addr = ip.ipv6_address();
    290     saddr->sin6_port = HostToNetwork16(port);
    291     saddr->sin6_scope_id = scope_id;
    292     return sizeof(sockaddr_in6);
    293   } else if (addr->ss_family == AF_INET) {
    294     sockaddr_in* saddr = reinterpret_cast<sockaddr_in*>(addr);
    295     saddr->sin_addr = ip.ipv4_address();
    296     saddr->sin_port = HostToNetwork16(port);
    297     return sizeof(sockaddr_in);
    298   }
    299   return 0;
    300 }
    301 
    302 size_t SocketAddress::ToDualStackSockAddrStorage(sockaddr_storage *addr) const {
    303   return ToSockAddrStorageHelper(addr, ip_.AsIPv6Address(), port_, scope_id_);
    304 }
    305 
    306 size_t SocketAddress::ToSockAddrStorage(sockaddr_storage* addr) const {
    307   return ToSockAddrStorageHelper(addr, ip_, port_, scope_id_);
    308 }
    309 
    310 bool SocketAddressFromSockAddrStorage(const sockaddr_storage& addr,
    311                                       SocketAddress* out) {
    312   if (!out) {
    313     return false;
    314   }
    315   if (addr.ss_family == AF_INET) {
    316     const sockaddr_in* saddr = reinterpret_cast<const sockaddr_in*>(&addr);
    317     *out = SocketAddress(IPAddress(saddr->sin_addr),
    318                          NetworkToHost16(saddr->sin_port));
    319     return true;
    320   } else if (addr.ss_family == AF_INET6) {
    321     const sockaddr_in6* saddr = reinterpret_cast<const sockaddr_in6*>(&addr);
    322     *out = SocketAddress(IPAddress(saddr->sin6_addr),
    323                          NetworkToHost16(saddr->sin6_port));
    324     out->SetScopeID(saddr->sin6_scope_id);
    325     return true;
    326   }
    327   return false;
    328 }
    329 
    330 SocketAddress EmptySocketAddressWithFamily(int family) {
    331   if (family == AF_INET) {
    332     return SocketAddress(IPAddress(INADDR_ANY), 0);
    333   } else if (family == AF_INET6) {
    334     return SocketAddress(IPAddress(in6addr_any), 0);
    335   }
    336   return SocketAddress();
    337 }
    338 
    339 }  // namespace rtc
    340