5
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11
#ifndef ASIO_IP_ADDRESS_V6_HPP
12
#define ASIO_IP_ADDRESS_V6_HPP
14
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
16
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18
#include "asio/detail/push_options.hpp"
20
#include "asio/detail/push_options.hpp"
25
#include <boost/array.hpp>
26
#include <boost/throw_exception.hpp>
27
#include "asio/detail/pop_options.hpp"
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"
38
/// Implements IP version 6 style addresses.
40
* The asio::ip::address_v6 class provides the ability to use and
41
* manipulate IP version 6 addresses.
44
* @e Distinct @e objects: Safe.@n
45
* @e Shared @e objects: Unsafe.
50
/// The type used to represent an address as an array of bytes.
51
typedef boost::array<unsigned char, 16> bytes_type;
53
/// Default constructor.
57
asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
61
/// Construct an address from raw bytes and scope ID.
62
explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0)
65
using namespace std; // For memcpy.
66
memcpy(addr_.s6_addr, bytes.elems, 16);
70
address_v6(const address_v6& other)
72
scope_id_(other.scope_id_)
76
/// Assign from another address.
77
address_v6& operator=(const address_v6& other)
80
scope_id_ = other.scope_id_;
84
/// The scope ID of the address.
86
* Returns the scope ID associated with the IPv6 address.
88
unsigned long scope_id() const
93
/// The scope ID of the address.
95
* Modifies the scope ID associated with the IPv6 address.
97
void scope_id(unsigned long id)
102
/// Get the address in bytes.
103
bytes_type to_bytes() const
105
using namespace std; // For memcpy.
107
memcpy(bytes.elems, addr_.s6_addr, 16);
111
/// Get the address as a string.
112
std::string to_string() const
115
std::string addr = to_string(ec);
116
asio::detail::throw_error(ec);
120
/// Get the address as a string.
121
std::string to_string(asio::error_code& ec) const
123
char addr_str[asio::detail::max_addr_v6_str_len];
125
asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str,
126
asio::detail::max_addr_v6_str_len, scope_id_, ec);
128
return std::string();
132
/// Create an address from an IP address string.
133
static address_v6 from_string(const char* str)
136
address_v6 addr = from_string(str, ec);
137
asio::detail::throw_error(ec);
141
/// Create an address from an IP address string.
142
static address_v6 from_string(const char* str, asio::error_code& ec)
145
if (asio::detail::socket_ops::inet_pton(
146
AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0)
151
/// Create an address from an IP address string.
152
static address_v6 from_string(const std::string& str)
154
return from_string(str.c_str());
157
/// Create an address from an IP address string.
158
static address_v6 from_string(const std::string& str,
159
asio::error_code& ec)
161
return from_string(str.c_str(), ec);
164
/// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address.
165
address_v4 to_v4() const
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);
174
/// Determine whether the address is a loopback address.
175
bool is_loopback() const
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));
187
using namespace asio::detail;
188
return IN6_IS_ADDR_LOOPBACK(&addr_) != 0;
192
/// Determine whether the address is unspecified.
193
bool is_unspecified() const
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));
205
using namespace asio::detail;
206
return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0;
210
/// Determine whether the address is link local.
211
bool is_link_local() const
213
using namespace asio::detail;
214
return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0;
217
/// Determine whether the address is site local.
218
bool is_site_local() const
220
using namespace asio::detail;
221
return IN6_IS_ADDR_SITELOCAL(&addr_) != 0;
224
/// Determine whether the address is a mapped IPv4 address.
225
bool is_v4_mapped() const
227
using namespace asio::detail;
228
return IN6_IS_ADDR_V4MAPPED(&addr_) != 0;
231
/// Determine whether the address is an IPv4-compatible address.
232
bool is_v4_compatible() const
234
using namespace asio::detail;
235
return IN6_IS_ADDR_V4COMPAT(&addr_) != 0;
238
/// Determine whether the address is a multicast address.
239
bool is_multicast() const
241
using namespace asio::detail;
242
return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
245
/// Determine whether the address is a global multicast address.
246
bool is_multicast_global() const
248
using namespace asio::detail;
249
return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0;
252
/// Determine whether the address is a link-local multicast address.
253
bool is_multicast_link_local() const
255
using namespace asio::detail;
256
return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0;
259
/// Determine whether the address is a node-local multicast address.
260
bool is_multicast_node_local() const
262
using namespace asio::detail;
263
return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0;
266
/// Determine whether the address is a org-local multicast address.
267
bool is_multicast_org_local() const
269
using namespace asio::detail;
270
return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0;
273
/// Determine whether the address is a site-local multicast address.
274
bool is_multicast_site_local() const
276
using namespace asio::detail;
277
return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0;
280
/// Compare two addresses for equality.
281
friend bool operator==(const address_v6& a1, const address_v6& a2)
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_;
289
/// Compare two addresses for inequality.
290
friend bool operator!=(const address_v6& a1, const address_v6& a2)
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_;
298
/// Compare addresses for ordering.
299
friend bool operator<(const address_v6& a1, const address_v6& a2)
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)
306
if (memcmp_result > 0)
308
return a1.scope_id_ < a2.scope_id_;
311
/// Compare addresses for ordering.
312
friend bool operator>(const address_v6& a1, const address_v6& a2)
317
/// Compare addresses for ordering.
318
friend bool operator<=(const address_v6& a1, const address_v6& a2)
323
/// Compare addresses for ordering.
324
friend bool operator>=(const address_v6& a1, const address_v6& a2)
329
/// Obtain an address object that represents any address.
330
static address_v6 any()
335
/// Obtain an address object that represents the loopback address.
336
static address_v6 loopback()
339
asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT;
340
tmp.addr_ = tmp_addr;
344
/// Create an IPv4-mapped IPv6 address.
345
static address_v6 v4_mapped(const address_v4& addr)
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);
353
/// Create an IPv4-compatible IPv6 address.
354
static address_v6 v4_compatible(const address_v4& addr)
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);
363
// The underlying IPv6 address.
364
asio::detail::in6_addr_type addr_;
366
// The scope ID associated with the address.
367
unsigned long scope_id_;
370
/// Output an address as a string.
372
* Used to output a human-readable string for a specified address.
374
* @param os The output stream to which the string will be written.
376
* @param addr The address to be written.
378
* @return The output stream.
380
* @relates asio::ip::address_v6
382
template <typename Elem, typename Traits>
383
std::basic_ostream<Elem, Traits>& operator<<(
384
std::basic_ostream<Elem, Traits>& os, const address_v6& addr)
387
std::string s = addr.to_string(ec);
390
if (os.exceptions() & std::ios::failbit)
391
asio::detail::throw_error(ec);
393
os.setstate(std::ios_base::failbit);
396
for (std::string::iterator i = s.begin(); i != s.end(); ++i)
404
#include "asio/detail/pop_options.hpp"
406
#endif // ASIO_IP_ADDRESS_V6_HPP