Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / asio / ip / detail / socket_option.hpp @ 2486

History | View | Annotate | Download (14.1 kB)

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 BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
12
#define BOOST_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 <boost/asio/detail/config.hpp>
19
#include <cstddef>
20
#include <cstring>
21
#include <stdexcept>
22
#include <boost/asio/detail/socket_ops.hpp>
23
#include <boost/asio/detail/socket_types.hpp>
24
#include <boost/asio/detail/throw_exception.hpp>
25
#include <boost/asio/ip/address.hpp>
26

    
27
#include <boost/asio/detail/push_options.hpp>
28

    
29
namespace boost {
30
namespace asio {
31
namespace ip {
32
namespace detail {
33
namespace socket_option {
34

    
35
// Helper template for implementing multicast enable loopback options.
36
template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
37
class multicast_enable_loopback
38
{
39
public:
40
#if defined(__sun) || defined(__osf__)
41
  typedef unsigned char ipv4_value_type;
42
  typedef unsigned char ipv6_value_type;
43
#elif defined(_AIX) || defined(__hpux) || defined(__QNXNTO__) 
44
  typedef unsigned char ipv4_value_type;
45
  typedef unsigned int ipv6_value_type;
46
#else
47
  typedef int ipv4_value_type;
48
  typedef int ipv6_value_type;
49
#endif
50

    
51
  // Default constructor.
52
  multicast_enable_loopback()
53
    : ipv4_value_(0),
54
      ipv6_value_(0)
55
  {
56
  }
57

    
58
  // Construct with a specific option value.
59
  explicit multicast_enable_loopback(bool v)
60
    : ipv4_value_(v ? 1 : 0),
61
      ipv6_value_(v ? 1 : 0)
62
  {
63
  }
64

    
65
  // Set the value of the boolean.
66
  multicast_enable_loopback& operator=(bool v)
67
  {
68
    ipv4_value_ = v ? 1 : 0;
69
    ipv6_value_ = v ? 1 : 0;
70
    return *this;
71
  }
72

    
73
  // Get the current value of the boolean.
74
  bool value() const
75
  {
76
    return !!ipv4_value_;
77
  }
78

    
79
  // Convert to bool.
80
  operator bool() const
81
  {
82
    return !!ipv4_value_;
83
  }
84

    
85
  // Test for false.
86
  bool operator!() const
87
  {
88
    return !ipv4_value_;
89
  }
90

    
91
  // Get the level of the socket option.
92
  template <typename Protocol>
93
  int level(const Protocol& protocol) const
94
  {
95
    if (protocol.family() == PF_INET6)
96
      return IPv6_Level;
97
    return IPv4_Level;
98
  }
99

    
100
  // Get the name of the socket option.
101
  template <typename Protocol>
102
  int name(const Protocol& protocol) const
103
  {
104
    if (protocol.family() == PF_INET6)
105
      return IPv6_Name;
106
    return IPv4_Name;
107
  }
108

    
109
  // Get the address of the boolean data.
110
  template <typename Protocol>
111
  void* data(const Protocol& protocol)
112
  {
113
    if (protocol.family() == PF_INET6)
114
      return &ipv6_value_;
115
    return &ipv4_value_;
116
  }
117

    
118
  // Get the address of the boolean data.
119
  template <typename Protocol>
120
  const void* data(const Protocol& protocol) const
121
  {
122
    if (protocol.family() == PF_INET6)
123
      return &ipv6_value_;
124
    return &ipv4_value_;
125
  }
126

    
127
  // Get the size of the boolean data.
128
  template <typename Protocol>
129
  std::size_t size(const Protocol& protocol) const
130
  {
131
    if (protocol.family() == PF_INET6)
132
      return sizeof(ipv6_value_);
133
    return sizeof(ipv4_value_);
134
  }
135

    
136
  // Set the size of the boolean data.
137
  template <typename Protocol>
138
  void resize(const Protocol& protocol, std::size_t s)
139
  {
140
    if (protocol.family() == PF_INET6)
141
    {
142
      if (s != sizeof(ipv6_value_))
143
      {
144
        std::length_error ex("multicast_enable_loopback socket option resize");
145
        boost::asio::detail::throw_exception(ex);
146
      }
147
      ipv4_value_ = ipv6_value_ ? 1 : 0;
148
    }
149
    else
150
    {
151
      if (s != sizeof(ipv4_value_))
152
      {
153
        std::length_error ex("multicast_enable_loopback socket option resize");
154
        boost::asio::detail::throw_exception(ex);
155
      }
156
      ipv6_value_ = ipv4_value_ ? 1 : 0;
157
    }
158
  }
159

    
160
private:
161
  ipv4_value_type ipv4_value_;
162
  ipv6_value_type ipv6_value_;
163
};
164

    
165
// Helper template for implementing unicast hops options.
166
template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
167
class unicast_hops
168
{
169
public:
170
  // Default constructor.
171
  unicast_hops()
172
    : value_(0)
173
  {
174
  }
175

    
176
  // Construct with a specific option value.
177
  explicit unicast_hops(int v)
178
    : value_(v)
179
  {
180
  }
181

    
182
  // Set the value of the option.
183
  unicast_hops& operator=(int v)
184
  {
185
    value_ = v;
186
    return *this;
187
  }
188

    
189
  // Get the current value of the option.
190
  int value() const
191
  {
192
    return value_;
193
  }
194

    
195
  // Get the level of the socket option.
196
  template <typename Protocol>
197
  int level(const Protocol& protocol) const
198
  {
199
    if (protocol.family() == PF_INET6)
200
      return IPv6_Level;
201
    return IPv4_Level;
202
  }
203

    
204
  // Get the name of the socket option.
205
  template <typename Protocol>
206
  int name(const Protocol& protocol) const
207
  {
208
    if (protocol.family() == PF_INET6)
209
      return IPv6_Name;
210
    return IPv4_Name;
211
  }
212

    
213
  // Get the address of the data.
214
  template <typename Protocol>
215
  int* data(const Protocol&)
216
  {
217
    return &value_;
218
  }
219

    
220
  // Get the address of the data.
221
  template <typename Protocol>
222
  const int* data(const Protocol&) const
223
  {
224
    return &value_;
225
  }
226

    
227
  // Get the size of the data.
228
  template <typename Protocol>
229
  std::size_t size(const Protocol&) const
230
  {
231
    return sizeof(value_);
232
  }
233

    
234
  // Set the size of the data.
235
  template <typename Protocol>
236
  void resize(const Protocol&, std::size_t s)
237
  {
238
    if (s != sizeof(value_))
239
    {
240
      std::length_error ex("unicast hops socket option resize");
241
      boost::asio::detail::throw_exception(ex);
242
    }
243
#if defined(__hpux)
244
    if (value_ < 0)
245
      value_ = value_ & 0xFF;
246
#endif
247
  }
248

    
249
private:
250
  int value_;
251
};
252

    
253
// Helper template for implementing multicast hops options.
254
template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
255
class multicast_hops
256
{
257
public:
258
#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
259
  typedef int ipv4_value_type;
260
#else
261
  typedef unsigned char ipv4_value_type;
262
#endif
263
  typedef int ipv6_value_type;
264

    
265
  // Default constructor.
266
  multicast_hops()
267
    : ipv4_value_(0),
268
      ipv6_value_(0)
269
  {
270
  }
271

    
272
  // Construct with a specific option value.
273
  explicit multicast_hops(int v)
274
  {
275
    if (v < 0 || v > 255)
276
    {
277
      std::out_of_range ex("multicast hops value out of range");
278
      boost::asio::detail::throw_exception(ex);
279
    }
280
    ipv4_value_ = (ipv4_value_type)v;
281
    ipv6_value_ = v;
282
  }
283

    
284
  // Set the value of the option.
285
  multicast_hops& operator=(int v)
286
  {
287
    if (v < 0 || v > 255)
288
    {
289
      std::out_of_range ex("multicast hops value out of range");
290
      boost::asio::detail::throw_exception(ex);
291
    }
292
    ipv4_value_ = (ipv4_value_type)v;
293
    ipv6_value_ = v;
294
    return *this;
295
  }
296

    
297
  // Get the current value of the option.
298
  int value() const
299
  {
300
    return ipv6_value_;
301
  }
302

    
303
  // Get the level of the socket option.
304
  template <typename Protocol>
305
  int level(const Protocol& protocol) const
306
  {
307
    if (protocol.family() == PF_INET6)
308
      return IPv6_Level;
309
    return IPv4_Level;
310
  }
311

    
312
  // Get the name of the socket option.
313
  template <typename Protocol>
314
  int name(const Protocol& protocol) const
315
  {
316
    if (protocol.family() == PF_INET6)
317
      return IPv6_Name;
318
    return IPv4_Name;
319
  }
320

    
321
  // Get the address of the data.
322
  template <typename Protocol>
323
  void* data(const Protocol& protocol)
324
  {
325
    if (protocol.family() == PF_INET6)
326
      return &ipv6_value_;
327
    return &ipv4_value_;
328
  }
329

    
330
  // Get the address of the data.
331
  template <typename Protocol>
332
  const void* data(const Protocol& protocol) const
333
  {
334
    if (protocol.family() == PF_INET6)
335
      return &ipv6_value_;
336
    return &ipv4_value_;
337
  }
338

    
339
  // Get the size of the data.
340
  template <typename Protocol>
341
  std::size_t size(const Protocol& protocol) const
342
  {
343
    if (protocol.family() == PF_INET6)
344
      return sizeof(ipv6_value_);
345
    return sizeof(ipv4_value_);
346
  }
347

    
348
  // Set the size of the data.
349
  template <typename Protocol>
350
  void resize(const Protocol& protocol, std::size_t s)
351
  {
352
    if (protocol.family() == PF_INET6)
353
    {
354
      if (s != sizeof(ipv6_value_))
355
      {
356
        std::length_error ex("multicast hops socket option resize");
357
        boost::asio::detail::throw_exception(ex);
358
      }
359
      if (ipv6_value_ < 0)
360
        ipv4_value_ = 0;
361
      else if (ipv6_value_ > 255)
362
        ipv4_value_ = 255;
363
      else
364
        ipv4_value_ = (ipv4_value_type)ipv6_value_;
365
    }
366
    else
367
    {
368
      if (s != sizeof(ipv4_value_))
369
      {
370
        std::length_error ex("multicast hops socket option resize");
371
        boost::asio::detail::throw_exception(ex);
372
      }
373
      ipv6_value_ = ipv4_value_;
374
    }
375
  }
376

    
377
private:
378
  ipv4_value_type ipv4_value_;
379
  ipv6_value_type ipv6_value_;
380
};
381

    
382
// Helper template for implementing ip_mreq-based options.
383
template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
384
class multicast_request
385
{
386
public:
387
  // Default constructor.
388
  multicast_request()
389
    : ipv4_value_(), // Zero-initialisation gives the "any" address.
390
      ipv6_value_() // Zero-initialisation gives the "any" address.
391
  {
392
  }
393

    
394
  // Construct with multicast address only.
395
  explicit multicast_request(const boost::asio::ip::address& multicast_address)
396
    : ipv4_value_(), // Zero-initialisation gives the "any" address.
397
      ipv6_value_() // Zero-initialisation gives the "any" address.
398
  {
399
    if (multicast_address.is_v6())
400
    {
401
      using namespace std; // For memcpy.
402
      boost::asio::ip::address_v6 ipv6_address = multicast_address.to_v6();
403
      boost::asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes();
404
      memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);
405
      ipv6_value_.ipv6mr_interface = ipv6_address.scope_id();
406
    }
407
    else
408
    {
409
      ipv4_value_.imr_multiaddr.s_addr =
410
        boost::asio::detail::socket_ops::host_to_network_long(
411
            multicast_address.to_v4().to_ulong());
412
      ipv4_value_.imr_interface.s_addr =
413
        boost::asio::detail::socket_ops::host_to_network_long(
414
            boost::asio::ip::address_v4::any().to_ulong());
415
    }
416
  }
417

    
418
  // Construct with multicast address and IPv4 address specifying an interface.
419
  explicit multicast_request(
420
      const boost::asio::ip::address_v4& multicast_address,
421
      const boost::asio::ip::address_v4& network_interface
422
        = boost::asio::ip::address_v4::any())
423
    : ipv6_value_() // Zero-initialisation gives the "any" address.
424
  {
425
    ipv4_value_.imr_multiaddr.s_addr =
426
      boost::asio::detail::socket_ops::host_to_network_long(
427
          multicast_address.to_ulong());
428
    ipv4_value_.imr_interface.s_addr =
429
      boost::asio::detail::socket_ops::host_to_network_long(
430
          network_interface.to_ulong());
431
  }
432

    
433
  // Construct with multicast address and IPv6 network interface index.
434
  explicit multicast_request(
435
      const boost::asio::ip::address_v6& multicast_address,
436
      unsigned long network_interface = 0)
437
    : ipv4_value_() // Zero-initialisation gives the "any" address.
438
  {
439
    using namespace std; // For memcpy.
440
    boost::asio::ip::address_v6::bytes_type bytes =
441
      multicast_address.to_bytes();
442
    memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);
443
    if (network_interface)
444
      ipv6_value_.ipv6mr_interface = network_interface;
445
    else
446
      ipv6_value_.ipv6mr_interface = multicast_address.scope_id();
447
  }
448

    
449
  // Get the level of the socket option.
450
  template <typename Protocol>
451
  int level(const Protocol& protocol) const
452
  {
453
    if (protocol.family() == PF_INET6)
454
      return IPv6_Level;
455
    return IPv4_Level;
456
  }
457

    
458
  // Get the name of the socket option.
459
  template <typename Protocol>
460
  int name(const Protocol& protocol) const
461
  {
462
    if (protocol.family() == PF_INET6)
463
      return IPv6_Name;
464
    return IPv4_Name;
465
  }
466

    
467
  // Get the address of the option data.
468
  template <typename Protocol>
469
  const void* data(const Protocol& protocol) const
470
  {
471
    if (protocol.family() == PF_INET6)
472
      return &ipv6_value_;
473
    return &ipv4_value_;
474
  }
475

    
476
  // Get the size of the option data.
477
  template <typename Protocol>
478
  std::size_t size(const Protocol& protocol) const
479
  {
480
    if (protocol.family() == PF_INET6)
481
      return sizeof(ipv6_value_);
482
    return sizeof(ipv4_value_);
483
  }
484

    
485
private:
486
  boost::asio::detail::in4_mreq_type ipv4_value_;
487
  boost::asio::detail::in6_mreq_type ipv6_value_;
488
};
489

    
490
// Helper template for implementing options that specify a network interface.
491
template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
492
class network_interface
493
{
494
public:
495
  // Default constructor.
496
  network_interface()
497
  {
498
    ipv4_value_.s_addr =
499
      boost::asio::detail::socket_ops::host_to_network_long(
500
          boost::asio::ip::address_v4::any().to_ulong());
501
    ipv6_value_ = 0;
502
  }
503

    
504
  // Construct with IPv4 interface.
505
  explicit network_interface(const boost::asio::ip::address_v4& ipv4_interface)
506
  {
507
    ipv4_value_.s_addr =
508
      boost::asio::detail::socket_ops::host_to_network_long(
509
          ipv4_interface.to_ulong());
510
    ipv6_value_ = 0;
511
  }
512

    
513
  // Construct with IPv6 interface.
514
  explicit network_interface(unsigned int ipv6_interface)
515
  {
516
    ipv4_value_.s_addr =
517
      boost::asio::detail::socket_ops::host_to_network_long(
518
          boost::asio::ip::address_v4::any().to_ulong());
519
    ipv6_value_ = ipv6_interface;
520
  }
521

    
522
  // Get the level of the socket option.
523
  template <typename Protocol>
524
  int level(const Protocol& protocol) const
525
  {
526
    if (protocol.family() == PF_INET6)
527
      return IPv6_Level;
528
    return IPv4_Level;
529
  }
530

    
531
  // Get the name of the socket option.
532
  template <typename Protocol>
533
  int name(const Protocol& protocol) const
534
  {
535
    if (protocol.family() == PF_INET6)
536
      return IPv6_Name;
537
    return IPv4_Name;
538
  }
539

    
540
  // Get the address of the option data.
541
  template <typename Protocol>
542
  const void* data(const Protocol& protocol) const
543
  {
544
    if (protocol.family() == PF_INET6)
545
      return &ipv6_value_;
546
    return &ipv4_value_;
547
  }
548

    
549
  // Get the size of the option data.
550
  template <typename Protocol>
551
  std::size_t size(const Protocol& protocol) const
552
  {
553
    if (protocol.family() == PF_INET6)
554
      return sizeof(ipv6_value_);
555
    return sizeof(ipv4_value_);
556
  }
557

    
558
private:
559
  boost::asio::detail::in4_addr_type ipv4_value_;
560
  unsigned int ipv6_value_;
561
};
562

    
563
} // namespace socket_option
564
} // namespace detail
565
} // namespace ip
566
} // namespace asio
567
} // namespace boost
568

    
569
#include <boost/asio/detail/pop_options.hpp>
570

    
571
#endif // BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP