~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/base/socketaddress.cc

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
#include "talk/base/socketaddress.h"
 
29
 
 
30
#ifdef POSIX
 
31
#include <sys/types.h>
 
32
#include <sys/socket.h>
 
33
#include <netinet/in.h>
 
34
#if defined(OPENBSD)
 
35
#include <netinet/in_systm.h>
 
36
#endif
 
37
#include <netinet/ip.h>
 
38
#include <arpa/inet.h>
 
39
#include <netdb.h>
 
40
#include <unistd.h>
 
41
#endif
 
42
 
 
43
#include <sstream>
 
44
 
 
45
#include "talk/base/byteorder.h"
 
46
#include "talk/base/common.h"
 
47
#include "talk/base/logging.h"
 
48
#include "talk/base/nethelpers.h"
 
49
 
 
50
#ifdef WIN32
 
51
#include "talk/base/win32.h"
 
52
#endif
 
53
 
 
54
namespace talk_base {
 
55
 
 
56
// Address family constants for STUN (see RFC 5389).
 
57
static const int kStunFamilyIPv4 = 1;
 
58
static const int kStunFamilyIPv6 = 2;
 
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_as_host_order_integer, int port) {
 
70
  SetIP(IPAddress(ip_as_host_order_integer));
 
71
  SetPort(port);
 
72
}
 
73
 
 
74
SocketAddress::SocketAddress(const IPAddress& ip, int port) {
 
75
  SetIP(ip);
 
76
  SetPort(port);
 
77
}
 
78
 
 
79
SocketAddress::SocketAddress(const SocketAddress& addr) {
 
80
  this->operator=(addr);
 
81
}
 
82
 
 
83
void SocketAddress::Clear() {
 
84
  hostname_.clear();
 
85
  literal_ = false;
 
86
  ip_ = IPAddress(INADDR_ANY);
 
87
  port_ = 0;
 
88
}
 
89
 
 
90
bool SocketAddress::IsNil() const {
 
91
  return hostname_.empty() && IPIsAny(ip_) && 0 == port_;
 
92
}
 
93
 
 
94
bool SocketAddress::IsComplete() const {
 
95
  return (!IPIsAny(ip_)) && (0 != port_);
 
96
}
 
97
 
 
98
SocketAddress& SocketAddress::operator=(const SocketAddress& addr) {
 
99
  hostname_ = addr.hostname_;
 
100
  ip_ = addr.ip_;
 
101
  port_ = addr.port_;
 
102
  literal_ = addr.literal_;
 
103
  return *this;
 
104
}
 
105
 
 
106
void SocketAddress::SetIP(uint32 ip_as_host_order_integer) {
 
107
  hostname_.clear();
 
108
  literal_ = false;
 
109
  ip_ = IPAddress(ip_as_host_order_integer);
 
110
}
 
111
 
 
112
void SocketAddress::SetIP(const IPAddress& ip) {
 
113
  hostname_.clear();
 
114
  literal_ = false;
 
115
  ip_ = ip;
 
116
}
 
117
 
 
118
void SocketAddress::SetIP(const std::string& hostname) {
 
119
  hostname_ = hostname;
 
120
  literal_ = IPFromString(hostname, &ip_);
 
121
  if (!literal_) {
 
122
    ip_ = IPAddress(INADDR_ANY);
 
123
  }
 
124
}
 
125
 
 
126
void SocketAddress::SetResolvedIP(uint32 ip_as_host_order_integer) {
 
127
  ip_ = IPAddress(ip_as_host_order_integer);
 
128
}
 
129
 
 
130
void SocketAddress::SetResolvedIP(const IPAddress& ip) {
 
131
  ip_ = ip;
 
132
}
 
133
 
 
134
void SocketAddress::SetPort(int port) {
 
135
  ASSERT((0 <= port) && (port < 65536));
 
136
  port_ = port;
 
137
}
 
138
 
 
139
uint32 SocketAddress::ip() const {
 
140
  return ip_.v4AddressAsHostOrderInteger();
 
141
}
 
142
 
 
143
const IPAddress& SocketAddress::ipaddr() const {
 
144
  return ip_;
 
145
}
 
146
 
 
147
uint16 SocketAddress::port() const {
 
148
  return port_;
 
149
}
 
150
 
 
151
std::string SocketAddress::IPAsString() 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_.ToString() + "]";
 
158
  } else {
 
159
    return ip_.ToString();
 
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 << IPAsString();
 
172
  ost << ":";
 
173
  ost << port();
 
174
  return ost.str();
 
175
}
 
176
 
 
177
bool SocketAddress::FromString(const std::string& str) {
 
178
  if (str.at(0) == '[') {
 
179
    std::string::size_type closebracket = str.rfind(']');
 
180
    if (closebracket != std::string::npos) {
 
181
      std::string::size_type colon = str.find(':', closebracket);
 
182
      if (colon != std::string::npos && colon > closebracket) {
 
183
        SetPort(strtoul(str.substr(colon + 1).c_str(), NULL, 10));
 
184
        SetIP(str.substr(1, closebracket - 1));
 
185
      } else {
 
186
        return false;
 
187
      }
 
188
    }
 
189
  } else {
 
190
    std::string::size_type pos = str.find(':');
 
191
    if (std::string::npos == pos)
 
192
      return false;
 
193
    SetPort(strtoul(str.substr(pos + 1).c_str(), NULL, 10));
 
194
    SetIP(str.substr(0, pos));
 
195
  }
 
196
  return true;
 
197
}
 
198
 
 
199
std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
 
200
  os << addr.IPAsString() << ":" << addr.port();
 
201
  return os;
 
202
}
 
203
 
 
204
bool SocketAddress::IsAnyIP() const {
 
205
  return IPIsAny(ip_);
 
206
}
 
207
 
 
208
bool SocketAddress::IsLoopbackIP() const {
 
209
  return IPIsLoopback(ip_) || (IPIsAny(ip_) &&
 
210
                               0 == strcmp(hostname_.c_str(), "localhost"));
 
211
}
 
212
 
 
213
bool SocketAddress::IsLocalIP() const {
 
214
  if (IsLoopbackIP())
 
215
    return true;
 
216
 
 
217
  std::vector<IPAddress> ips;
 
218
  if (IPIsAny(ip_)) {
 
219
    if (!hostname_.empty()
 
220
        && (0 == stricmp(hostname_.c_str(), GetHostname().c_str()))) {
 
221
      return true;
 
222
    }
 
223
  } else if (GetLocalIPs(&ips)) {
 
224
    for (size_t i = 0; i < ips.size(); ++i) {
 
225
      if (ips[i] == ip_) {
 
226
        return true;
 
227
      }
 
228
    }
 
229
  }
 
230
  return false;
 
231
}
 
232
 
 
233
bool SocketAddress::IsPrivateIP() const {
 
234
  return IPIsPrivate(ip_);
 
235
}
 
236
 
 
237
bool SocketAddress::IsUnresolvedIP() const {
 
238
  return IsAny() && !literal_ && !hostname_.empty();
 
239
}
 
240
 
 
241
bool SocketAddress::ResolveIP(bool force, int* error) {
 
242
  if (hostname_.empty()) {
 
243
    // nothing to resolve
 
244
  } else if (!force && !IsAny()) {
 
245
    // already resolved
 
246
  } else {
 
247
    LOG_F(LS_VERBOSE) << "(" << hostname_ << ")";
 
248
    int errcode = 0;
 
249
    if (hostent* pHost = SafeGetHostByName(hostname_.c_str(), &errcode)) {
 
250
      if (IPFromHostEnt(pHost, &ip_)) {
 
251
        LOG_F(LS_VERBOSE) << "(" << hostname_ << ") resolved to: "
 
252
                          << ip_.ToString();
 
253
      }
 
254
      FreeHostEnt(pHost);
 
255
    } else {
 
256
      LOG_F(LS_ERROR) << "(" << hostname_ << ") err: " << errcode;
 
257
    }
 
258
    if (error) {
 
259
      *error = errcode;
 
260
    }
 
261
  }
 
262
  return (!IPIsAny(ip_));
 
263
}
 
264
 
 
265
bool SocketAddress::operator==(const SocketAddress& addr) const {
 
266
  return EqualIPs(addr) && EqualPorts(addr);
 
267
}
 
268
 
 
269
bool SocketAddress::operator<(const SocketAddress& addr) const {
 
270
  if (ip_ < addr.ip_)
 
271
    return true;
 
272
  else if (addr.ip_ < ip_)
 
273
    return false;
 
274
 
 
275
  // We only check hostnames if both IPs are zero.  This matches EqualIPs()
 
276
  if (addr.IsAnyIP()) {
 
277
    if (hostname_ < addr.hostname_)
 
278
      return true;
 
279
    else if (addr.hostname_ < hostname_)
 
280
      return false;
 
281
  }
 
282
 
 
283
  return port_ < addr.port_;
 
284
}
 
285
 
 
286
bool SocketAddress::EqualIPs(const SocketAddress& addr) const {
 
287
  return (ip_ == addr.ip_) &&
 
288
      ((!IPIsAny(ip_)) || (hostname_ == addr.hostname_));
 
289
}
 
290
 
 
291
bool SocketAddress::EqualPorts(const SocketAddress& addr) const {
 
292
  return (port_ == addr.port_);
 
293
}
 
294
 
 
295
size_t SocketAddress::Hash() const {
 
296
  size_t h = 0;
 
297
  h ^= HashIP(ip_);
 
298
  h ^= port_ | (port_ << 16);
 
299
  return h;
 
300
}
 
301
 
 
302
void SocketAddress::ToSockAddr(sockaddr_in* saddr) const {
 
303
  memset(saddr, 0, sizeof(*saddr));
 
304
  if (ip_.family() != AF_INET) {
 
305
    saddr->sin_family = AF_UNSPEC;
 
306
    return;
 
307
  }
 
308
  saddr->sin_family = AF_INET;
 
309
  saddr->sin_port = HostToNetwork16(port_);
 
310
  if (IPIsAny(ip_)) {
 
311
    saddr->sin_addr.s_addr = INADDR_ANY;
 
312
  } else {
 
313
    saddr->sin_addr = ip_.ipv4_address();
 
314
  }
 
315
}
 
316
 
 
317
bool SocketAddress::FromSockAddr(const sockaddr_in& saddr) {
 
318
  if (saddr.sin_family != AF_INET)
 
319
    return false;
 
320
  SetIP(NetworkToHost32(saddr.sin_addr.s_addr));
 
321
  SetPort(NetworkToHost16(saddr.sin_port));
 
322
  literal_ = false;
 
323
  return true;
 
324
}
 
325
 
 
326
static size_t ToSockAddrStorageHelper(sockaddr_storage* addr,
 
327
                                      IPAddress ip, int port, int scope_id) {
 
328
  memset(addr, 0, sizeof(sockaddr_storage));
 
329
  addr->ss_family = ip.family();
 
330
  if (addr->ss_family == AF_INET6) {
 
331
    sockaddr_in6* saddr = reinterpret_cast<sockaddr_in6*>(addr);
 
332
    saddr->sin6_addr = ip.ipv6_address();
 
333
    saddr->sin6_port = HostToNetwork16(port);
 
334
    saddr->sin6_scope_id = scope_id;
 
335
    return sizeof(sockaddr_in6);
 
336
  } else if (addr->ss_family == AF_INET) {
 
337
    sockaddr_in* saddr = reinterpret_cast<sockaddr_in*>(addr);
 
338
    saddr->sin_addr = ip.ipv4_address();
 
339
    saddr->sin_port = HostToNetwork16(port);
 
340
    return sizeof(sockaddr_in);
 
341
  }
 
342
  return 0;
 
343
}
 
344
 
 
345
size_t SocketAddress::ToDualStackSockAddrStorage(sockaddr_storage *addr) const {
 
346
  return ToSockAddrStorageHelper(addr, ip_.AsIPv6Address(), port_, scope_id_);
 
347
}
 
348
 
 
349
size_t SocketAddress::ToSockAddrStorage(sockaddr_storage* addr) const {
 
350
  return ToSockAddrStorageHelper(addr, ip_, port_, scope_id_);
 
351
}
 
352
 
 
353
std::string SocketAddress::IPToString(uint32 ip_as_host_order_integer) {
 
354
  std::ostringstream ost;
 
355
  ost << ((ip_as_host_order_integer >> 24) & 0xff);
 
356
  ost << '.';
 
357
  ost << ((ip_as_host_order_integer >> 16) & 0xff);
 
358
  ost << '.';
 
359
  ost << ((ip_as_host_order_integer >> 8) & 0xff);
 
360
  ost << '.';
 
361
  ost << ((ip_as_host_order_integer >> 0) & 0xff);
 
362
  return ost.str();
 
363
}
 
364
 
 
365
bool SocketAddress::StringToIP(const std::string& hostname, uint32* ip) {
 
366
  in_addr addr;
 
367
  if (talk_base::inet_pton(AF_INET, hostname.c_str(), &addr) == 0)
 
368
    return false;
 
369
  *ip = NetworkToHost32(addr.s_addr);
 
370
  return true;
 
371
}
 
372
 
 
373
bool SocketAddress::StringToIP(const std::string& hostname, IPAddress* ip) {
 
374
  in_addr addr4;
 
375
  if (talk_base::inet_pton(AF_INET, hostname.c_str(), &addr4) > 0) {
 
376
    if (ip) {
 
377
      *ip = IPAddress(addr4);
 
378
    }
 
379
    return true;
 
380
  }
 
381
 
 
382
  in6_addr addr6;
 
383
  if (talk_base::inet_pton(AF_INET6, hostname.c_str(), &addr6) > 0) {
 
384
    if (ip) {
 
385
      *ip = IPAddress(addr6);
 
386
    }
 
387
    return true;
 
388
  }
 
389
  return false;
 
390
}
 
391
 
 
392
uint32 SocketAddress::StringToIP(const std::string& hostname) {
 
393
  uint32 ip = 0;
 
394
  StringToIP(hostname, &ip);
 
395
  return ip;
 
396
}
 
397
 
 
398
std::string SocketAddress::GetHostname() {
 
399
  char hostname[256];
 
400
  if (gethostname(hostname, ARRAY_SIZE(hostname)) == 0)
 
401
    return hostname;
 
402
  return "";
 
403
}
 
404
 
 
405
bool SocketAddress::GetLocalIPs(std::vector<IPAddress>* ips) {
 
406
  if (!ips) {
 
407
    return false;
 
408
  }
 
409
  ips->clear();
 
410
 
 
411
  const std::string hostname = SocketAddress::GetHostname();
 
412
  if (hostname.empty())
 
413
    return false;
 
414
 
 
415
  int errcode;
 
416
  if (hostent* pHost = SafeGetHostByName(hostname.c_str(), &errcode)) {
 
417
    for (int i = 0; pHost->h_addr_list[i]; ++i) {
 
418
      IPAddress ip;
 
419
      if (IPFromHostEnt(pHost, i, &ip)) {
 
420
        ips->push_back(ip);
 
421
      }
 
422
    }
 
423
    FreeHostEnt(pHost);
 
424
    return !ips->empty();
 
425
  }
 
426
  LOG(LS_ERROR) << "gethostbyname err: " << errcode;
 
427
  return false;
 
428
}
 
429
 
 
430
bool SocketAddressFromSockAddrStorage(const sockaddr_storage& addr,
 
431
                                      SocketAddress* out) {
 
432
  if (!out) {
 
433
    return false;
 
434
  }
 
435
  if (addr.ss_family == AF_INET) {
 
436
    const sockaddr_in* saddr = reinterpret_cast<const sockaddr_in*>(&addr);
 
437
    *out = SocketAddress(IPAddress(saddr->sin_addr),
 
438
                         NetworkToHost16(saddr->sin_port));
 
439
    return true;
 
440
  } else if (addr.ss_family == AF_INET6) {
 
441
    const sockaddr_in6* saddr = reinterpret_cast<const sockaddr_in6*>(&addr);
 
442
    *out = SocketAddress(IPAddress(saddr->sin6_addr),
 
443
                         NetworkToHost16(saddr->sin6_port));
 
444
    out->SetScopeID(saddr->sin6_scope_id);
 
445
    return true;
 
446
  }
 
447
  return false;
 
448
}
 
449
}  // namespace talk_base