~ubuntu-branches/ubuntu/trusty/miro/trusty

« back to all changes in this revision

Viewing changes to portable/libtorrent/include/libtorrent/asio/ip/address_v6.hpp

  • Committer: Daniel Hahler
  • Date: 2010-04-13 18:51:35 UTC
  • mfrom: (1.2.10 upstream)
  • Revision ID: ubuntu-launchpad@thequod.de-20100413185135-xi24v1diqg8w406x
Merging shared upstream rev into target branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
// address_v6.hpp
3
 
// ~~~~~~~~~~~~~~
4
 
//
5
 
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6
 
//
7
 
// Distributed under the Boost Software License, Version 1.0. (See accompanying
8
 
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
 
//
10
 
 
11
 
#ifndef ASIO_IP_ADDRESS_V6_HPP
12
 
#define ASIO_IP_ADDRESS_V6_HPP
13
 
 
14
 
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15
 
# pragma once
16
 
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
 
 
18
 
#include "asio/detail/push_options.hpp"
19
 
 
20
 
#include "asio/detail/push_options.hpp"
21
 
#include <cstring>
22
 
#include <string>
23
 
#include <stdexcept>
24
 
#include <typeinfo>
25
 
#include <boost/array.hpp>
26
 
#include <boost/throw_exception.hpp>
27
 
#include "asio/detail/pop_options.hpp"
28
 
 
29
 
#include "asio/error.hpp"
30
 
#include "asio/detail/socket_ops.hpp"
31
 
#include "asio/detail/socket_types.hpp"
32
 
#include "asio/detail/throw_error.hpp"
33
 
#include "asio/ip/address_v4.hpp"
34
 
 
35
 
namespace asio {
36
 
namespace ip {
37
 
 
38
 
/// Implements IP version 6 style addresses.
39
 
/**
40
 
 * The asio::ip::address_v6 class provides the ability to use and
41
 
 * manipulate IP version 6 addresses.
42
 
 *
43
 
 * @par Thread Safety
44
 
 * @e Distinct @e objects: Safe.@n
45
 
 * @e Shared @e objects: Unsafe.
46
 
 */
47
 
class address_v6
48
 
{
49
 
public:
50
 
  /// The type used to represent an address as an array of bytes.
51
 
  typedef boost::array<unsigned char, 16> bytes_type;
52
 
 
53
 
  /// Default constructor.
54
 
  address_v6()
55
 
    : scope_id_(0)
56
 
  {
57
 
    asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
58
 
    addr_ = tmp_addr;
59
 
  }
60
 
 
61
 
  /// Construct an address from raw bytes and scope ID.
62
 
  explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0)
63
 
    : scope_id_(scope_id)
64
 
  {
65
 
    using namespace std; // For memcpy.
66
 
    memcpy(addr_.s6_addr, bytes.elems, 16);
67
 
  }
68
 
 
69
 
  /// Copy constructor.
70
 
  address_v6(const address_v6& other)
71
 
    : addr_(other.addr_),
72
 
      scope_id_(other.scope_id_)
73
 
  {
74
 
  }
75
 
 
76
 
  /// Assign from another address.
77
 
  address_v6& operator=(const address_v6& other)
78
 
  {
79
 
    addr_ = other.addr_;
80
 
    scope_id_ = other.scope_id_;
81
 
    return *this;
82
 
  }
83
 
 
84
 
  /// The scope ID of the address.
85
 
  /**
86
 
   * Returns the scope ID associated with the IPv6 address.
87
 
   */
88
 
  unsigned long scope_id() const
89
 
  {
90
 
    return scope_id_;
91
 
  }
92
 
 
93
 
  /// The scope ID of the address.
94
 
  /**
95
 
   * Modifies the scope ID associated with the IPv6 address.
96
 
   */
97
 
  void scope_id(unsigned long id)
98
 
  {
99
 
    scope_id_ = id;
100
 
  }
101
 
 
102
 
  /// Get the address in bytes.
103
 
  bytes_type to_bytes() const
104
 
  {
105
 
    using namespace std; // For memcpy.
106
 
    bytes_type bytes;
107
 
    memcpy(bytes.elems, addr_.s6_addr, 16);
108
 
    return bytes;
109
 
  }
110
 
 
111
 
  /// Get the address as a string.
112
 
  std::string to_string() const
113
 
  {
114
 
    asio::error_code ec;
115
 
    std::string addr = to_string(ec);
116
 
    asio::detail::throw_error(ec);
117
 
    return addr;
118
 
  }
119
 
 
120
 
  /// Get the address as a string.
121
 
  std::string to_string(asio::error_code& ec) const
122
 
  {
123
 
    char addr_str[asio::detail::max_addr_v6_str_len];
124
 
    const char* addr =
125
 
      asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str,
126
 
          asio::detail::max_addr_v6_str_len, scope_id_, ec);
127
 
    if (addr == 0)
128
 
      return std::string();
129
 
    return addr;
130
 
  }
131
 
 
132
 
  /// Create an address from an IP address string.
133
 
  static address_v6 from_string(const char* str)
134
 
  {
135
 
    asio::error_code ec;
136
 
    address_v6 addr = from_string(str, ec);
137
 
    asio::detail::throw_error(ec);
138
 
    return addr;
139
 
  }
140
 
 
141
 
  /// Create an address from an IP address string.
142
 
  static address_v6 from_string(const char* str, asio::error_code& ec)
143
 
  {
144
 
    address_v6 tmp;
145
 
    if (asio::detail::socket_ops::inet_pton(
146
 
          AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0)
147
 
      return address_v6();
148
 
    return tmp;
149
 
  }
150
 
 
151
 
  /// Create an address from an IP address string.
152
 
  static address_v6 from_string(const std::string& str)
153
 
  {
154
 
    return from_string(str.c_str());
155
 
  }
156
 
 
157
 
  /// Create an address from an IP address string.
158
 
  static address_v6 from_string(const std::string& str,
159
 
      asio::error_code& ec)
160
 
  {
161
 
    return from_string(str.c_str(), ec);
162
 
  }
163
 
 
164
 
  /// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address.
165
 
  address_v4 to_v4() const
166
 
  {
167
 
    if (!is_v4_mapped() && !is_v4_compatible())
168
 
      throw std::bad_cast();
169
 
    address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],
170
 
      addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
171
 
    return address_v4(v4_bytes);
172
 
  }
173
 
 
174
 
  /// Determine whether the address is a loopback address.
175
 
  bool is_loopback() const
176
 
  {
177
 
#if defined(__BORLANDC__)
178
 
    return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
179
 
        && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
180
 
        && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
181
 
        && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
182
 
        && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
183
 
        && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
184
 
        && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
185
 
        && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1));
186
 
#else
187
 
    using namespace asio::detail;
188
 
    return IN6_IS_ADDR_LOOPBACK(&addr_) != 0;
189
 
#endif
190
 
  }
191
 
 
192
 
  /// Determine whether the address is unspecified.
193
 
  bool is_unspecified() const
194
 
  {
195
 
#if defined(__BORLANDC__)
196
 
    return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
197
 
        && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
198
 
        && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
199
 
        && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
200
 
        && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
201
 
        && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
202
 
        && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
203
 
        && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0));
204
 
#else
205
 
    using namespace asio::detail;
206
 
    return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0;
207
 
#endif
208
 
  }
209
 
 
210
 
  /// Determine whether the address is link local.
211
 
  bool is_link_local() const
212
 
  {
213
 
    using namespace asio::detail;
214
 
    return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0;
215
 
  }
216
 
 
217
 
  /// Determine whether the address is site local.
218
 
  bool is_site_local() const
219
 
  {
220
 
    using namespace asio::detail;
221
 
    return IN6_IS_ADDR_SITELOCAL(&addr_) != 0;
222
 
  }
223
 
 
224
 
  /// Determine whether the address is a mapped IPv4 address.
225
 
  bool is_v4_mapped() const
226
 
  {
227
 
    using namespace asio::detail;
228
 
    return IN6_IS_ADDR_V4MAPPED(&addr_) != 0;
229
 
  }
230
 
 
231
 
  /// Determine whether the address is an IPv4-compatible address.
232
 
  bool is_v4_compatible() const
233
 
  {
234
 
    using namespace asio::detail;
235
 
    return IN6_IS_ADDR_V4COMPAT(&addr_) != 0;
236
 
  }
237
 
 
238
 
  /// Determine whether the address is a multicast address.
239
 
  bool is_multicast() const
240
 
  {
241
 
    using namespace asio::detail;
242
 
    return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
243
 
  }
244
 
 
245
 
  /// Determine whether the address is a global multicast address.
246
 
  bool is_multicast_global() const
247
 
  {
248
 
    using namespace asio::detail;
249
 
    return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0;
250
 
  }
251
 
 
252
 
  /// Determine whether the address is a link-local multicast address.
253
 
  bool is_multicast_link_local() const
254
 
  {
255
 
    using namespace asio::detail;
256
 
    return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0;
257
 
  }
258
 
 
259
 
  /// Determine whether the address is a node-local multicast address.
260
 
  bool is_multicast_node_local() const
261
 
  {
262
 
    using namespace asio::detail;
263
 
    return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0;
264
 
  }
265
 
 
266
 
  /// Determine whether the address is a org-local multicast address.
267
 
  bool is_multicast_org_local() const
268
 
  {
269
 
    using namespace asio::detail;
270
 
    return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0;
271
 
  }
272
 
 
273
 
  /// Determine whether the address is a site-local multicast address.
274
 
  bool is_multicast_site_local() const
275
 
  {
276
 
    using namespace asio::detail;
277
 
    return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0;
278
 
  }
279
 
 
280
 
  /// Compare two addresses for equality.
281
 
  friend bool operator==(const address_v6& a1, const address_v6& a2)
282
 
  {
283
 
    using namespace std; // For memcmp.
284
 
    return memcmp(&a1.addr_, &a2.addr_,
285
 
        sizeof(asio::detail::in6_addr_type)) == 0
286
 
      && a1.scope_id_ == a2.scope_id_;
287
 
  }
288
 
 
289
 
  /// Compare two addresses for inequality.
290
 
  friend bool operator!=(const address_v6& a1, const address_v6& a2)
291
 
  {
292
 
    using namespace std; // For memcmp.
293
 
    return memcmp(&a1.addr_, &a2.addr_,
294
 
        sizeof(asio::detail::in6_addr_type)) != 0
295
 
      || a1.scope_id_ != a2.scope_id_;
296
 
  }
297
 
 
298
 
  /// Compare addresses for ordering.
299
 
  friend bool operator<(const address_v6& a1, const address_v6& a2)
300
 
  {
301
 
    using namespace std; // For memcmp.
302
 
    int memcmp_result = memcmp(&a1.addr_, &a2.addr_,
303
 
        sizeof(asio::detail::in6_addr_type));
304
 
    if (memcmp_result < 0)
305
 
      return true;
306
 
    if (memcmp_result > 0)
307
 
      return false;
308
 
    return a1.scope_id_ < a2.scope_id_;
309
 
  }
310
 
 
311
 
  /// Compare addresses for ordering.
312
 
  friend bool operator>(const address_v6& a1, const address_v6& a2)
313
 
  {
314
 
    return a2 < a1;
315
 
  }
316
 
 
317
 
  /// Compare addresses for ordering.
318
 
  friend bool operator<=(const address_v6& a1, const address_v6& a2)
319
 
  {
320
 
    return !(a2 < a1);
321
 
  }
322
 
 
323
 
  /// Compare addresses for ordering.
324
 
  friend bool operator>=(const address_v6& a1, const address_v6& a2)
325
 
  {
326
 
    return !(a1 < a2);
327
 
  }
328
 
 
329
 
  /// Obtain an address object that represents any address.
330
 
  static address_v6 any()
331
 
  {
332
 
    return address_v6();
333
 
  }
334
 
 
335
 
  /// Obtain an address object that represents the loopback address.
336
 
  static address_v6 loopback()
337
 
  {
338
 
    address_v6 tmp;
339
 
    asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT;
340
 
    tmp.addr_ = tmp_addr;
341
 
    return tmp;
342
 
  }
343
 
 
344
 
  /// Create an IPv4-mapped IPv6 address.
345
 
  static address_v6 v4_mapped(const address_v4& addr)
346
 
  {
347
 
    address_v4::bytes_type v4_bytes = addr.to_bytes();
348
 
    bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,
349
 
      v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
350
 
    return address_v6(v6_bytes);
351
 
  }
352
 
 
353
 
  /// Create an IPv4-compatible IPv6 address.
354
 
  static address_v6 v4_compatible(const address_v4& addr)
355
 
  {
356
 
    address_v4::bytes_type v4_bytes = addr.to_bytes();
357
 
    bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
358
 
      v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
359
 
    return address_v6(v6_bytes);
360
 
  }
361
 
 
362
 
private:
363
 
  // The underlying IPv6 address.
364
 
  asio::detail::in6_addr_type addr_;
365
 
 
366
 
  // The scope ID associated with the address.
367
 
  unsigned long scope_id_;
368
 
};
369
 
 
370
 
/// Output an address as a string.
371
 
/**
372
 
 * Used to output a human-readable string for a specified address.
373
 
 *
374
 
 * @param os The output stream to which the string will be written.
375
 
 *
376
 
 * @param addr The address to be written.
377
 
 *
378
 
 * @return The output stream.
379
 
 *
380
 
 * @relates asio::ip::address_v6
381
 
 */
382
 
template <typename Elem, typename Traits>
383
 
std::basic_ostream<Elem, Traits>& operator<<(
384
 
    std::basic_ostream<Elem, Traits>& os, const address_v6& addr)
385
 
{
386
 
  asio::error_code ec;
387
 
  std::string s = addr.to_string(ec);
388
 
  if (ec)
389
 
  {
390
 
    if (os.exceptions() & std::ios::failbit)
391
 
      asio::detail::throw_error(ec);
392
 
    else
393
 
      os.setstate(std::ios_base::failbit);
394
 
  }
395
 
  else
396
 
    for (std::string::iterator i = s.begin(); i != s.end(); ++i)
397
 
      os << os.widen(*i);
398
 
  return os;
399
 
}
400
 
 
401
 
} // namespace ip
402
 
} // namespace asio
403
 
 
404
 
#include "asio/detail/pop_options.hpp"
405
 
 
406
 
#endif // ASIO_IP_ADDRESS_V6_HPP