Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_IP_DETAIL_SOCKET_OPTION_HPP
00012 #define ASIO_IP_DETAIL_SOCKET_OPTION_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 <cstddef>
00022 #include <cstring>
00023 #include <boost/config.hpp>
00024 #include "asio/detail/pop_options.hpp"
00025
00026 #include "asio/ip/address.hpp"
00027 #include "asio/detail/socket_ops.hpp"
00028 #include "asio/detail/socket_types.hpp"
00029
00030 namespace asio {
00031 namespace ip {
00032 namespace detail {
00033 namespace socket_option {
00034
00035
00036 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00037 class multicast_enable_loopback
00038 {
00039 public:
00040 #if defined(__sun) || defined(__osf__)
00041 typedef unsigned char ipv4_value_type;
00042 typedef unsigned char ipv6_value_type;
00043 #elif defined(_AIX) || defined(__hpux)
00044 typedef unsigned char ipv4_value_type;
00045 typedef unsigned int ipv6_value_type;
00046 #else
00047 typedef int ipv4_value_type;
00048 typedef int ipv6_value_type;
00049 #endif
00050
00051
00052 multicast_enable_loopback()
00053 : ipv4_value_(0),
00054 ipv6_value_(0)
00055 {
00056 }
00057
00058
00059 explicit multicast_enable_loopback(bool v)
00060 : ipv4_value_(v ? 1 : 0),
00061 ipv6_value_(v ? 1 : 0)
00062 {
00063 }
00064
00065
00066 multicast_enable_loopback& operator=(bool v)
00067 {
00068 ipv4_value_ = v ? 1 : 0;
00069 ipv6_value_ = v ? 1 : 0;
00070 return *this;
00071 }
00072
00073
00074 bool value() const
00075 {
00076 return !!ipv4_value_;
00077 }
00078
00079
00080 operator bool() const
00081 {
00082 return !!ipv4_value_;
00083 }
00084
00085
00086 bool operator!() const
00087 {
00088 return !ipv4_value_;
00089 }
00090
00091
00092 template <typename Protocol>
00093 int level(const Protocol& protocol) const
00094 {
00095 if (protocol.family() == PF_INET6)
00096 return IPv6_Level;
00097 return IPv4_Level;
00098 }
00099
00100
00101 template <typename Protocol>
00102 int name(const Protocol& protocol) const
00103 {
00104 if (protocol.family() == PF_INET6)
00105 return IPv6_Name;
00106 return IPv4_Name;
00107 }
00108
00109
00110 template <typename Protocol>
00111 void* data(const Protocol& protocol)
00112 {
00113 if (protocol.family() == PF_INET6)
00114 return &ipv6_value_;
00115 return &ipv4_value_;
00116 }
00117
00118
00119 template <typename Protocol>
00120 const void* data(const Protocol& protocol) const
00121 {
00122 if (protocol.family() == PF_INET6)
00123 return &ipv6_value_;
00124 return &ipv4_value_;
00125 }
00126
00127
00128 template <typename Protocol>
00129 std::size_t size(const Protocol& protocol) const
00130 {
00131 if (protocol.family() == PF_INET6)
00132 return sizeof(ipv6_value_);
00133 return sizeof(ipv4_value_);
00134 }
00135
00136
00137 template <typename Protocol>
00138 void resize(const Protocol& protocol, std::size_t s)
00139 {
00140 if (protocol.family() == PF_INET6)
00141 {
00142 if (s != sizeof(ipv6_value_))
00143 {
00144 throw std::length_error(
00145 "multicast_enable_loopback socket option resize");
00146 }
00147 ipv4_value_ = ipv6_value_ ? 1 : 0;
00148 }
00149 else
00150 {
00151 if (s != sizeof(ipv4_value_))
00152 {
00153 throw std::length_error(
00154 "multicast_enable_loopback socket option resize");
00155 }
00156 ipv6_value_ = ipv4_value_ ? 1 : 0;
00157 }
00158 }
00159
00160 private:
00161 ipv4_value_type ipv4_value_;
00162 ipv6_value_type ipv6_value_;
00163 };
00164
00165
00166 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00167 class unicast_hops
00168 {
00169 public:
00170
00171 unicast_hops()
00172 : value_(0)
00173 {
00174 }
00175
00176
00177 explicit unicast_hops(int v)
00178 : value_(v)
00179 {
00180 }
00181
00182
00183 unicast_hops& operator=(int v)
00184 {
00185 value_ = v;
00186 return *this;
00187 }
00188
00189
00190 int value() const
00191 {
00192 return value_;
00193 }
00194
00195
00196 template <typename Protocol>
00197 int level(const Protocol& protocol) const
00198 {
00199 if (protocol.family() == PF_INET6)
00200 return IPv6_Level;
00201 return IPv4_Level;
00202 }
00203
00204
00205 template <typename Protocol>
00206 int name(const Protocol& protocol) const
00207 {
00208 if (protocol.family() == PF_INET6)
00209 return IPv6_Name;
00210 return IPv4_Name;
00211 }
00212
00213
00214 template <typename Protocol>
00215 int* data(const Protocol&)
00216 {
00217 return &value_;
00218 }
00219
00220
00221 template <typename Protocol>
00222 const int* data(const Protocol&) const
00223 {
00224 return &value_;
00225 }
00226
00227
00228 template <typename Protocol>
00229 std::size_t size(const Protocol&) const
00230 {
00231 return sizeof(value_);
00232 }
00233
00234
00235 template <typename Protocol>
00236 void resize(const Protocol&, std::size_t s)
00237 {
00238 if (s != sizeof(value_))
00239 throw std::length_error("unicast hops socket option resize");
00240 #if defined(__hpux)
00241 if (value_ < 0)
00242 value_ = value_ & 0xFF;
00243 #endif
00244 }
00245
00246 private:
00247 int value_;
00248 };
00249
00250
00251 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00252 class multicast_hops
00253 {
00254 public:
00255 #if defined(BOOST_WINDOWS) && defined(UNDER_CE)
00256 typedef int ipv4_value_type;
00257 #else
00258 typedef unsigned char ipv4_value_type;
00259 #endif
00260 typedef int ipv6_value_type;
00261
00262
00263 multicast_hops()
00264 : ipv4_value_(0),
00265 ipv6_value_(0)
00266 {
00267 }
00268
00269
00270 explicit multicast_hops(int v)
00271 {
00272 if (v < 0 || v > 255)
00273 throw std::out_of_range("multicast hops value out of range");
00274 ipv4_value_ = (ipv4_value_type)v;
00275 ipv6_value_ = v;
00276 }
00277
00278
00279 multicast_hops& operator=(int v)
00280 {
00281 if (v < 0 || v > 255)
00282 throw std::out_of_range("multicast hops value out of range");
00283 ipv4_value_ = (ipv4_value_type)v;
00284 ipv6_value_ = v;
00285 return *this;
00286 }
00287
00288
00289 int value() const
00290 {
00291 return ipv6_value_;
00292 }
00293
00294
00295 template <typename Protocol>
00296 int level(const Protocol& protocol) const
00297 {
00298 if (protocol.family() == PF_INET6)
00299 return IPv6_Level;
00300 return IPv4_Level;
00301 }
00302
00303
00304 template <typename Protocol>
00305 int name(const Protocol& protocol) const
00306 {
00307 if (protocol.family() == PF_INET6)
00308 return IPv6_Name;
00309 return IPv4_Name;
00310 }
00311
00312
00313 template <typename Protocol>
00314 void* data(const Protocol& protocol)
00315 {
00316 if (protocol.family() == PF_INET6)
00317 return &ipv6_value_;
00318 return &ipv4_value_;
00319 }
00320
00321
00322 template <typename Protocol>
00323 const void* data(const Protocol& protocol) const
00324 {
00325 if (protocol.family() == PF_INET6)
00326 return &ipv6_value_;
00327 return &ipv4_value_;
00328 }
00329
00330
00331 template <typename Protocol>
00332 std::size_t size(const Protocol& protocol) const
00333 {
00334 if (protocol.family() == PF_INET6)
00335 return sizeof(ipv6_value_);
00336 return sizeof(ipv4_value_);
00337 }
00338
00339
00340 template <typename Protocol>
00341 void resize(const Protocol& protocol, std::size_t s)
00342 {
00343 if (protocol.family() == PF_INET6)
00344 {
00345 if (s != sizeof(ipv6_value_))
00346 throw std::length_error("multicast hops socket option resize");
00347 if (ipv6_value_ < 0)
00348 ipv4_value_ = 0;
00349 else if (ipv6_value_ > 255)
00350 ipv4_value_ = 255;
00351 else
00352 ipv4_value_ = (ipv4_value_type)ipv6_value_;
00353 }
00354 else
00355 {
00356 if (s != sizeof(ipv4_value_))
00357 throw std::length_error("multicast hops socket option resize");
00358 ipv6_value_ = ipv4_value_;
00359 }
00360 }
00361
00362 private:
00363 ipv4_value_type ipv4_value_;
00364 ipv6_value_type ipv6_value_;
00365 };
00366
00367
00368 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00369 class multicast_request
00370 {
00371 public:
00372
00373 multicast_request()
00374 {
00375 ipv4_value_.imr_multiaddr.s_addr =
00376 asio::detail::socket_ops::host_to_network_long(
00377 asio::ip::address_v4::any().to_ulong());
00378 ipv4_value_.imr_interface.s_addr =
00379 asio::detail::socket_ops::host_to_network_long(
00380 asio::ip::address_v4::any().to_ulong());
00381
00382 asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
00383 ipv6_value_.ipv6mr_multiaddr = tmp_addr;
00384 ipv6_value_.ipv6mr_interface = 0;
00385 }
00386
00387
00388 explicit multicast_request(const asio::ip::address& multicast_address)
00389 {
00390 if (multicast_address.is_v6())
00391 {
00392 ipv4_value_.imr_multiaddr.s_addr =
00393 asio::detail::socket_ops::host_to_network_long(
00394 asio::ip::address_v4::any().to_ulong());
00395 ipv4_value_.imr_interface.s_addr =
00396 asio::detail::socket_ops::host_to_network_long(
00397 asio::ip::address_v4::any().to_ulong());
00398
00399 using namespace std;
00400 asio::ip::address_v6 ipv6_address = multicast_address.to_v6();
00401 asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes();
00402 memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16);
00403 ipv6_value_.ipv6mr_interface = 0;
00404 }
00405 else
00406 {
00407 ipv4_value_.imr_multiaddr.s_addr =
00408 asio::detail::socket_ops::host_to_network_long(
00409 multicast_address.to_v4().to_ulong());
00410 ipv4_value_.imr_interface.s_addr =
00411 asio::detail::socket_ops::host_to_network_long(
00412 asio::ip::address_v4::any().to_ulong());
00413
00414 asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
00415 ipv6_value_.ipv6mr_multiaddr = tmp_addr;
00416 ipv6_value_.ipv6mr_interface = 0;
00417 }
00418 }
00419
00420
00421 explicit multicast_request(
00422 const asio::ip::address_v4& multicast_address,
00423 const asio::ip::address_v4& network_interface
00424 = asio::ip::address_v4::any())
00425 {
00426 ipv4_value_.imr_multiaddr.s_addr =
00427 asio::detail::socket_ops::host_to_network_long(
00428 multicast_address.to_ulong());
00429 ipv4_value_.imr_interface.s_addr =
00430 asio::detail::socket_ops::host_to_network_long(
00431 network_interface.to_ulong());
00432
00433 asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
00434 ipv6_value_.ipv6mr_multiaddr = tmp_addr;
00435 ipv6_value_.ipv6mr_interface = 0;
00436 }
00437
00438
00439 explicit multicast_request(
00440 const asio::ip::address_v6& multicast_address,
00441 unsigned long network_interface = 0)
00442 {
00443 ipv4_value_.imr_multiaddr.s_addr =
00444 asio::detail::socket_ops::host_to_network_long(
00445 asio::ip::address_v4::any().to_ulong());
00446 ipv4_value_.imr_interface.s_addr =
00447 asio::detail::socket_ops::host_to_network_long(
00448 asio::ip::address_v4::any().to_ulong());
00449
00450 using namespace std;
00451 asio::ip::address_v6::bytes_type bytes =
00452 multicast_address.to_bytes();
00453 memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16);
00454 ipv6_value_.ipv6mr_interface = network_interface;
00455 }
00456
00457
00458 template <typename Protocol>
00459 int level(const Protocol& protocol) const
00460 {
00461 if (protocol.family() == PF_INET6)
00462 return IPv6_Level;
00463 return IPv4_Level;
00464 }
00465
00466
00467 template <typename Protocol>
00468 int name(const Protocol& protocol) const
00469 {
00470 if (protocol.family() == PF_INET6)
00471 return IPv6_Name;
00472 return IPv4_Name;
00473 }
00474
00475
00476 template <typename Protocol>
00477 const void* data(const Protocol& protocol) const
00478 {
00479 if (protocol.family() == PF_INET6)
00480 return &ipv6_value_;
00481 return &ipv4_value_;
00482 }
00483
00484
00485 template <typename Protocol>
00486 std::size_t size(const Protocol& protocol) const
00487 {
00488 if (protocol.family() == PF_INET6)
00489 return sizeof(ipv6_value_);
00490 return sizeof(ipv4_value_);
00491 }
00492
00493 private:
00494 asio::detail::in4_mreq_type ipv4_value_;
00495 asio::detail::in6_mreq_type ipv6_value_;
00496 };
00497
00498
00499 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
00500 class network_interface
00501 {
00502 public:
00503
00504 network_interface()
00505 {
00506 ipv4_value_.s_addr =
00507 asio::detail::socket_ops::host_to_network_long(
00508 asio::ip::address_v4::any().to_ulong());
00509 ipv6_value_ = 0;
00510 }
00511
00512
00513 explicit network_interface(const asio::ip::address_v4& ipv4_interface)
00514 {
00515 ipv4_value_.s_addr =
00516 asio::detail::socket_ops::host_to_network_long(
00517 ipv4_interface.to_ulong());
00518 ipv6_value_ = 0;
00519 }
00520
00521
00522 explicit network_interface(unsigned int ipv6_interface)
00523 {
00524 ipv4_value_.s_addr =
00525 asio::detail::socket_ops::host_to_network_long(
00526 asio::ip::address_v4::any().to_ulong());
00527 ipv6_value_ = ipv6_interface;
00528 }
00529
00530
00531 template <typename Protocol>
00532 int level(const Protocol& protocol) const
00533 {
00534 if (protocol.family() == PF_INET6)
00535 return IPv6_Level;
00536 return IPv4_Level;
00537 }
00538
00539
00540 template <typename Protocol>
00541 int name(const Protocol& protocol) const
00542 {
00543 if (protocol.family() == PF_INET6)
00544 return IPv6_Name;
00545 return IPv4_Name;
00546 }
00547
00548
00549 template <typename Protocol>
00550 const void* data(const Protocol& protocol) const
00551 {
00552 if (protocol.family() == PF_INET6)
00553 return &ipv6_value_;
00554 return &ipv4_value_;
00555 }
00556
00557
00558 template <typename Protocol>
00559 std::size_t size(const Protocol& protocol) const
00560 {
00561 if (protocol.family() == PF_INET6)
00562 return sizeof(ipv6_value_);
00563 return sizeof(ipv4_value_);
00564 }
00565
00566 private:
00567 asio::detail::in4_addr_type ipv4_value_;
00568 unsigned int ipv6_value_;
00569 };
00570
00571 }
00572 }
00573 }
00574 }
00575
00576 #include "asio/detail/pop_options.hpp"
00577
00578 #endif // ASIO_IP_DETAIL_SOCKET_OPTION_HPP