$search
00001 // 00002 // address_v6.hpp 00003 // ~~~~~~~~~~~~~~ 00004 // 00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) 00006 // 00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00009 // 00010 00011 #ifndef ASIO_IP_ADDRESS_V6_HPP 00012 #define ASIO_IP_ADDRESS_V6_HPP 00013 00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 00015 # pragma once 00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 00017 00018 #include "asio/detail/push_options.hpp" 00019 00020 #include "asio/detail/push_options.hpp" 00021 #include <cstring> 00022 #include <string> 00023 #include <stdexcept> 00024 #include <typeinfo> 00025 #include <boost/array.hpp> 00026 #include <boost/throw_exception.hpp> 00027 #include "asio/detail/pop_options.hpp" 00028 00029 #include "asio/error.hpp" 00030 #include "asio/detail/socket_ops.hpp" 00031 #include "asio/detail/socket_types.hpp" 00032 #include "asio/detail/throw_error.hpp" 00033 #include "asio/ip/address_v4.hpp" 00034 00035 namespace asio { 00036 namespace ip { 00037 00039 00047 class address_v6 00048 { 00049 public: 00051 typedef boost::array<unsigned char, 16> bytes_type; 00052 00054 address_v6() 00055 : scope_id_(0) 00056 { 00057 asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; 00058 addr_ = tmp_addr; 00059 } 00060 00062 explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0) 00063 : scope_id_(scope_id) 00064 { 00065 using namespace std; // For memcpy. 00066 memcpy(addr_.s6_addr, bytes.elems, 16); 00067 } 00068 00070 address_v6(const address_v6& other) 00071 : addr_(other.addr_), 00072 scope_id_(other.scope_id_) 00073 { 00074 } 00075 00077 address_v6& operator=(const address_v6& other) 00078 { 00079 addr_ = other.addr_; 00080 scope_id_ = other.scope_id_; 00081 return *this; 00082 } 00083 00085 00088 unsigned long scope_id() const 00089 { 00090 return scope_id_; 00091 } 00092 00094 00097 void scope_id(unsigned long id) 00098 { 00099 scope_id_ = id; 00100 } 00101 00103 bytes_type to_bytes() const 00104 { 00105 using namespace std; // For memcpy. 00106 bytes_type bytes; 00107 memcpy(bytes.elems, addr_.s6_addr, 16); 00108 return bytes; 00109 } 00110 00112 std::string to_string() const 00113 { 00114 asio::error_code ec; 00115 std::string addr = to_string(ec); 00116 asio::detail::throw_error(ec); 00117 return addr; 00118 } 00119 00121 std::string to_string(asio::error_code& ec) const 00122 { 00123 char addr_str[asio::detail::max_addr_v6_str_len]; 00124 const char* addr = 00125 asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str, 00126 asio::detail::max_addr_v6_str_len, scope_id_, ec); 00127 if (addr == 0) 00128 return std::string(); 00129 return addr; 00130 } 00131 00133 static address_v6 from_string(const char* str) 00134 { 00135 asio::error_code ec; 00136 address_v6 addr = from_string(str, ec); 00137 asio::detail::throw_error(ec); 00138 return addr; 00139 } 00140 00142 static address_v6 from_string(const char* str, asio::error_code& ec) 00143 { 00144 address_v6 tmp; 00145 if (asio::detail::socket_ops::inet_pton( 00146 AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0) 00147 return address_v6(); 00148 return tmp; 00149 } 00150 00152 static address_v6 from_string(const std::string& str) 00153 { 00154 return from_string(str.c_str()); 00155 } 00156 00158 static address_v6 from_string(const std::string& str, 00159 asio::error_code& ec) 00160 { 00161 return from_string(str.c_str(), ec); 00162 } 00163 00165 address_v4 to_v4() const 00166 { 00167 if (!is_v4_mapped() && !is_v4_compatible()) 00168 throw std::bad_cast(); 00169 address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12], 00170 addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } }; 00171 return address_v4(v4_bytes); 00172 } 00173 00175 bool is_loopback() const 00176 { 00177 #if defined(__BORLANDC__) 00178 return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) 00179 && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) 00180 && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) 00181 && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) 00182 && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) 00183 && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) 00184 && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) 00185 && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1)); 00186 #else 00187 using namespace asio::detail; 00188 return IN6_IS_ADDR_LOOPBACK(&addr_) != 0; 00189 #endif 00190 } 00191 00193 bool is_unspecified() const 00194 { 00195 #if defined(__BORLANDC__) 00196 return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) 00197 && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) 00198 && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) 00199 && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) 00200 && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) 00201 && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) 00202 && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) 00203 && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0)); 00204 #else 00205 using namespace asio::detail; 00206 return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0; 00207 #endif 00208 } 00209 00211 bool is_link_local() const 00212 { 00213 using namespace asio::detail; 00214 return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0; 00215 } 00216 00218 bool is_site_local() const 00219 { 00220 using namespace asio::detail; 00221 return IN6_IS_ADDR_SITELOCAL(&addr_) != 0; 00222 } 00223 00225 bool is_v4_mapped() const 00226 { 00227 using namespace asio::detail; 00228 return IN6_IS_ADDR_V4MAPPED(&addr_) != 0; 00229 } 00230 00232 bool is_v4_compatible() const 00233 { 00234 using namespace asio::detail; 00235 return IN6_IS_ADDR_V4COMPAT(&addr_) != 0; 00236 } 00237 00239 bool is_multicast() const 00240 { 00241 using namespace asio::detail; 00242 return IN6_IS_ADDR_MULTICAST(&addr_) != 0; 00243 } 00244 00246 bool is_multicast_global() const 00247 { 00248 using namespace asio::detail; 00249 return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0; 00250 } 00251 00253 bool is_multicast_link_local() const 00254 { 00255 using namespace asio::detail; 00256 return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0; 00257 } 00258 00260 bool is_multicast_node_local() const 00261 { 00262 using namespace asio::detail; 00263 return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0; 00264 } 00265 00267 bool is_multicast_org_local() const 00268 { 00269 using namespace asio::detail; 00270 return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0; 00271 } 00272 00274 bool is_multicast_site_local() const 00275 { 00276 using namespace asio::detail; 00277 return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0; 00278 } 00279 00281 friend bool operator==(const address_v6& a1, const address_v6& a2) 00282 { 00283 using namespace std; // For memcmp. 00284 return memcmp(&a1.addr_, &a2.addr_, 00285 sizeof(asio::detail::in6_addr_type)) == 0 00286 && a1.scope_id_ == a2.scope_id_; 00287 } 00288 00290 friend bool operator!=(const address_v6& a1, const address_v6& a2) 00291 { 00292 using namespace std; // For memcmp. 00293 return memcmp(&a1.addr_, &a2.addr_, 00294 sizeof(asio::detail::in6_addr_type)) != 0 00295 || a1.scope_id_ != a2.scope_id_; 00296 } 00297 00299 friend bool operator<(const address_v6& a1, const address_v6& a2) 00300 { 00301 using namespace std; // For memcmp. 00302 int memcmp_result = memcmp(&a1.addr_, &a2.addr_, 00303 sizeof(asio::detail::in6_addr_type)); 00304 if (memcmp_result < 0) 00305 return true; 00306 if (memcmp_result > 0) 00307 return false; 00308 return a1.scope_id_ < a2.scope_id_; 00309 } 00310 00312 friend bool operator>(const address_v6& a1, const address_v6& a2) 00313 { 00314 return a2 < a1; 00315 } 00316 00318 friend bool operator<=(const address_v6& a1, const address_v6& a2) 00319 { 00320 return !(a2 < a1); 00321 } 00322 00324 friend bool operator>=(const address_v6& a1, const address_v6& a2) 00325 { 00326 return !(a1 < a2); 00327 } 00328 00330 static address_v6 any() 00331 { 00332 return address_v6(); 00333 } 00334 00336 static address_v6 loopback() 00337 { 00338 address_v6 tmp; 00339 asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT; 00340 tmp.addr_ = tmp_addr; 00341 return tmp; 00342 } 00343 00345 static address_v6 v4_mapped(const address_v4& addr) 00346 { 00347 address_v4::bytes_type v4_bytes = addr.to_bytes(); 00348 bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 00349 v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; 00350 return address_v6(v6_bytes); 00351 } 00352 00354 static address_v6 v4_compatible(const address_v4& addr) 00355 { 00356 address_v4::bytes_type v4_bytes = addr.to_bytes(); 00357 bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00358 v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; 00359 return address_v6(v6_bytes); 00360 } 00361 00362 private: 00363 // The underlying IPv6 address. 00364 asio::detail::in6_addr_type addr_; 00365 00366 // The scope ID associated with the address. 00367 unsigned long scope_id_; 00368 }; 00369 00371 00382 template <typename Elem, typename Traits> 00383 std::basic_ostream<Elem, Traits>& operator<<( 00384 std::basic_ostream<Elem, Traits>& os, const address_v6& addr) 00385 { 00386 asio::error_code ec; 00387 std::string s = addr.to_string(ec); 00388 if (ec) 00389 { 00390 if (os.exceptions() & std::ios::failbit) 00391 asio::detail::throw_error(ec); 00392 else 00393 os.setstate(std::ios_base::failbit); 00394 } 00395 else 00396 for (std::string::iterator i = s.begin(); i != s.end(); ++i) 00397 os << os.widen(*i); 00398 return os; 00399 } 00400 00401 } // namespace ip 00402 } // namespace asio 00403 00404 #include "asio/detail/pop_options.hpp" 00405 00406 #endif // ASIO_IP_ADDRESS_V6_HPP