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