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