~ubuntu-branches/ubuntu/intrepid/asio/intrepid

« back to all changes in this revision

Viewing changes to include/asio/ip/detail/socket_option.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Simon Richter
  • Date: 2007-09-07 11:10:41 UTC
  • Revision ID: james.westby@ubuntu.com-20070907111041-f0uwhs0llvzj9ah5
Tags: upstream-0.3.8~rc3
ImportĀ upstreamĀ versionĀ 0.3.8~rc3

Show diffs side-by-side

added added

removed removed

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