Chris@16
|
1 //
|
Chris@16
|
2 // detail/socket_option.hpp
|
Chris@16
|
3 // ~~~~~~~~~~~~~~~~~~~~~~~~
|
Chris@16
|
4 //
|
Chris@101
|
5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
Chris@16
|
6 //
|
Chris@16
|
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
Chris@16
|
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
9 //
|
Chris@16
|
10
|
Chris@16
|
11 #ifndef BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
|
Chris@16
|
12 #define BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
|
Chris@16
|
13
|
Chris@16
|
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
15 # pragma once
|
Chris@16
|
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/asio/detail/config.hpp>
|
Chris@16
|
19 #include <cstddef>
|
Chris@16
|
20 #include <cstring>
|
Chris@16
|
21 #include <stdexcept>
|
Chris@16
|
22 #include <boost/asio/detail/socket_ops.hpp>
|
Chris@16
|
23 #include <boost/asio/detail/socket_types.hpp>
|
Chris@16
|
24 #include <boost/asio/detail/throw_exception.hpp>
|
Chris@16
|
25 #include <boost/asio/ip/address.hpp>
|
Chris@16
|
26
|
Chris@16
|
27 #include <boost/asio/detail/push_options.hpp>
|
Chris@16
|
28
|
Chris@16
|
29 namespace boost {
|
Chris@16
|
30 namespace asio {
|
Chris@16
|
31 namespace ip {
|
Chris@16
|
32 namespace detail {
|
Chris@16
|
33 namespace socket_option {
|
Chris@16
|
34
|
Chris@16
|
35 // Helper template for implementing multicast enable loopback options.
|
Chris@16
|
36 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
|
Chris@16
|
37 class multicast_enable_loopback
|
Chris@16
|
38 {
|
Chris@16
|
39 public:
|
Chris@16
|
40 #if defined(__sun) || defined(__osf__)
|
Chris@16
|
41 typedef unsigned char ipv4_value_type;
|
Chris@16
|
42 typedef unsigned char ipv6_value_type;
|
Chris@16
|
43 #elif defined(_AIX) || defined(__hpux) || defined(__QNXNTO__)
|
Chris@16
|
44 typedef unsigned char ipv4_value_type;
|
Chris@16
|
45 typedef unsigned int ipv6_value_type;
|
Chris@16
|
46 #else
|
Chris@16
|
47 typedef int ipv4_value_type;
|
Chris@16
|
48 typedef int ipv6_value_type;
|
Chris@16
|
49 #endif
|
Chris@16
|
50
|
Chris@16
|
51 // Default constructor.
|
Chris@16
|
52 multicast_enable_loopback()
|
Chris@16
|
53 : ipv4_value_(0),
|
Chris@16
|
54 ipv6_value_(0)
|
Chris@16
|
55 {
|
Chris@16
|
56 }
|
Chris@16
|
57
|
Chris@16
|
58 // Construct with a specific option value.
|
Chris@16
|
59 explicit multicast_enable_loopback(bool v)
|
Chris@16
|
60 : ipv4_value_(v ? 1 : 0),
|
Chris@16
|
61 ipv6_value_(v ? 1 : 0)
|
Chris@16
|
62 {
|
Chris@16
|
63 }
|
Chris@16
|
64
|
Chris@16
|
65 // Set the value of the boolean.
|
Chris@16
|
66 multicast_enable_loopback& operator=(bool v)
|
Chris@16
|
67 {
|
Chris@16
|
68 ipv4_value_ = v ? 1 : 0;
|
Chris@16
|
69 ipv6_value_ = v ? 1 : 0;
|
Chris@16
|
70 return *this;
|
Chris@16
|
71 }
|
Chris@16
|
72
|
Chris@16
|
73 // Get the current value of the boolean.
|
Chris@16
|
74 bool value() const
|
Chris@16
|
75 {
|
Chris@16
|
76 return !!ipv4_value_;
|
Chris@16
|
77 }
|
Chris@16
|
78
|
Chris@16
|
79 // Convert to bool.
|
Chris@16
|
80 operator bool() const
|
Chris@16
|
81 {
|
Chris@16
|
82 return !!ipv4_value_;
|
Chris@16
|
83 }
|
Chris@16
|
84
|
Chris@16
|
85 // Test for false.
|
Chris@16
|
86 bool operator!() const
|
Chris@16
|
87 {
|
Chris@16
|
88 return !ipv4_value_;
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 // Get the level of the socket option.
|
Chris@16
|
92 template <typename Protocol>
|
Chris@16
|
93 int level(const Protocol& protocol) const
|
Chris@16
|
94 {
|
Chris@16
|
95 if (protocol.family() == PF_INET6)
|
Chris@16
|
96 return IPv6_Level;
|
Chris@16
|
97 return IPv4_Level;
|
Chris@16
|
98 }
|
Chris@16
|
99
|
Chris@16
|
100 // Get the name of the socket option.
|
Chris@16
|
101 template <typename Protocol>
|
Chris@16
|
102 int name(const Protocol& protocol) const
|
Chris@16
|
103 {
|
Chris@16
|
104 if (protocol.family() == PF_INET6)
|
Chris@16
|
105 return IPv6_Name;
|
Chris@16
|
106 return IPv4_Name;
|
Chris@16
|
107 }
|
Chris@16
|
108
|
Chris@16
|
109 // Get the address of the boolean data.
|
Chris@16
|
110 template <typename Protocol>
|
Chris@16
|
111 void* data(const Protocol& protocol)
|
Chris@16
|
112 {
|
Chris@16
|
113 if (protocol.family() == PF_INET6)
|
Chris@16
|
114 return &ipv6_value_;
|
Chris@16
|
115 return &ipv4_value_;
|
Chris@16
|
116 }
|
Chris@16
|
117
|
Chris@16
|
118 // Get the address of the boolean data.
|
Chris@16
|
119 template <typename Protocol>
|
Chris@16
|
120 const void* data(const Protocol& protocol) const
|
Chris@16
|
121 {
|
Chris@16
|
122 if (protocol.family() == PF_INET6)
|
Chris@16
|
123 return &ipv6_value_;
|
Chris@16
|
124 return &ipv4_value_;
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 // Get the size of the boolean data.
|
Chris@16
|
128 template <typename Protocol>
|
Chris@16
|
129 std::size_t size(const Protocol& protocol) const
|
Chris@16
|
130 {
|
Chris@16
|
131 if (protocol.family() == PF_INET6)
|
Chris@16
|
132 return sizeof(ipv6_value_);
|
Chris@16
|
133 return sizeof(ipv4_value_);
|
Chris@16
|
134 }
|
Chris@16
|
135
|
Chris@16
|
136 // Set the size of the boolean data.
|
Chris@16
|
137 template <typename Protocol>
|
Chris@16
|
138 void resize(const Protocol& protocol, std::size_t s)
|
Chris@16
|
139 {
|
Chris@16
|
140 if (protocol.family() == PF_INET6)
|
Chris@16
|
141 {
|
Chris@16
|
142 if (s != sizeof(ipv6_value_))
|
Chris@16
|
143 {
|
Chris@16
|
144 std::length_error ex("multicast_enable_loopback socket option resize");
|
Chris@16
|
145 boost::asio::detail::throw_exception(ex);
|
Chris@16
|
146 }
|
Chris@16
|
147 ipv4_value_ = ipv6_value_ ? 1 : 0;
|
Chris@16
|
148 }
|
Chris@16
|
149 else
|
Chris@16
|
150 {
|
Chris@16
|
151 if (s != sizeof(ipv4_value_))
|
Chris@16
|
152 {
|
Chris@16
|
153 std::length_error ex("multicast_enable_loopback socket option resize");
|
Chris@16
|
154 boost::asio::detail::throw_exception(ex);
|
Chris@16
|
155 }
|
Chris@16
|
156 ipv6_value_ = ipv4_value_ ? 1 : 0;
|
Chris@16
|
157 }
|
Chris@16
|
158 }
|
Chris@16
|
159
|
Chris@16
|
160 private:
|
Chris@16
|
161 ipv4_value_type ipv4_value_;
|
Chris@16
|
162 ipv6_value_type ipv6_value_;
|
Chris@16
|
163 };
|
Chris@16
|
164
|
Chris@16
|
165 // Helper template for implementing unicast hops options.
|
Chris@16
|
166 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
|
Chris@16
|
167 class unicast_hops
|
Chris@16
|
168 {
|
Chris@16
|
169 public:
|
Chris@16
|
170 // Default constructor.
|
Chris@16
|
171 unicast_hops()
|
Chris@16
|
172 : value_(0)
|
Chris@16
|
173 {
|
Chris@16
|
174 }
|
Chris@16
|
175
|
Chris@16
|
176 // Construct with a specific option value.
|
Chris@16
|
177 explicit unicast_hops(int v)
|
Chris@16
|
178 : value_(v)
|
Chris@16
|
179 {
|
Chris@16
|
180 }
|
Chris@16
|
181
|
Chris@16
|
182 // Set the value of the option.
|
Chris@16
|
183 unicast_hops& operator=(int v)
|
Chris@16
|
184 {
|
Chris@16
|
185 value_ = v;
|
Chris@16
|
186 return *this;
|
Chris@16
|
187 }
|
Chris@16
|
188
|
Chris@16
|
189 // Get the current value of the option.
|
Chris@16
|
190 int value() const
|
Chris@16
|
191 {
|
Chris@16
|
192 return value_;
|
Chris@16
|
193 }
|
Chris@16
|
194
|
Chris@16
|
195 // Get the level of the socket option.
|
Chris@16
|
196 template <typename Protocol>
|
Chris@16
|
197 int level(const Protocol& protocol) const
|
Chris@16
|
198 {
|
Chris@16
|
199 if (protocol.family() == PF_INET6)
|
Chris@16
|
200 return IPv6_Level;
|
Chris@16
|
201 return IPv4_Level;
|
Chris@16
|
202 }
|
Chris@16
|
203
|
Chris@16
|
204 // Get the name of the socket option.
|
Chris@16
|
205 template <typename Protocol>
|
Chris@16
|
206 int name(const Protocol& protocol) const
|
Chris@16
|
207 {
|
Chris@16
|
208 if (protocol.family() == PF_INET6)
|
Chris@16
|
209 return IPv6_Name;
|
Chris@16
|
210 return IPv4_Name;
|
Chris@16
|
211 }
|
Chris@16
|
212
|
Chris@16
|
213 // Get the address of the data.
|
Chris@16
|
214 template <typename Protocol>
|
Chris@16
|
215 int* data(const Protocol&)
|
Chris@16
|
216 {
|
Chris@16
|
217 return &value_;
|
Chris@16
|
218 }
|
Chris@16
|
219
|
Chris@16
|
220 // Get the address of the data.
|
Chris@16
|
221 template <typename Protocol>
|
Chris@16
|
222 const int* data(const Protocol&) const
|
Chris@16
|
223 {
|
Chris@16
|
224 return &value_;
|
Chris@16
|
225 }
|
Chris@16
|
226
|
Chris@16
|
227 // Get the size of the data.
|
Chris@16
|
228 template <typename Protocol>
|
Chris@16
|
229 std::size_t size(const Protocol&) const
|
Chris@16
|
230 {
|
Chris@16
|
231 return sizeof(value_);
|
Chris@16
|
232 }
|
Chris@16
|
233
|
Chris@16
|
234 // Set the size of the data.
|
Chris@16
|
235 template <typename Protocol>
|
Chris@16
|
236 void resize(const Protocol&, std::size_t s)
|
Chris@16
|
237 {
|
Chris@16
|
238 if (s != sizeof(value_))
|
Chris@16
|
239 {
|
Chris@16
|
240 std::length_error ex("unicast hops socket option resize");
|
Chris@16
|
241 boost::asio::detail::throw_exception(ex);
|
Chris@16
|
242 }
|
Chris@16
|
243 #if defined(__hpux)
|
Chris@16
|
244 if (value_ < 0)
|
Chris@16
|
245 value_ = value_ & 0xFF;
|
Chris@16
|
246 #endif
|
Chris@16
|
247 }
|
Chris@16
|
248
|
Chris@16
|
249 private:
|
Chris@16
|
250 int value_;
|
Chris@16
|
251 };
|
Chris@16
|
252
|
Chris@16
|
253 // Helper template for implementing multicast hops options.
|
Chris@16
|
254 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
|
Chris@16
|
255 class multicast_hops
|
Chris@16
|
256 {
|
Chris@16
|
257 public:
|
Chris@16
|
258 #if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
|
Chris@16
|
259 typedef int ipv4_value_type;
|
Chris@16
|
260 #else
|
Chris@16
|
261 typedef unsigned char ipv4_value_type;
|
Chris@16
|
262 #endif
|
Chris@16
|
263 typedef int ipv6_value_type;
|
Chris@16
|
264
|
Chris@16
|
265 // Default constructor.
|
Chris@16
|
266 multicast_hops()
|
Chris@16
|
267 : ipv4_value_(0),
|
Chris@16
|
268 ipv6_value_(0)
|
Chris@16
|
269 {
|
Chris@16
|
270 }
|
Chris@16
|
271
|
Chris@16
|
272 // Construct with a specific option value.
|
Chris@16
|
273 explicit multicast_hops(int v)
|
Chris@16
|
274 {
|
Chris@16
|
275 if (v < 0 || v > 255)
|
Chris@16
|
276 {
|
Chris@16
|
277 std::out_of_range ex("multicast hops value out of range");
|
Chris@16
|
278 boost::asio::detail::throw_exception(ex);
|
Chris@16
|
279 }
|
Chris@16
|
280 ipv4_value_ = (ipv4_value_type)v;
|
Chris@16
|
281 ipv6_value_ = v;
|
Chris@16
|
282 }
|
Chris@16
|
283
|
Chris@16
|
284 // Set the value of the option.
|
Chris@16
|
285 multicast_hops& operator=(int v)
|
Chris@16
|
286 {
|
Chris@16
|
287 if (v < 0 || v > 255)
|
Chris@16
|
288 {
|
Chris@16
|
289 std::out_of_range ex("multicast hops value out of range");
|
Chris@16
|
290 boost::asio::detail::throw_exception(ex);
|
Chris@16
|
291 }
|
Chris@16
|
292 ipv4_value_ = (ipv4_value_type)v;
|
Chris@16
|
293 ipv6_value_ = v;
|
Chris@16
|
294 return *this;
|
Chris@16
|
295 }
|
Chris@16
|
296
|
Chris@16
|
297 // Get the current value of the option.
|
Chris@16
|
298 int value() const
|
Chris@16
|
299 {
|
Chris@16
|
300 return ipv6_value_;
|
Chris@16
|
301 }
|
Chris@16
|
302
|
Chris@16
|
303 // Get the level of the socket option.
|
Chris@16
|
304 template <typename Protocol>
|
Chris@16
|
305 int level(const Protocol& protocol) const
|
Chris@16
|
306 {
|
Chris@16
|
307 if (protocol.family() == PF_INET6)
|
Chris@16
|
308 return IPv6_Level;
|
Chris@16
|
309 return IPv4_Level;
|
Chris@16
|
310 }
|
Chris@16
|
311
|
Chris@16
|
312 // Get the name of the socket option.
|
Chris@16
|
313 template <typename Protocol>
|
Chris@16
|
314 int name(const Protocol& protocol) const
|
Chris@16
|
315 {
|
Chris@16
|
316 if (protocol.family() == PF_INET6)
|
Chris@16
|
317 return IPv6_Name;
|
Chris@16
|
318 return IPv4_Name;
|
Chris@16
|
319 }
|
Chris@16
|
320
|
Chris@16
|
321 // Get the address of the data.
|
Chris@16
|
322 template <typename Protocol>
|
Chris@16
|
323 void* data(const Protocol& protocol)
|
Chris@16
|
324 {
|
Chris@16
|
325 if (protocol.family() == PF_INET6)
|
Chris@16
|
326 return &ipv6_value_;
|
Chris@16
|
327 return &ipv4_value_;
|
Chris@16
|
328 }
|
Chris@16
|
329
|
Chris@16
|
330 // Get the address of the data.
|
Chris@16
|
331 template <typename Protocol>
|
Chris@16
|
332 const void* data(const Protocol& protocol) const
|
Chris@16
|
333 {
|
Chris@16
|
334 if (protocol.family() == PF_INET6)
|
Chris@16
|
335 return &ipv6_value_;
|
Chris@16
|
336 return &ipv4_value_;
|
Chris@16
|
337 }
|
Chris@16
|
338
|
Chris@16
|
339 // Get the size of the data.
|
Chris@16
|
340 template <typename Protocol>
|
Chris@16
|
341 std::size_t size(const Protocol& protocol) const
|
Chris@16
|
342 {
|
Chris@16
|
343 if (protocol.family() == PF_INET6)
|
Chris@16
|
344 return sizeof(ipv6_value_);
|
Chris@16
|
345 return sizeof(ipv4_value_);
|
Chris@16
|
346 }
|
Chris@16
|
347
|
Chris@16
|
348 // Set the size of the data.
|
Chris@16
|
349 template <typename Protocol>
|
Chris@16
|
350 void resize(const Protocol& protocol, std::size_t s)
|
Chris@16
|
351 {
|
Chris@16
|
352 if (protocol.family() == PF_INET6)
|
Chris@16
|
353 {
|
Chris@16
|
354 if (s != sizeof(ipv6_value_))
|
Chris@16
|
355 {
|
Chris@16
|
356 std::length_error ex("multicast hops socket option resize");
|
Chris@16
|
357 boost::asio::detail::throw_exception(ex);
|
Chris@16
|
358 }
|
Chris@16
|
359 if (ipv6_value_ < 0)
|
Chris@16
|
360 ipv4_value_ = 0;
|
Chris@16
|
361 else if (ipv6_value_ > 255)
|
Chris@16
|
362 ipv4_value_ = 255;
|
Chris@16
|
363 else
|
Chris@16
|
364 ipv4_value_ = (ipv4_value_type)ipv6_value_;
|
Chris@16
|
365 }
|
Chris@16
|
366 else
|
Chris@16
|
367 {
|
Chris@16
|
368 if (s != sizeof(ipv4_value_))
|
Chris@16
|
369 {
|
Chris@16
|
370 std::length_error ex("multicast hops socket option resize");
|
Chris@16
|
371 boost::asio::detail::throw_exception(ex);
|
Chris@16
|
372 }
|
Chris@16
|
373 ipv6_value_ = ipv4_value_;
|
Chris@16
|
374 }
|
Chris@16
|
375 }
|
Chris@16
|
376
|
Chris@16
|
377 private:
|
Chris@16
|
378 ipv4_value_type ipv4_value_;
|
Chris@16
|
379 ipv6_value_type ipv6_value_;
|
Chris@16
|
380 };
|
Chris@16
|
381
|
Chris@16
|
382 // Helper template for implementing ip_mreq-based options.
|
Chris@16
|
383 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
|
Chris@16
|
384 class multicast_request
|
Chris@16
|
385 {
|
Chris@16
|
386 public:
|
Chris@16
|
387 // Default constructor.
|
Chris@16
|
388 multicast_request()
|
Chris@16
|
389 : ipv4_value_(), // Zero-initialisation gives the "any" address.
|
Chris@16
|
390 ipv6_value_() // Zero-initialisation gives the "any" address.
|
Chris@16
|
391 {
|
Chris@16
|
392 }
|
Chris@16
|
393
|
Chris@16
|
394 // Construct with multicast address only.
|
Chris@16
|
395 explicit multicast_request(const boost::asio::ip::address& multicast_address)
|
Chris@16
|
396 : ipv4_value_(), // Zero-initialisation gives the "any" address.
|
Chris@16
|
397 ipv6_value_() // Zero-initialisation gives the "any" address.
|
Chris@16
|
398 {
|
Chris@16
|
399 if (multicast_address.is_v6())
|
Chris@16
|
400 {
|
Chris@16
|
401 using namespace std; // For memcpy.
|
Chris@16
|
402 boost::asio::ip::address_v6 ipv6_address = multicast_address.to_v6();
|
Chris@16
|
403 boost::asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes();
|
Chris@16
|
404 memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);
|
Chris@101
|
405 ipv6_value_.ipv6mr_interface = ipv6_address.scope_id();
|
Chris@16
|
406 }
|
Chris@16
|
407 else
|
Chris@16
|
408 {
|
Chris@16
|
409 ipv4_value_.imr_multiaddr.s_addr =
|
Chris@16
|
410 boost::asio::detail::socket_ops::host_to_network_long(
|
Chris@16
|
411 multicast_address.to_v4().to_ulong());
|
Chris@16
|
412 ipv4_value_.imr_interface.s_addr =
|
Chris@16
|
413 boost::asio::detail::socket_ops::host_to_network_long(
|
Chris@16
|
414 boost::asio::ip::address_v4::any().to_ulong());
|
Chris@16
|
415 }
|
Chris@16
|
416 }
|
Chris@16
|
417
|
Chris@16
|
418 // Construct with multicast address and IPv4 address specifying an interface.
|
Chris@16
|
419 explicit multicast_request(
|
Chris@16
|
420 const boost::asio::ip::address_v4& multicast_address,
|
Chris@16
|
421 const boost::asio::ip::address_v4& network_interface
|
Chris@16
|
422 = boost::asio::ip::address_v4::any())
|
Chris@16
|
423 : ipv6_value_() // Zero-initialisation gives the "any" address.
|
Chris@16
|
424 {
|
Chris@16
|
425 ipv4_value_.imr_multiaddr.s_addr =
|
Chris@16
|
426 boost::asio::detail::socket_ops::host_to_network_long(
|
Chris@16
|
427 multicast_address.to_ulong());
|
Chris@16
|
428 ipv4_value_.imr_interface.s_addr =
|
Chris@16
|
429 boost::asio::detail::socket_ops::host_to_network_long(
|
Chris@16
|
430 network_interface.to_ulong());
|
Chris@16
|
431 }
|
Chris@16
|
432
|
Chris@16
|
433 // Construct with multicast address and IPv6 network interface index.
|
Chris@16
|
434 explicit multicast_request(
|
Chris@16
|
435 const boost::asio::ip::address_v6& multicast_address,
|
Chris@16
|
436 unsigned long network_interface = 0)
|
Chris@16
|
437 : ipv4_value_() // Zero-initialisation gives the "any" address.
|
Chris@16
|
438 {
|
Chris@16
|
439 using namespace std; // For memcpy.
|
Chris@16
|
440 boost::asio::ip::address_v6::bytes_type bytes =
|
Chris@16
|
441 multicast_address.to_bytes();
|
Chris@16
|
442 memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);
|
Chris@101
|
443 if (network_interface)
|
Chris@101
|
444 ipv6_value_.ipv6mr_interface = network_interface;
|
Chris@101
|
445 else
|
Chris@101
|
446 ipv6_value_.ipv6mr_interface = multicast_address.scope_id();
|
Chris@16
|
447 }
|
Chris@16
|
448
|
Chris@16
|
449 // Get the level of the socket option.
|
Chris@16
|
450 template <typename Protocol>
|
Chris@16
|
451 int level(const Protocol& protocol) const
|
Chris@16
|
452 {
|
Chris@16
|
453 if (protocol.family() == PF_INET6)
|
Chris@16
|
454 return IPv6_Level;
|
Chris@16
|
455 return IPv4_Level;
|
Chris@16
|
456 }
|
Chris@16
|
457
|
Chris@16
|
458 // Get the name of the socket option.
|
Chris@16
|
459 template <typename Protocol>
|
Chris@16
|
460 int name(const Protocol& protocol) const
|
Chris@16
|
461 {
|
Chris@16
|
462 if (protocol.family() == PF_INET6)
|
Chris@16
|
463 return IPv6_Name;
|
Chris@16
|
464 return IPv4_Name;
|
Chris@16
|
465 }
|
Chris@16
|
466
|
Chris@16
|
467 // Get the address of the option data.
|
Chris@16
|
468 template <typename Protocol>
|
Chris@16
|
469 const void* data(const Protocol& protocol) const
|
Chris@16
|
470 {
|
Chris@16
|
471 if (protocol.family() == PF_INET6)
|
Chris@16
|
472 return &ipv6_value_;
|
Chris@16
|
473 return &ipv4_value_;
|
Chris@16
|
474 }
|
Chris@16
|
475
|
Chris@16
|
476 // Get the size of the option data.
|
Chris@16
|
477 template <typename Protocol>
|
Chris@16
|
478 std::size_t size(const Protocol& protocol) const
|
Chris@16
|
479 {
|
Chris@16
|
480 if (protocol.family() == PF_INET6)
|
Chris@16
|
481 return sizeof(ipv6_value_);
|
Chris@16
|
482 return sizeof(ipv4_value_);
|
Chris@16
|
483 }
|
Chris@16
|
484
|
Chris@16
|
485 private:
|
Chris@16
|
486 boost::asio::detail::in4_mreq_type ipv4_value_;
|
Chris@16
|
487 boost::asio::detail::in6_mreq_type ipv6_value_;
|
Chris@16
|
488 };
|
Chris@16
|
489
|
Chris@16
|
490 // Helper template for implementing options that specify a network interface.
|
Chris@16
|
491 template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
|
Chris@16
|
492 class network_interface
|
Chris@16
|
493 {
|
Chris@16
|
494 public:
|
Chris@16
|
495 // Default constructor.
|
Chris@16
|
496 network_interface()
|
Chris@16
|
497 {
|
Chris@16
|
498 ipv4_value_.s_addr =
|
Chris@16
|
499 boost::asio::detail::socket_ops::host_to_network_long(
|
Chris@16
|
500 boost::asio::ip::address_v4::any().to_ulong());
|
Chris@16
|
501 ipv6_value_ = 0;
|
Chris@16
|
502 }
|
Chris@16
|
503
|
Chris@16
|
504 // Construct with IPv4 interface.
|
Chris@16
|
505 explicit network_interface(const boost::asio::ip::address_v4& ipv4_interface)
|
Chris@16
|
506 {
|
Chris@16
|
507 ipv4_value_.s_addr =
|
Chris@16
|
508 boost::asio::detail::socket_ops::host_to_network_long(
|
Chris@16
|
509 ipv4_interface.to_ulong());
|
Chris@16
|
510 ipv6_value_ = 0;
|
Chris@16
|
511 }
|
Chris@16
|
512
|
Chris@16
|
513 // Construct with IPv6 interface.
|
Chris@16
|
514 explicit network_interface(unsigned int ipv6_interface)
|
Chris@16
|
515 {
|
Chris@16
|
516 ipv4_value_.s_addr =
|
Chris@16
|
517 boost::asio::detail::socket_ops::host_to_network_long(
|
Chris@16
|
518 boost::asio::ip::address_v4::any().to_ulong());
|
Chris@16
|
519 ipv6_value_ = ipv6_interface;
|
Chris@16
|
520 }
|
Chris@16
|
521
|
Chris@16
|
522 // Get the level of the socket option.
|
Chris@16
|
523 template <typename Protocol>
|
Chris@16
|
524 int level(const Protocol& protocol) const
|
Chris@16
|
525 {
|
Chris@16
|
526 if (protocol.family() == PF_INET6)
|
Chris@16
|
527 return IPv6_Level;
|
Chris@16
|
528 return IPv4_Level;
|
Chris@16
|
529 }
|
Chris@16
|
530
|
Chris@16
|
531 // Get the name of the socket option.
|
Chris@16
|
532 template <typename Protocol>
|
Chris@16
|
533 int name(const Protocol& protocol) const
|
Chris@16
|
534 {
|
Chris@16
|
535 if (protocol.family() == PF_INET6)
|
Chris@16
|
536 return IPv6_Name;
|
Chris@16
|
537 return IPv4_Name;
|
Chris@16
|
538 }
|
Chris@16
|
539
|
Chris@16
|
540 // Get the address of the option data.
|
Chris@16
|
541 template <typename Protocol>
|
Chris@16
|
542 const void* data(const Protocol& protocol) const
|
Chris@16
|
543 {
|
Chris@16
|
544 if (protocol.family() == PF_INET6)
|
Chris@16
|
545 return &ipv6_value_;
|
Chris@16
|
546 return &ipv4_value_;
|
Chris@16
|
547 }
|
Chris@16
|
548
|
Chris@16
|
549 // Get the size of the option data.
|
Chris@16
|
550 template <typename Protocol>
|
Chris@16
|
551 std::size_t size(const Protocol& protocol) const
|
Chris@16
|
552 {
|
Chris@16
|
553 if (protocol.family() == PF_INET6)
|
Chris@16
|
554 return sizeof(ipv6_value_);
|
Chris@16
|
555 return sizeof(ipv4_value_);
|
Chris@16
|
556 }
|
Chris@16
|
557
|
Chris@16
|
558 private:
|
Chris@16
|
559 boost::asio::detail::in4_addr_type ipv4_value_;
|
Chris@16
|
560 unsigned int ipv6_value_;
|
Chris@16
|
561 };
|
Chris@16
|
562
|
Chris@16
|
563 } // namespace socket_option
|
Chris@16
|
564 } // namespace detail
|
Chris@16
|
565 } // namespace ip
|
Chris@16
|
566 } // namespace asio
|
Chris@16
|
567 } // namespace boost
|
Chris@16
|
568
|
Chris@16
|
569 #include <boost/asio/detail/pop_options.hpp>
|
Chris@16
|
570
|
Chris@16
|
571 #endif // BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
|