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