147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/socketaddress.h"
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sys/types.h>
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sys/socket.h>
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <netinet/in.h>
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(OPENBSD)
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <netinet/in_systm.h>
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if !defined(__native_client__)
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <netinet/ip.h>
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <arpa/inet.h>
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <netdb.h>
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <unistd.h>
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sstream>
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/byteorder.h"
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h"
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h"
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/nethelpers.h"
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/win32.h"
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress::SocketAddress() {
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Clear();
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress::SocketAddress(const std::string& hostname, int port) {
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetIP(hostname);
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetPort(port);
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress::SocketAddress(uint32 ip_as_host_order_integer, int port) {
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetIP(IPAddress(ip_as_host_order_integer));
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetPort(port);
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress::SocketAddress(const IPAddress& ip, int port) {
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetIP(ip);
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetPort(port);
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress::SocketAddress(const SocketAddress& addr) {
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  this->operator=(addr);
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SocketAddress::Clear() {
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  hostname_.clear();
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  literal_ = false;
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ip_ = IPAddress();
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  port_ = 0;
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scope_id_ = 0;
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::IsNil() const {
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return hostname_.empty() && IPIsUnspec(ip_) && 0 == port_;
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::IsComplete() const {
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (!IPIsAny(ip_)) && (0 != port_);
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  hostname_ = addr.hostname_;
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ip_ = addr.ip_;
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  port_ = addr.port_;
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  literal_ = addr.literal_;
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scope_id_ = addr.scope_id_;
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return *this;
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SocketAddress::SetIP(uint32 ip_as_host_order_integer) {
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  hostname_.clear();
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  literal_ = false;
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ip_ = IPAddress(ip_as_host_order_integer);
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scope_id_ = 0;
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SocketAddress::SetIP(const IPAddress& ip) {
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  hostname_.clear();
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  literal_ = false;
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ip_ = ip;
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scope_id_ = 0;
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SocketAddress::SetIP(const std::string& hostname) {
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  hostname_ = hostname;
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  literal_ = IPFromString(hostname, &ip_);
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!literal_) {
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ip_ = IPAddress();
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scope_id_ = 0;
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SocketAddress::SetResolvedIP(uint32 ip_as_host_order_integer) {
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ip_ = IPAddress(ip_as_host_order_integer);
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scope_id_ = 0;
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SocketAddress::SetResolvedIP(const IPAddress& ip) {
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ip_ = ip;
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  scope_id_ = 0;
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SocketAddress::SetPort(int port) {
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT((0 <= port) && (port < 65536));
124c2e6614c20710991cdbae41993e6c92d64dab9afhenrike@webrtc.org  port_ = static_cast<uint16>(port);
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orguint32 SocketAddress::ip() const {
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ip_.v4AddressAsHostOrderInteger();
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst IPAddress& SocketAddress::ipaddr() const {
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ip_;
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orguint16 SocketAddress::port() const {
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return port_;
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string SocketAddress::HostAsURIString() const {
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // If the hostname was a literal IP string, it may need to have square
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // brackets added (for SocketAddress::ToString()).
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!literal_ && !hostname_.empty())
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return hostname_;
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ip_.family() == AF_INET6) {
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return "[" + ip_.ToString() + "]";
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return ip_.ToString();
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string SocketAddress::HostAsSensitiveURIString() const {
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // If the hostname was a literal IP string, it may need to have square
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // brackets added (for SocketAddress::ToString()).
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!literal_ && !hostname_.empty())
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return hostname_;
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ip_.family() == AF_INET6) {
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return "[" + ip_.ToSensitiveString() + "]";
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return ip_.ToSensitiveString();
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string SocketAddress::PortAsString() const {
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::ostringstream ost;
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ost << port_;
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ost.str();
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string SocketAddress::ToString() const {
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::ostringstream ost;
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ost << *this;
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ost.str();
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string SocketAddress::ToSensitiveString() const {
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::ostringstream ost;
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ost << HostAsSensitiveURIString() << ":" << port();
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ost.str();
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::FromString(const std::string& str) {
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (str.at(0) == '[') {
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    std::string::size_type closebracket = str.rfind(']');
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (closebracket != std::string::npos) {
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      std::string::size_type colon = str.find(':', closebracket);
18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (colon != std::string::npos && colon > closebracket) {
18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        SetPort(strtoul(str.substr(colon + 1).c_str(), NULL, 10));
18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        SetIP(str.substr(1, closebracket - 1));
18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return false;
19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    std::string::size_type pos = str.find(':');
19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (std::string::npos == pos)
19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10));
19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    SetIP(str.substr(0, pos));
19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  os << addr.HostAsURIString() << ":" << addr.port();
20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return os;
20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::IsAnyIP() const {
20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return IPIsAny(ip_);
21047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::IsLoopbackIP() const {
21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return IPIsLoopback(ip_) || (IPIsAny(ip_) &&
21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                               0 == strcmp(hostname_.c_str(), "localhost"));
21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::IsPrivateIP() const {
21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return IPIsPrivate(ip_);
21947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
22047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::IsUnresolvedIP() const {
22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return IPIsUnspec(ip_) && !literal_ && !hostname_.empty();
22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::operator==(const SocketAddress& addr) const {
22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return EqualIPs(addr) && EqualPorts(addr);
22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::operator<(const SocketAddress& addr) const {
230c4b828d1b37c297978031b1a6871a03cc2522c3ahenrike@webrtc.org  if (ip_ != addr.ip_)
231c4b828d1b37c297978031b1a6871a03cc2522c3ahenrike@webrtc.org    return ip_ < addr.ip_;
23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
233c4b828d1b37c297978031b1a6871a03cc2522c3ahenrike@webrtc.org  // We only check hostnames if both IPs are ANY or unspecified.  This matches
234c4b828d1b37c297978031b1a6871a03cc2522c3ahenrike@webrtc.org  // EqualIPs().
235c4b828d1b37c297978031b1a6871a03cc2522c3ahenrike@webrtc.org  if ((IPIsAny(ip_) || IPIsUnspec(ip_)) && hostname_ != addr.hostname_)
236c4b828d1b37c297978031b1a6871a03cc2522c3ahenrike@webrtc.org    return hostname_ < addr.hostname_;
23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return port_ < addr.port_;
23947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::EqualIPs(const SocketAddress& addr) const {
24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (ip_ == addr.ip_) &&
243c4b828d1b37c297978031b1a6871a03cc2522c3ahenrike@webrtc.org      ((!IPIsAny(ip_) && !IPIsUnspec(ip_)) || (hostname_ == addr.hostname_));
24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::EqualPorts(const SocketAddress& addr) const {
24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return (port_ == addr.port_);
24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t SocketAddress::Hash() const {
25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t h = 0;
25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  h ^= HashIP(ip_);
25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  h ^= port_ | (port_ << 16);
25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return h;
25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SocketAddress::ToSockAddr(sockaddr_in* saddr) const {
25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  memset(saddr, 0, sizeof(*saddr));
25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ip_.family() != AF_INET) {
26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    saddr->sin_family = AF_UNSPEC;
26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  saddr->sin_family = AF_INET;
26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  saddr->sin_port = HostToNetwork16(port_);
26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (IPIsAny(ip_)) {
26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    saddr->sin_addr.s_addr = INADDR_ANY;
26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    saddr->sin_addr = ip_.ipv4_address();
26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (saddr.sin_family != AF_INET)
27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetPort(NetworkToHost16(saddr.sin_port));
27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  literal_ = false;
27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic size_t ToSockAddrStorageHelper(sockaddr_storage* addr,
282c2e6614c20710991cdbae41993e6c92d64dab9afhenrike@webrtc.org                                      IPAddress ip, uint16 port, int scope_id) {
28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  memset(addr, 0, sizeof(sockaddr_storage));
284c2e6614c20710991cdbae41993e6c92d64dab9afhenrike@webrtc.org  addr->ss_family = static_cast<unsigned short>(ip.family());
28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (addr->ss_family == AF_INET6) {
28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_in6* saddr = reinterpret_cast<sockaddr_in6*>(addr);
28747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    saddr->sin6_addr = ip.ipv6_address();
28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    saddr->sin6_port = HostToNetwork16(port);
28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    saddr->sin6_scope_id = scope_id;
29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return sizeof(sockaddr_in6);
29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (addr->ss_family == AF_INET) {
29247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sockaddr_in* saddr = reinterpret_cast<sockaddr_in*>(addr);
29347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    saddr->sin_addr = ip.ipv4_address();
29447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    saddr->sin_port = HostToNetwork16(port);
29547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return sizeof(sockaddr_in);
29647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
29747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return 0;
29847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
29947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t SocketAddress::ToDualStackSockAddrStorage(sockaddr_storage *addr) const {
30147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ToSockAddrStorageHelper(addr, ip_.AsIPv6Address(), port_, scope_id_);
30247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
30347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgsize_t SocketAddress::ToSockAddrStorage(sockaddr_storage* addr) const {
30547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ToSockAddrStorageHelper(addr, ip_, port_, scope_id_);
30647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
30747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
30847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string SocketAddress::IPToString(uint32 ip_as_host_order_integer) {
30947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return IPAddress(ip_as_host_order_integer).ToString();
31047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
31147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
31247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstd::string IPToSensitiveString(uint32 ip_as_host_order_integer) {
31347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return IPAddress(ip_as_host_order_integer).ToSensitiveString();
31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
31547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
31647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::StringToIP(const std::string& hostname, uint32* ip) {
31747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  in_addr addr;
31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (rtc::inet_pton(AF_INET, hostname.c_str(), &addr) == 0)
31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
32047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  *ip = NetworkToHost32(addr.s_addr);
32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddress::StringToIP(const std::string& hostname, IPAddress* ip) {
32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  in_addr addr4;
32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (rtc::inet_pton(AF_INET, hostname.c_str(), &addr4) > 0) {
32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ip) {
32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *ip = IPAddress(addr4);
32947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
33347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  in6_addr addr6;
33447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (rtc::inet_pton(AF_INET6, hostname.c_str(), &addr6) > 0) {
33547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (ip) {
33647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *ip = IPAddress(addr6);
33747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
33847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
33947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
34047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return false;
34147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
34247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
34347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orguint32 SocketAddress::StringToIP(const std::string& hostname) {
34447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint32 ip = 0;
34547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  StringToIP(hostname, &ip);
34647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ip;
34747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool SocketAddressFromSockAddrStorage(const sockaddr_storage& addr,
35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                      SocketAddress* out) {
35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!out) {
35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (addr.ss_family == AF_INET) {
35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const sockaddr_in* saddr = reinterpret_cast<const sockaddr_in*>(&addr);
35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *out = SocketAddress(IPAddress(saddr->sin_addr),
35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                         NetworkToHost16(saddr->sin_port));
35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (addr.ss_family == AF_INET6) {
36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    const sockaddr_in6* saddr = reinterpret_cast<const sockaddr_in6*>(&addr);
36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *out = SocketAddress(IPAddress(saddr->sin6_addr),
36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                         NetworkToHost16(saddr->sin6_port));
36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    out->SetScopeID(saddr->sin6_scope_id);
36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return false;
36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgSocketAddress EmptySocketAddressWithFamily(int family) {
37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (family == AF_INET) {
37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SocketAddress(IPAddress(INADDR_ANY), 0);
37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else if (family == AF_INET6) {
37347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return SocketAddress(IPAddress(in6addr_any), 0);
37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return SocketAddress();
37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
379