File indexing completed on 2025-01-18 09:28:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
0012 #define BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019 #include <cstddef>
0020 #include <cstring>
0021 #include <stdexcept>
0022 #include <boost/asio/detail/socket_ops.hpp>
0023 #include <boost/asio/detail/socket_types.hpp>
0024 #include <boost/asio/detail/throw_exception.hpp>
0025 #include <boost/asio/ip/address.hpp>
0026
0027 #include <boost/asio/detail/push_options.hpp>
0028
0029 namespace boost {
0030 namespace asio {
0031 namespace ip {
0032 namespace detail {
0033 namespace socket_option {
0034
0035
0036 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
0037 class multicast_enable_loopback
0038 {
0039 public:
0040 #if defined(__sun) || defined(__osf__)
0041 typedef unsigned char ipv4_value_type;
0042 typedef unsigned char ipv6_value_type;
0043 #elif defined(_AIX) || defined(__hpux) || defined(__QNXNTO__)
0044 typedef unsigned char ipv4_value_type;
0045 typedef unsigned int ipv6_value_type;
0046 #else
0047 typedef int ipv4_value_type;
0048 typedef int ipv6_value_type;
0049 #endif
0050
0051
0052 multicast_enable_loopback()
0053 : ipv4_value_(0),
0054 ipv6_value_(0)
0055 {
0056 }
0057
0058
0059 explicit multicast_enable_loopback(bool v)
0060 : ipv4_value_(v ? 1 : 0),
0061 ipv6_value_(v ? 1 : 0)
0062 {
0063 }
0064
0065
0066 multicast_enable_loopback& operator=(bool v)
0067 {
0068 ipv4_value_ = v ? 1 : 0;
0069 ipv6_value_ = v ? 1 : 0;
0070 return *this;
0071 }
0072
0073
0074 bool value() const
0075 {
0076 return !!ipv4_value_;
0077 }
0078
0079
0080 operator bool() const
0081 {
0082 return !!ipv4_value_;
0083 }
0084
0085
0086 bool operator!() const
0087 {
0088 return !ipv4_value_;
0089 }
0090
0091
0092 template <typename Protocol>
0093 int level(const Protocol& protocol) const
0094 {
0095 if (protocol.family() == PF_INET6)
0096 return IPv6_Level;
0097 return IPv4_Level;
0098 }
0099
0100
0101 template <typename Protocol>
0102 int name(const Protocol& protocol) const
0103 {
0104 if (protocol.family() == PF_INET6)
0105 return IPv6_Name;
0106 return IPv4_Name;
0107 }
0108
0109
0110 template <typename Protocol>
0111 void* data(const Protocol& protocol)
0112 {
0113 if (protocol.family() == PF_INET6)
0114 return &ipv6_value_;
0115 return &ipv4_value_;
0116 }
0117
0118
0119 template <typename Protocol>
0120 const void* data(const Protocol& protocol) const
0121 {
0122 if (protocol.family() == PF_INET6)
0123 return &ipv6_value_;
0124 return &ipv4_value_;
0125 }
0126
0127
0128 template <typename Protocol>
0129 std::size_t size(const Protocol& protocol) const
0130 {
0131 if (protocol.family() == PF_INET6)
0132 return sizeof(ipv6_value_);
0133 return sizeof(ipv4_value_);
0134 }
0135
0136
0137 template <typename Protocol>
0138 void resize(const Protocol& protocol, std::size_t s)
0139 {
0140 if (protocol.family() == PF_INET6)
0141 {
0142 if (s != sizeof(ipv6_value_))
0143 {
0144 std::length_error ex("multicast_enable_loopback socket option resize");
0145 boost::asio::detail::throw_exception(ex);
0146 }
0147 ipv4_value_ = ipv6_value_ ? 1 : 0;
0148 }
0149 else
0150 {
0151 if (s != sizeof(ipv4_value_))
0152 {
0153 std::length_error ex("multicast_enable_loopback socket option resize");
0154 boost::asio::detail::throw_exception(ex);
0155 }
0156 ipv6_value_ = ipv4_value_ ? 1 : 0;
0157 }
0158 }
0159
0160 private:
0161 ipv4_value_type ipv4_value_;
0162 ipv6_value_type ipv6_value_;
0163 };
0164
0165
0166 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
0167 class unicast_hops
0168 {
0169 public:
0170
0171 unicast_hops()
0172 : value_(0)
0173 {
0174 }
0175
0176
0177 explicit unicast_hops(int v)
0178 : value_(v)
0179 {
0180 }
0181
0182
0183 unicast_hops& operator=(int v)
0184 {
0185 value_ = v;
0186 return *this;
0187 }
0188
0189
0190 int value() const
0191 {
0192 return value_;
0193 }
0194
0195
0196 template <typename Protocol>
0197 int level(const Protocol& protocol) const
0198 {
0199 if (protocol.family() == PF_INET6)
0200 return IPv6_Level;
0201 return IPv4_Level;
0202 }
0203
0204
0205 template <typename Protocol>
0206 int name(const Protocol& protocol) const
0207 {
0208 if (protocol.family() == PF_INET6)
0209 return IPv6_Name;
0210 return IPv4_Name;
0211 }
0212
0213
0214 template <typename Protocol>
0215 int* data(const Protocol&)
0216 {
0217 return &value_;
0218 }
0219
0220
0221 template <typename Protocol>
0222 const int* data(const Protocol&) const
0223 {
0224 return &value_;
0225 }
0226
0227
0228 template <typename Protocol>
0229 std::size_t size(const Protocol&) const
0230 {
0231 return sizeof(value_);
0232 }
0233
0234
0235 template <typename Protocol>
0236 void resize(const Protocol&, std::size_t s)
0237 {
0238 if (s != sizeof(value_))
0239 {
0240 std::length_error ex("unicast hops socket option resize");
0241 boost::asio::detail::throw_exception(ex);
0242 }
0243 #if defined(__hpux)
0244 if (value_ < 0)
0245 value_ = value_ & 0xFF;
0246 #endif
0247 }
0248
0249 private:
0250 int value_;
0251 };
0252
0253
0254 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
0255 class multicast_hops
0256 {
0257 public:
0258 #if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
0259 typedef int ipv4_value_type;
0260 #else
0261 typedef unsigned char ipv4_value_type;
0262 #endif
0263 typedef int ipv6_value_type;
0264
0265
0266 multicast_hops()
0267 : ipv4_value_(0),
0268 ipv6_value_(0)
0269 {
0270 }
0271
0272
0273 explicit multicast_hops(int v)
0274 {
0275 if (v < 0 || v > 255)
0276 {
0277 std::out_of_range ex("multicast hops value out of range");
0278 boost::asio::detail::throw_exception(ex);
0279 }
0280 ipv4_value_ = (ipv4_value_type)v;
0281 ipv6_value_ = v;
0282 }
0283
0284
0285 multicast_hops& operator=(int v)
0286 {
0287 if (v < 0 || v > 255)
0288 {
0289 std::out_of_range ex("multicast hops value out of range");
0290 boost::asio::detail::throw_exception(ex);
0291 }
0292 ipv4_value_ = (ipv4_value_type)v;
0293 ipv6_value_ = v;
0294 return *this;
0295 }
0296
0297
0298 int value() const
0299 {
0300 return ipv6_value_;
0301 }
0302
0303
0304 template <typename Protocol>
0305 int level(const Protocol& protocol) const
0306 {
0307 if (protocol.family() == PF_INET6)
0308 return IPv6_Level;
0309 return IPv4_Level;
0310 }
0311
0312
0313 template <typename Protocol>
0314 int name(const Protocol& protocol) const
0315 {
0316 if (protocol.family() == PF_INET6)
0317 return IPv6_Name;
0318 return IPv4_Name;
0319 }
0320
0321
0322 template <typename Protocol>
0323 void* data(const Protocol& protocol)
0324 {
0325 if (protocol.family() == PF_INET6)
0326 return &ipv6_value_;
0327 return &ipv4_value_;
0328 }
0329
0330
0331 template <typename Protocol>
0332 const void* data(const Protocol& protocol) const
0333 {
0334 if (protocol.family() == PF_INET6)
0335 return &ipv6_value_;
0336 return &ipv4_value_;
0337 }
0338
0339
0340 template <typename Protocol>
0341 std::size_t size(const Protocol& protocol) const
0342 {
0343 if (protocol.family() == PF_INET6)
0344 return sizeof(ipv6_value_);
0345 return sizeof(ipv4_value_);
0346 }
0347
0348
0349 template <typename Protocol>
0350 void resize(const Protocol& protocol, std::size_t s)
0351 {
0352 if (protocol.family() == PF_INET6)
0353 {
0354 if (s != sizeof(ipv6_value_))
0355 {
0356 std::length_error ex("multicast hops socket option resize");
0357 boost::asio::detail::throw_exception(ex);
0358 }
0359 if (ipv6_value_ < 0)
0360 ipv4_value_ = 0;
0361 else if (ipv6_value_ > 255)
0362 ipv4_value_ = 255;
0363 else
0364 ipv4_value_ = (ipv4_value_type)ipv6_value_;
0365 }
0366 else
0367 {
0368 if (s != sizeof(ipv4_value_))
0369 {
0370 std::length_error ex("multicast hops socket option resize");
0371 boost::asio::detail::throw_exception(ex);
0372 }
0373 ipv6_value_ = ipv4_value_;
0374 }
0375 }
0376
0377 private:
0378 ipv4_value_type ipv4_value_;
0379 ipv6_value_type ipv6_value_;
0380 };
0381
0382
0383 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
0384 class multicast_request
0385 {
0386 public:
0387
0388 multicast_request()
0389 : ipv4_value_(),
0390 ipv6_value_()
0391 {
0392 }
0393
0394
0395 explicit multicast_request(const address& multicast_address)
0396 : ipv4_value_(),
0397 ipv6_value_()
0398 {
0399 if (multicast_address.is_v6())
0400 {
0401 using namespace std;
0402 address_v6 ipv6_address = multicast_address.to_v6();
0403 address_v6::bytes_type bytes = ipv6_address.to_bytes();
0404 memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);
0405 ipv6_value_.ipv6mr_interface = ipv6_address.scope_id();
0406 }
0407 else
0408 {
0409 ipv4_value_.imr_multiaddr.s_addr =
0410 boost::asio::detail::socket_ops::host_to_network_long(
0411 multicast_address.to_v4().to_uint());
0412 ipv4_value_.imr_interface.s_addr =
0413 boost::asio::detail::socket_ops::host_to_network_long(
0414 address_v4::any().to_uint());
0415 }
0416 }
0417
0418
0419 explicit multicast_request(const address_v4& multicast_address,
0420 const address_v4& network_interface = address_v4::any())
0421 : ipv6_value_()
0422 {
0423 ipv4_value_.imr_multiaddr.s_addr =
0424 boost::asio::detail::socket_ops::host_to_network_long(
0425 multicast_address.to_uint());
0426 ipv4_value_.imr_interface.s_addr =
0427 boost::asio::detail::socket_ops::host_to_network_long(
0428 network_interface.to_uint());
0429 }
0430
0431
0432 explicit multicast_request(
0433 const address_v6& multicast_address,
0434 unsigned long network_interface = 0)
0435 : ipv4_value_()
0436 {
0437 using namespace std;
0438 address_v6::bytes_type bytes = multicast_address.to_bytes();
0439 memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);
0440 if (network_interface)
0441 ipv6_value_.ipv6mr_interface = network_interface;
0442 else
0443 ipv6_value_.ipv6mr_interface = multicast_address.scope_id();
0444 }
0445
0446
0447 template <typename Protocol>
0448 int level(const Protocol& protocol) const
0449 {
0450 if (protocol.family() == PF_INET6)
0451 return IPv6_Level;
0452 return IPv4_Level;
0453 }
0454
0455
0456 template <typename Protocol>
0457 int name(const Protocol& protocol) const
0458 {
0459 if (protocol.family() == PF_INET6)
0460 return IPv6_Name;
0461 return IPv4_Name;
0462 }
0463
0464
0465 template <typename Protocol>
0466 const void* data(const Protocol& protocol) const
0467 {
0468 if (protocol.family() == PF_INET6)
0469 return &ipv6_value_;
0470 return &ipv4_value_;
0471 }
0472
0473
0474 template <typename Protocol>
0475 std::size_t size(const Protocol& protocol) const
0476 {
0477 if (protocol.family() == PF_INET6)
0478 return sizeof(ipv6_value_);
0479 return sizeof(ipv4_value_);
0480 }
0481
0482 private:
0483 boost::asio::detail::in4_mreq_type ipv4_value_;
0484 boost::asio::detail::in6_mreq_type ipv6_value_;
0485 };
0486
0487
0488 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
0489 class network_interface
0490 {
0491 public:
0492
0493 network_interface()
0494 {
0495 ipv4_value_.s_addr =
0496 boost::asio::detail::socket_ops::host_to_network_long(
0497 address_v4::any().to_uint());
0498 ipv6_value_ = 0;
0499 }
0500
0501
0502 explicit network_interface(const address_v4& ipv4_interface)
0503 {
0504 ipv4_value_.s_addr =
0505 boost::asio::detail::socket_ops::host_to_network_long(
0506 ipv4_interface.to_uint());
0507 ipv6_value_ = 0;
0508 }
0509
0510
0511 explicit network_interface(unsigned int ipv6_interface)
0512 {
0513 ipv4_value_.s_addr =
0514 boost::asio::detail::socket_ops::host_to_network_long(
0515 address_v4::any().to_uint());
0516 ipv6_value_ = ipv6_interface;
0517 }
0518
0519
0520 template <typename Protocol>
0521 int level(const Protocol& protocol) const
0522 {
0523 if (protocol.family() == PF_INET6)
0524 return IPv6_Level;
0525 return IPv4_Level;
0526 }
0527
0528
0529 template <typename Protocol>
0530 int name(const Protocol& protocol) const
0531 {
0532 if (protocol.family() == PF_INET6)
0533 return IPv6_Name;
0534 return IPv4_Name;
0535 }
0536
0537
0538 template <typename Protocol>
0539 const void* data(const Protocol& protocol) const
0540 {
0541 if (protocol.family() == PF_INET6)
0542 return &ipv6_value_;
0543 return &ipv4_value_;
0544 }
0545
0546
0547 template <typename Protocol>
0548 std::size_t size(const Protocol& protocol) const
0549 {
0550 if (protocol.family() == PF_INET6)
0551 return sizeof(ipv6_value_);
0552 return sizeof(ipv4_value_);
0553 }
0554
0555 private:
0556 boost::asio::detail::in4_addr_type ipv4_value_;
0557 unsigned int ipv6_value_;
0558 };
0559
0560 }
0561 }
0562 }
0563 }
0564 }
0565
0566 #include <boost/asio/detail/pop_options.hpp>
0567
0568 #endif