~ubuntu-branches/ubuntu/maverick/libtorrent-rasterbar/maverick

« back to all changes in this revision

Viewing changes to include/libtorrent/asio/detail/reactive_socket_service.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Sauthier
  • Date: 2010-08-10 12:59:37 UTC
  • mfrom: (1.3.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20100810125937-jbcmmf17y8yo9hgz
Tags: 0.15.0-0ubuntu1
* New upstream version.
* debian/patches/100_fix_html_docs.patch: refreshed.
* debian/control: bump up standards-version to 3.9.1 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
// reactive_socket_service.hpp
3
 
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
 
//
5
 
// Copyright (c) 2003-2008 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_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
12
 
#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_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 <boost/shared_ptr.hpp>
22
 
#include "asio/detail/pop_options.hpp"
23
 
 
24
 
#include "asio/buffer.hpp"
25
 
#include "asio/error.hpp"
26
 
#include "asio/io_service.hpp"
27
 
#include "asio/socket_base.hpp"
28
 
#include "asio/detail/bind_handler.hpp"
29
 
#include "asio/detail/handler_base_from_member.hpp"
30
 
#include "asio/detail/noncopyable.hpp"
31
 
#include "asio/detail/service_base.hpp"
32
 
#include "asio/detail/socket_holder.hpp"
33
 
#include "asio/detail/socket_ops.hpp"
34
 
#include "asio/detail/socket_types.hpp"
35
 
 
36
 
namespace asio {
37
 
namespace detail {
38
 
 
39
 
template <typename Protocol, typename Reactor>
40
 
class reactive_socket_service
41
 
  : public asio::detail::service_base<
42
 
      reactive_socket_service<Protocol, Reactor> >
43
 
{
44
 
public:
45
 
  // The protocol type.
46
 
  typedef Protocol protocol_type;
47
 
 
48
 
  // The endpoint type.
49
 
  typedef typename Protocol::endpoint endpoint_type;
50
 
 
51
 
  // The native type of a socket.
52
 
  typedef socket_type native_type;
53
 
 
54
 
  // The implementation type of the socket.
55
 
  class implementation_type
56
 
    : private asio::detail::noncopyable
57
 
  {
58
 
  public:
59
 
    // Default constructor.
60
 
    implementation_type()
61
 
      : socket_(invalid_socket),
62
 
        flags_(0),
63
 
        protocol_(endpoint_type().protocol())
64
 
    {
65
 
    }
66
 
 
67
 
  private:
68
 
    // Only this service will have access to the internal values.
69
 
    friend class reactive_socket_service<Protocol, Reactor>;
70
 
 
71
 
    // The native socket representation.
72
 
    socket_type socket_;
73
 
 
74
 
    enum
75
 
    {
76
 
      user_set_non_blocking = 1, // The user wants a non-blocking socket.
77
 
      internal_non_blocking = 2, // The socket has been set non-blocking.
78
 
      enable_connection_aborted = 4, // User wants connection_aborted errors.
79
 
      user_set_linger = 8 // The user set the linger option.
80
 
    };
81
 
 
82
 
    // Flags indicating the current state of the socket.
83
 
    unsigned char flags_;
84
 
 
85
 
    // The protocol associated with the socket.
86
 
    protocol_type protocol_;
87
 
 
88
 
    // Per-descriptor data used by the reactor.
89
 
    typename Reactor::per_descriptor_data reactor_data_;
90
 
  };
91
 
 
92
 
  // The maximum number of buffers to support in a single operation.
93
 
  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
94
 
 
95
 
  // Constructor.
96
 
  reactive_socket_service(asio::io_service& io_service)
97
 
    : asio::detail::service_base<
98
 
        reactive_socket_service<Protocol, Reactor> >(io_service),
99
 
      reactor_(asio::use_service<Reactor>(io_service))
100
 
  {
101
 
  }
102
 
 
103
 
  // Destroy all user-defined handler objects owned by the service.
104
 
  void shutdown_service()
105
 
  {
106
 
  }
107
 
 
108
 
  // Construct a new socket implementation.
109
 
  void construct(implementation_type& impl)
110
 
  {
111
 
    impl.socket_ = invalid_socket;
112
 
    impl.flags_ = 0;
113
 
  }
114
 
 
115
 
  // Destroy a socket implementation.
116
 
  void destroy(implementation_type& impl)
117
 
  {
118
 
    if (impl.socket_ != invalid_socket)
119
 
    {
120
 
      reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
121
 
 
122
 
      if (impl.flags_ & implementation_type::internal_non_blocking)
123
 
      {
124
 
        ioctl_arg_type non_blocking = 0;
125
 
        asio::error_code ignored_ec;
126
 
        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
127
 
        impl.flags_ &= ~implementation_type::internal_non_blocking;
128
 
      }
129
 
 
130
 
      if (impl.flags_ & implementation_type::user_set_linger)
131
 
      {
132
 
        ::linger opt;
133
 
        opt.l_onoff = 0;
134
 
        opt.l_linger = 0;
135
 
        asio::error_code ignored_ec;
136
 
        socket_ops::setsockopt(impl.socket_,
137
 
            SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
138
 
      }
139
 
 
140
 
      asio::error_code ignored_ec;
141
 
      socket_ops::close(impl.socket_, ignored_ec);
142
 
 
143
 
      impl.socket_ = invalid_socket;
144
 
    }
145
 
  }
146
 
 
147
 
  // Open a new socket implementation.
148
 
  asio::error_code open(implementation_type& impl,
149
 
      const protocol_type& protocol, asio::error_code& ec)
150
 
  {
151
 
    if (is_open(impl))
152
 
    {
153
 
      ec = asio::error::already_open;
154
 
      return ec;
155
 
    }
156
 
 
157
 
    socket_holder sock(socket_ops::socket(protocol.family(),
158
 
          protocol.type(), protocol.protocol(), ec));
159
 
    if (sock.get() == invalid_socket)
160
 
      return ec;
161
 
 
162
 
    if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
163
 
    {
164
 
      ec = asio::error_code(err,
165
 
          asio::error::get_system_category());
166
 
      return ec;
167
 
    }
168
 
 
169
 
    impl.socket_ = sock.release();
170
 
    impl.flags_ = 0;
171
 
    impl.protocol_ = protocol;
172
 
    ec = asio::error_code();
173
 
    return ec;
174
 
  }
175
 
 
176
 
  // Assign a native socket to a socket implementation.
177
 
  asio::error_code assign(implementation_type& impl,
178
 
      const protocol_type& protocol, const native_type& native_socket,
179
 
      asio::error_code& ec)
180
 
  {
181
 
    if (is_open(impl))
182
 
    {
183
 
      ec = asio::error::already_open;
184
 
      return ec;
185
 
    }
186
 
 
187
 
    if (int err = reactor_.register_descriptor(
188
 
          native_socket, impl.reactor_data_))
189
 
    {
190
 
      ec = asio::error_code(err,
191
 
          asio::error::get_system_category());
192
 
      return ec;
193
 
    }
194
 
 
195
 
    impl.socket_ = native_socket;
196
 
    impl.flags_ = 0;
197
 
    impl.protocol_ = protocol;
198
 
    ec = asio::error_code();
199
 
    return ec;
200
 
  }
201
 
 
202
 
  // Determine whether the socket is open.
203
 
  bool is_open(const implementation_type& impl) const
204
 
  {
205
 
    return impl.socket_ != invalid_socket;
206
 
  }
207
 
 
208
 
  // Destroy a socket implementation.
209
 
  asio::error_code close(implementation_type& impl,
210
 
      asio::error_code& ec)
211
 
  {
212
 
    if (is_open(impl))
213
 
    {
214
 
      reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
215
 
 
216
 
      if (impl.flags_ & implementation_type::internal_non_blocking)
217
 
      {
218
 
        ioctl_arg_type non_blocking = 0;
219
 
        asio::error_code ignored_ec;
220
 
        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
221
 
        impl.flags_ &= ~implementation_type::internal_non_blocking;
222
 
      }
223
 
 
224
 
      if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
225
 
        return ec;
226
 
 
227
 
      impl.socket_ = invalid_socket;
228
 
    }
229
 
 
230
 
    ec = asio::error_code();
231
 
    return ec;
232
 
  }
233
 
 
234
 
  // Get the native socket representation.
235
 
  native_type native(implementation_type& impl)
236
 
  {
237
 
    return impl.socket_;
238
 
  }
239
 
 
240
 
  // Cancel all operations associated with the socket.
241
 
  asio::error_code cancel(implementation_type& impl,
242
 
      asio::error_code& ec)
243
 
  {
244
 
    if (!is_open(impl))
245
 
    {
246
 
      ec = asio::error::bad_descriptor;
247
 
      return ec;
248
 
    }
249
 
 
250
 
    reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
251
 
    ec = asio::error_code();
252
 
    return ec;
253
 
  }
254
 
 
255
 
  // Determine whether the socket is at the out-of-band data mark.
256
 
  bool at_mark(const implementation_type& impl,
257
 
      asio::error_code& ec) const
258
 
  {
259
 
    if (!is_open(impl))
260
 
    {
261
 
      ec = asio::error::bad_descriptor;
262
 
      return false;
263
 
    }
264
 
 
265
 
    asio::detail::ioctl_arg_type value = 0;
266
 
    socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
267
 
#if defined(ENOTTY)
268
 
    if (ec.value() == ENOTTY)
269
 
      ec = asio::error::not_socket;
270
 
#endif // defined(ENOTTY)
271
 
    return ec ? false : value != 0;
272
 
  }
273
 
 
274
 
  // Determine the number of bytes available for reading.
275
 
  std::size_t available(const implementation_type& impl,
276
 
      asio::error_code& ec) const
277
 
  {
278
 
    if (!is_open(impl))
279
 
    {
280
 
      ec = asio::error::bad_descriptor;
281
 
      return 0;
282
 
    }
283
 
 
284
 
    asio::detail::ioctl_arg_type value = 0;
285
 
    socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
286
 
#if defined(ENOTTY)
287
 
    if (ec.value() == ENOTTY)
288
 
      ec = asio::error::not_socket;
289
 
#endif // defined(ENOTTY)
290
 
    return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
291
 
  }
292
 
 
293
 
  // Bind the socket to the specified local endpoint.
294
 
  asio::error_code bind(implementation_type& impl,
295
 
      const endpoint_type& endpoint, asio::error_code& ec)
296
 
  {
297
 
    if (!is_open(impl))
298
 
    {
299
 
      ec = asio::error::bad_descriptor;
300
 
      return ec;
301
 
    }
302
 
 
303
 
    socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
304
 
    return ec;
305
 
  }
306
 
 
307
 
  // Place the socket into the state where it will listen for new connections.
308
 
  asio::error_code listen(implementation_type& impl, int backlog,
309
 
      asio::error_code& ec)
310
 
  {
311
 
    if (!is_open(impl))
312
 
    {
313
 
      ec = asio::error::bad_descriptor;
314
 
      return ec;
315
 
    }
316
 
 
317
 
    socket_ops::listen(impl.socket_, backlog, ec);
318
 
    return ec;
319
 
  }
320
 
 
321
 
  // Set a socket option.
322
 
  template <typename Option>
323
 
  asio::error_code set_option(implementation_type& impl,
324
 
      const Option& option, asio::error_code& ec)
325
 
  {
326
 
    if (!is_open(impl))
327
 
    {
328
 
      ec = asio::error::bad_descriptor;
329
 
      return ec;
330
 
    }
331
 
 
332
 
    if (option.level(impl.protocol_) == custom_socket_option_level
333
 
        && option.name(impl.protocol_) == enable_connection_aborted_option)
334
 
    {
335
 
      if (option.size(impl.protocol_) != sizeof(int))
336
 
      {
337
 
        ec = asio::error::invalid_argument;
338
 
      }
339
 
      else
340
 
      {
341
 
        if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
342
 
          impl.flags_ |= implementation_type::enable_connection_aborted;
343
 
        else
344
 
          impl.flags_ &= ~implementation_type::enable_connection_aborted;
345
 
        ec = asio::error_code();
346
 
      }
347
 
      return ec;
348
 
    }
349
 
    else
350
 
    {
351
 
      if (option.level(impl.protocol_) == SOL_SOCKET
352
 
          && option.name(impl.protocol_) == SO_LINGER)
353
 
      {
354
 
        impl.flags_ |= implementation_type::user_set_linger;
355
 
      }
356
 
 
357
 
      socket_ops::setsockopt(impl.socket_,
358
 
          option.level(impl.protocol_), option.name(impl.protocol_),
359
 
          option.data(impl.protocol_), option.size(impl.protocol_), ec);
360
 
 
361
 
#if defined(__MACH__) && defined(__APPLE__) \
362
 
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
363
 
      // To implement portable behaviour for SO_REUSEADDR with UDP sockets we
364
 
      // need to also set SO_REUSEPORT on BSD-based platforms.
365
 
      if (!ec && impl.protocol_.type() == SOCK_DGRAM
366
 
          && option.level(impl.protocol_) == SOL_SOCKET
367
 
          && option.name(impl.protocol_) == SO_REUSEADDR)
368
 
      {
369
 
        asio::error_code ignored_ec;
370
 
        socket_ops::setsockopt(impl.socket_, SOL_SOCKET, SO_REUSEPORT,
371
 
            option.data(impl.protocol_), option.size(impl.protocol_),
372
 
            ignored_ec);
373
 
      }
374
 
#endif
375
 
 
376
 
      return ec;
377
 
    }
378
 
  }
379
 
 
380
 
  // Set a socket option.
381
 
  template <typename Option>
382
 
  asio::error_code get_option(const implementation_type& impl,
383
 
      Option& option, asio::error_code& ec) const
384
 
  {
385
 
    if (!is_open(impl))
386
 
    {
387
 
      ec = asio::error::bad_descriptor;
388
 
      return ec;
389
 
    }
390
 
 
391
 
    if (option.level(impl.protocol_) == custom_socket_option_level
392
 
        && option.name(impl.protocol_) == enable_connection_aborted_option)
393
 
    {
394
 
      if (option.size(impl.protocol_) != sizeof(int))
395
 
      {
396
 
        ec = asio::error::invalid_argument;
397
 
      }
398
 
      else
399
 
      {
400
 
        int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
401
 
        if (impl.flags_ & implementation_type::enable_connection_aborted)
402
 
          *target = 1;
403
 
        else
404
 
          *target = 0;
405
 
        option.resize(impl.protocol_, sizeof(int));
406
 
        ec = asio::error_code();
407
 
      }
408
 
      return ec;
409
 
    }
410
 
    else
411
 
    {
412
 
      size_t size = option.size(impl.protocol_);
413
 
      socket_ops::getsockopt(impl.socket_,
414
 
          option.level(impl.protocol_), option.name(impl.protocol_),
415
 
          option.data(impl.protocol_), &size, ec);
416
 
      if (!ec)
417
 
        option.resize(impl.protocol_, size);
418
 
      return ec;
419
 
    }
420
 
  }
421
 
 
422
 
  // Perform an IO control command on the socket.
423
 
  template <typename IO_Control_Command>
424
 
  asio::error_code io_control(implementation_type& impl,
425
 
      IO_Control_Command& command, asio::error_code& ec)
426
 
  {
427
 
    if (!is_open(impl))
428
 
    {
429
 
      ec = asio::error::bad_descriptor;
430
 
      return ec;
431
 
    }
432
 
 
433
 
    if (command.name() == static_cast<int>(FIONBIO))
434
 
    {
435
 
      if (command.get())
436
 
        impl.flags_ |= implementation_type::user_set_non_blocking;
437
 
      else
438
 
        impl.flags_ &= ~implementation_type::user_set_non_blocking;
439
 
      ec = asio::error_code();
440
 
    }
441
 
    else
442
 
    {
443
 
      socket_ops::ioctl(impl.socket_, command.name(),
444
 
          static_cast<ioctl_arg_type*>(command.data()), ec);
445
 
    }
446
 
    return ec;
447
 
  }
448
 
 
449
 
  // Get the local endpoint.
450
 
  endpoint_type local_endpoint(const implementation_type& impl,
451
 
      asio::error_code& ec) const
452
 
  {
453
 
    if (!is_open(impl))
454
 
    {
455
 
      ec = asio::error::bad_descriptor;
456
 
      return endpoint_type();
457
 
    }
458
 
 
459
 
    endpoint_type endpoint;
460
 
    std::size_t addr_len = endpoint.capacity();
461
 
    if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
462
 
      return endpoint_type();
463
 
    endpoint.resize(addr_len);
464
 
    return endpoint;
465
 
  }
466
 
 
467
 
  // Get the remote endpoint.
468
 
  endpoint_type remote_endpoint(const implementation_type& impl,
469
 
      asio::error_code& ec) const
470
 
  {
471
 
    if (!is_open(impl))
472
 
    {
473
 
      ec = asio::error::bad_descriptor;
474
 
      return endpoint_type();
475
 
    }
476
 
 
477
 
    endpoint_type endpoint;
478
 
    std::size_t addr_len = endpoint.capacity();
479
 
    if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
480
 
      return endpoint_type();
481
 
    endpoint.resize(addr_len);
482
 
    return endpoint;
483
 
  }
484
 
 
485
 
  /// Disable sends or receives on the socket.
486
 
  asio::error_code shutdown(implementation_type& impl,
487
 
      socket_base::shutdown_type what, asio::error_code& ec)
488
 
  {
489
 
    if (!is_open(impl))
490
 
    {
491
 
      ec = asio::error::bad_descriptor;
492
 
      return ec;
493
 
    }
494
 
 
495
 
    socket_ops::shutdown(impl.socket_, what, ec);
496
 
    return ec;
497
 
  }
498
 
 
499
 
  // Send the given data to the peer.
500
 
  template <typename ConstBufferSequence>
501
 
  size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
502
 
      socket_base::message_flags flags, asio::error_code& ec)
503
 
  {
504
 
    if (!is_open(impl))
505
 
    {
506
 
      ec = asio::error::bad_descriptor;
507
 
      return 0;
508
 
    }
509
 
 
510
 
    // Copy buffers into array.
511
 
    socket_ops::buf bufs[max_buffers];
512
 
    typename ConstBufferSequence::const_iterator iter = buffers.begin();
513
 
    typename ConstBufferSequence::const_iterator end = buffers.end();
514
 
    size_t i = 0;
515
 
    size_t total_buffer_size = 0;
516
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
517
 
    {
518
 
      asio::const_buffer buffer(*iter);
519
 
      socket_ops::init_buf(bufs[i],
520
 
          asio::buffer_cast<const void*>(buffer),
521
 
          asio::buffer_size(buffer));
522
 
      total_buffer_size += asio::buffer_size(buffer);
523
 
    }
524
 
 
525
 
    // A request to receive 0 bytes on a stream socket is a no-op.
526
 
    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
527
 
    {
528
 
      ec = asio::error_code();
529
 
      return 0;
530
 
    }
531
 
 
532
 
    // Make socket non-blocking if user wants non-blocking.
533
 
    if (impl.flags_ & implementation_type::user_set_non_blocking)
534
 
    {
535
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
536
 
      {
537
 
        ioctl_arg_type non_blocking = 1;
538
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
539
 
          return 0;
540
 
        impl.flags_ |= implementation_type::internal_non_blocking;
541
 
      }
542
 
    }
543
 
 
544
 
    // Send the data.
545
 
    for (;;)
546
 
    {
547
 
      // Try to complete the operation without blocking.
548
 
      int bytes_sent = socket_ops::send(impl.socket_, bufs, i, flags, ec);
549
 
 
550
 
      // Check if operation succeeded.
551
 
      if (bytes_sent >= 0)
552
 
        return bytes_sent;
553
 
 
554
 
      // Operation failed.
555
 
      if ((impl.flags_ & implementation_type::user_set_non_blocking)
556
 
          || (ec != asio::error::would_block
557
 
            && ec != asio::error::try_again))
558
 
        return 0;
559
 
 
560
 
      // Wait for socket to become ready.
561
 
      if (socket_ops::poll_write(impl.socket_, ec) < 0)
562
 
        return 0;
563
 
    }
564
 
  }
565
 
 
566
 
  // Wait until data can be sent without blocking.
567
 
  size_t send(implementation_type& impl, const null_buffers&,
568
 
      socket_base::message_flags, asio::error_code& ec)
569
 
  {
570
 
    if (!is_open(impl))
571
 
    {
572
 
      ec = asio::error::bad_descriptor;
573
 
      return 0;
574
 
    }
575
 
 
576
 
    // Wait for socket to become ready.
577
 
    socket_ops::poll_write(impl.socket_, ec);
578
 
 
579
 
    return 0;
580
 
  }
581
 
 
582
 
  template <typename ConstBufferSequence, typename Handler>
583
 
  class send_operation :
584
 
    public handler_base_from_member<Handler>
585
 
  {
586
 
  public:
587
 
    send_operation(socket_type socket, asio::io_service& io_service,
588
 
        const ConstBufferSequence& buffers, socket_base::message_flags flags,
589
 
        Handler handler)
590
 
      : handler_base_from_member<Handler>(handler),
591
 
        socket_(socket),
592
 
        io_service_(io_service),
593
 
        work_(io_service),
594
 
        buffers_(buffers),
595
 
        flags_(flags)
596
 
    {
597
 
    }
598
 
 
599
 
    bool perform(asio::error_code& ec,
600
 
        std::size_t& bytes_transferred)
601
 
    {
602
 
      // Check whether the operation was successful.
603
 
      if (ec)
604
 
      {
605
 
        bytes_transferred = 0;
606
 
        return true;
607
 
      }
608
 
 
609
 
      // Copy buffers into array.
610
 
      socket_ops::buf bufs[max_buffers];
611
 
      typename ConstBufferSequence::const_iterator iter = buffers_.begin();
612
 
      typename ConstBufferSequence::const_iterator end = buffers_.end();
613
 
      size_t i = 0;
614
 
      for (; iter != end && i < max_buffers; ++iter, ++i)
615
 
      {
616
 
        asio::const_buffer buffer(*iter);
617
 
        socket_ops::init_buf(bufs[i],
618
 
            asio::buffer_cast<const void*>(buffer),
619
 
            asio::buffer_size(buffer));
620
 
      }
621
 
 
622
 
      // Send the data.
623
 
      int bytes = socket_ops::send(socket_, bufs, i, flags_, ec);
624
 
 
625
 
      // Check if we need to run the operation again.
626
 
      if (ec == asio::error::would_block
627
 
          || ec == asio::error::try_again)
628
 
        return false;
629
 
 
630
 
      bytes_transferred = (bytes < 0 ? 0 : bytes);
631
 
      return true;
632
 
    }
633
 
 
634
 
    void complete(const asio::error_code& ec,
635
 
        std::size_t bytes_transferred)
636
 
    {
637
 
      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
638
 
    }
639
 
 
640
 
  private:
641
 
    socket_type socket_;
642
 
    asio::io_service& io_service_;
643
 
    asio::io_service::work work_;
644
 
    ConstBufferSequence buffers_;
645
 
    socket_base::message_flags flags_;
646
 
  };
647
 
 
648
 
  // Start an asynchronous send. The data being sent must be valid for the
649
 
  // lifetime of the asynchronous operation.
650
 
  template <typename ConstBufferSequence, typename Handler>
651
 
  void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
652
 
      socket_base::message_flags flags, Handler handler)
653
 
  {
654
 
    if (!is_open(impl))
655
 
    {
656
 
      this->get_io_service().post(bind_handler(handler,
657
 
            asio::error::bad_descriptor, 0));
658
 
    }
659
 
    else
660
 
    {
661
 
      if (impl.protocol_.type() == SOCK_STREAM)
662
 
      {
663
 
        // Determine total size of buffers.
664
 
        typename ConstBufferSequence::const_iterator iter = buffers.begin();
665
 
        typename ConstBufferSequence::const_iterator end = buffers.end();
666
 
        size_t i = 0;
667
 
        size_t total_buffer_size = 0;
668
 
        for (; iter != end && i < max_buffers; ++iter, ++i)
669
 
        {
670
 
          asio::const_buffer buffer(*iter);
671
 
          total_buffer_size += asio::buffer_size(buffer);
672
 
        }
673
 
 
674
 
        // A request to receive 0 bytes on a stream socket is a no-op.
675
 
        if (total_buffer_size == 0)
676
 
        {
677
 
          this->get_io_service().post(bind_handler(handler,
678
 
                asio::error_code(), 0));
679
 
          return;
680
 
        }
681
 
      }
682
 
 
683
 
      // Make socket non-blocking.
684
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
685
 
      {
686
 
        ioctl_arg_type non_blocking = 1;
687
 
        asio::error_code ec;
688
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
689
 
        {
690
 
          this->get_io_service().post(bind_handler(handler, ec, 0));
691
 
          return;
692
 
        }
693
 
        impl.flags_ |= implementation_type::internal_non_blocking;
694
 
      }
695
 
 
696
 
      reactor_.start_write_op(impl.socket_, impl.reactor_data_,
697
 
          send_operation<ConstBufferSequence, Handler>(
698
 
            impl.socket_, this->get_io_service(), buffers, flags, handler));
699
 
    }
700
 
  }
701
 
 
702
 
  template <typename Handler>
703
 
  class null_buffers_operation :
704
 
    public handler_base_from_member<Handler>
705
 
  {
706
 
  public:
707
 
    null_buffers_operation(asio::io_service& io_service, Handler handler)
708
 
      : handler_base_from_member<Handler>(handler),
709
 
        work_(io_service)
710
 
    {
711
 
    }
712
 
 
713
 
    bool perform(asio::error_code&,
714
 
        std::size_t& bytes_transferred)
715
 
    {
716
 
      bytes_transferred = 0;
717
 
      return true;
718
 
    }
719
 
 
720
 
    void complete(const asio::error_code& ec,
721
 
        std::size_t bytes_transferred)
722
 
    {
723
 
      work_.get_io_service().post(bind_handler(
724
 
            this->handler_, ec, bytes_transferred));
725
 
    }
726
 
 
727
 
  private:
728
 
    asio::io_service::work work_;
729
 
  };
730
 
 
731
 
  // Start an asynchronous wait until data can be sent without blocking.
732
 
  template <typename Handler>
733
 
  void async_send(implementation_type& impl, const null_buffers&,
734
 
      socket_base::message_flags, Handler handler)
735
 
  {
736
 
    if (!is_open(impl))
737
 
    {
738
 
      this->get_io_service().post(bind_handler(handler,
739
 
            asio::error::bad_descriptor, 0));
740
 
    }
741
 
    else
742
 
    {
743
 
      reactor_.start_write_op(impl.socket_, impl.reactor_data_,
744
 
          null_buffers_operation<Handler>(this->get_io_service(), handler),
745
 
          false);
746
 
    }
747
 
  }
748
 
 
749
 
  // Send a datagram to the specified endpoint. Returns the number of bytes
750
 
  // sent.
751
 
  template <typename ConstBufferSequence>
752
 
  size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
753
 
      const endpoint_type& destination, socket_base::message_flags flags,
754
 
      asio::error_code& ec)
755
 
  {
756
 
    if (!is_open(impl))
757
 
    {
758
 
      ec = asio::error::bad_descriptor;
759
 
      return 0;
760
 
    }
761
 
 
762
 
    // Copy buffers into array.
763
 
    socket_ops::buf bufs[max_buffers];
764
 
    typename ConstBufferSequence::const_iterator iter = buffers.begin();
765
 
    typename ConstBufferSequence::const_iterator end = buffers.end();
766
 
    size_t i = 0;
767
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
768
 
    {
769
 
      asio::const_buffer buffer(*iter);
770
 
      socket_ops::init_buf(bufs[i],
771
 
          asio::buffer_cast<const void*>(buffer),
772
 
          asio::buffer_size(buffer));
773
 
    }
774
 
 
775
 
    // Make socket non-blocking if user wants non-blocking.
776
 
    if (impl.flags_ & implementation_type::user_set_non_blocking)
777
 
    {
778
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
779
 
      {
780
 
        ioctl_arg_type non_blocking = 1;
781
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
782
 
          return 0;
783
 
        impl.flags_ |= implementation_type::internal_non_blocking;
784
 
      }
785
 
    }
786
 
 
787
 
    // Send the data.
788
 
    for (;;)
789
 
    {
790
 
      // Try to complete the operation without blocking.
791
 
      int bytes_sent = socket_ops::sendto(impl.socket_, bufs, i, flags,
792
 
          destination.data(), destination.size(), ec);
793
 
 
794
 
      // Check if operation succeeded.
795
 
      if (bytes_sent >= 0)
796
 
        return bytes_sent;
797
 
 
798
 
      // Operation failed.
799
 
      if ((impl.flags_ & implementation_type::user_set_non_blocking)
800
 
          || (ec != asio::error::would_block
801
 
            && ec != asio::error::try_again))
802
 
        return 0;
803
 
 
804
 
      // Wait for socket to become ready.
805
 
      if (socket_ops::poll_write(impl.socket_, ec) < 0)
806
 
        return 0;
807
 
    }
808
 
  }
809
 
 
810
 
  // Wait until data can be sent without blocking.
811
 
  size_t send_to(implementation_type& impl, const null_buffers&,
812
 
      socket_base::message_flags, const endpoint_type&,
813
 
      asio::error_code& ec)
814
 
  {
815
 
    if (!is_open(impl))
816
 
    {
817
 
      ec = asio::error::bad_descriptor;
818
 
      return 0;
819
 
    }
820
 
 
821
 
    // Wait for socket to become ready.
822
 
    socket_ops::poll_write(impl.socket_, ec);
823
 
 
824
 
    return 0;
825
 
  }
826
 
 
827
 
  template <typename ConstBufferSequence, typename Handler>
828
 
  class send_to_operation :
829
 
    public handler_base_from_member<Handler>
830
 
  {
831
 
  public:
832
 
    send_to_operation(socket_type socket, asio::io_service& io_service,
833
 
        const ConstBufferSequence& buffers, const endpoint_type& endpoint,
834
 
        socket_base::message_flags flags, Handler handler)
835
 
      : handler_base_from_member<Handler>(handler),
836
 
        socket_(socket),
837
 
        io_service_(io_service),
838
 
        work_(io_service),
839
 
        buffers_(buffers),
840
 
        destination_(endpoint),
841
 
        flags_(flags)
842
 
    {
843
 
    }
844
 
 
845
 
    bool perform(asio::error_code& ec,
846
 
        std::size_t& bytes_transferred)
847
 
    {
848
 
      // Check whether the operation was successful.
849
 
      if (ec)
850
 
      {
851
 
        bytes_transferred = 0;
852
 
        return true;
853
 
      }
854
 
 
855
 
      // Copy buffers into array.
856
 
      socket_ops::buf bufs[max_buffers];
857
 
      typename ConstBufferSequence::const_iterator iter = buffers_.begin();
858
 
      typename ConstBufferSequence::const_iterator end = buffers_.end();
859
 
      size_t i = 0;
860
 
      for (; iter != end && i < max_buffers; ++iter, ++i)
861
 
      {
862
 
        asio::const_buffer buffer(*iter);
863
 
        socket_ops::init_buf(bufs[i],
864
 
            asio::buffer_cast<const void*>(buffer),
865
 
            asio::buffer_size(buffer));
866
 
      }
867
 
 
868
 
      // Send the data.
869
 
      int bytes = socket_ops::sendto(socket_, bufs, i, flags_,
870
 
          destination_.data(), destination_.size(), ec);
871
 
 
872
 
      // Check if we need to run the operation again.
873
 
      if (ec == asio::error::would_block
874
 
          || ec == asio::error::try_again)
875
 
        return false;
876
 
 
877
 
      bytes_transferred = (bytes < 0 ? 0 : bytes);
878
 
      return true;
879
 
    }
880
 
 
881
 
    void complete(const asio::error_code& ec,
882
 
        std::size_t bytes_transferred)
883
 
    {
884
 
      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
885
 
    }
886
 
 
887
 
  private:
888
 
    socket_type socket_;
889
 
    asio::io_service& io_service_;
890
 
    asio::io_service::work work_;
891
 
    ConstBufferSequence buffers_;
892
 
    endpoint_type destination_;
893
 
    socket_base::message_flags flags_;
894
 
  };
895
 
 
896
 
  // Start an asynchronous send. The data being sent must be valid for the
897
 
  // lifetime of the asynchronous operation.
898
 
  template <typename ConstBufferSequence, typename Handler>
899
 
  void async_send_to(implementation_type& impl,
900
 
      const ConstBufferSequence& buffers,
901
 
      const endpoint_type& destination, socket_base::message_flags flags,
902
 
      Handler handler)
903
 
  {
904
 
    if (!is_open(impl))
905
 
    {
906
 
      this->get_io_service().post(bind_handler(handler,
907
 
            asio::error::bad_descriptor, 0));
908
 
    }
909
 
    else
910
 
    {
911
 
      // Make socket non-blocking.
912
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
913
 
      {
914
 
        ioctl_arg_type non_blocking = 1;
915
 
        asio::error_code ec;
916
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
917
 
        {
918
 
          this->get_io_service().post(bind_handler(handler, ec, 0));
919
 
          return;
920
 
        }
921
 
        impl.flags_ |= implementation_type::internal_non_blocking;
922
 
      }
923
 
 
924
 
      reactor_.start_write_op(impl.socket_, impl.reactor_data_,
925
 
          send_to_operation<ConstBufferSequence, Handler>(
926
 
            impl.socket_, this->get_io_service(), buffers,
927
 
            destination, flags, handler));
928
 
    }
929
 
  }
930
 
 
931
 
  // Start an asynchronous wait until data can be sent without blocking.
932
 
  template <typename Handler>
933
 
  void async_send_to(implementation_type& impl, const null_buffers&,
934
 
      socket_base::message_flags, const endpoint_type&, Handler handler)
935
 
  {
936
 
    if (!is_open(impl))
937
 
    {
938
 
      this->get_io_service().post(bind_handler(handler,
939
 
            asio::error::bad_descriptor, 0));
940
 
    }
941
 
    else
942
 
    {
943
 
      reactor_.start_write_op(impl.socket_, impl.reactor_data_,
944
 
          null_buffers_operation<Handler>(this->get_io_service(), handler),
945
 
          false);
946
 
    }
947
 
  }
948
 
 
949
 
  // Receive some data from the peer. Returns the number of bytes received.
950
 
  template <typename MutableBufferSequence>
951
 
  size_t receive(implementation_type& impl,
952
 
      const MutableBufferSequence& buffers,
953
 
      socket_base::message_flags flags, asio::error_code& ec)
954
 
  {
955
 
    if (!is_open(impl))
956
 
    {
957
 
      ec = asio::error::bad_descriptor;
958
 
      return 0;
959
 
    }
960
 
 
961
 
    // Copy buffers into array.
962
 
    socket_ops::buf bufs[max_buffers];
963
 
    typename MutableBufferSequence::const_iterator iter = buffers.begin();
964
 
    typename MutableBufferSequence::const_iterator end = buffers.end();
965
 
    size_t i = 0;
966
 
    size_t total_buffer_size = 0;
967
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
968
 
    {
969
 
      asio::mutable_buffer buffer(*iter);
970
 
      socket_ops::init_buf(bufs[i],
971
 
          asio::buffer_cast<void*>(buffer),
972
 
          asio::buffer_size(buffer));
973
 
      total_buffer_size += asio::buffer_size(buffer);
974
 
    }
975
 
 
976
 
    // A request to receive 0 bytes on a stream socket is a no-op.
977
 
    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
978
 
    {
979
 
      ec = asio::error_code();
980
 
      return 0;
981
 
    }
982
 
 
983
 
    // Make socket non-blocking if user wants non-blocking.
984
 
    if (impl.flags_ & implementation_type::user_set_non_blocking)
985
 
    {
986
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
987
 
      {
988
 
        ioctl_arg_type non_blocking = 1;
989
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
990
 
          return 0;
991
 
        impl.flags_ |= implementation_type::internal_non_blocking;
992
 
      }
993
 
    }
994
 
 
995
 
    // Receive some data.
996
 
    for (;;)
997
 
    {
998
 
      // Try to complete the operation without blocking.
999
 
      int bytes_recvd = socket_ops::recv(impl.socket_, bufs, i, flags, ec);
1000
 
 
1001
 
      // Check if operation succeeded.
1002
 
      if (bytes_recvd > 0)
1003
 
        return bytes_recvd;
1004
 
 
1005
 
      // Check for EOF.
1006
 
      if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM)
1007
 
      {
1008
 
        ec = asio::error::eof;
1009
 
        return 0;
1010
 
      }
1011
 
 
1012
 
      // Operation failed.
1013
 
      if ((impl.flags_ & implementation_type::user_set_non_blocking)
1014
 
          || (ec != asio::error::would_block
1015
 
            && ec != asio::error::try_again))
1016
 
        return 0;
1017
 
 
1018
 
      // Wait for socket to become ready.
1019
 
      if (socket_ops::poll_read(impl.socket_, ec) < 0)
1020
 
        return 0;
1021
 
    }
1022
 
  }
1023
 
 
1024
 
  // Wait until data can be received without blocking.
1025
 
  size_t receive(implementation_type& impl, const null_buffers&,
1026
 
      socket_base::message_flags, asio::error_code& ec)
1027
 
  {
1028
 
    if (!is_open(impl))
1029
 
    {
1030
 
      ec = asio::error::bad_descriptor;
1031
 
      return 0;
1032
 
    }
1033
 
 
1034
 
    // Wait for socket to become ready.
1035
 
    socket_ops::poll_read(impl.socket_, ec);
1036
 
 
1037
 
    return 0;
1038
 
  }
1039
 
 
1040
 
  template <typename MutableBufferSequence, typename Handler>
1041
 
  class receive_operation :
1042
 
    public handler_base_from_member<Handler>
1043
 
  {
1044
 
  public:
1045
 
    receive_operation(socket_type socket, int protocol_type,
1046
 
        asio::io_service& io_service,
1047
 
        const MutableBufferSequence& buffers,
1048
 
        socket_base::message_flags flags, Handler handler)
1049
 
      : handler_base_from_member<Handler>(handler),
1050
 
        socket_(socket),
1051
 
        protocol_type_(protocol_type),
1052
 
        io_service_(io_service),
1053
 
        work_(io_service),
1054
 
        buffers_(buffers),
1055
 
        flags_(flags)
1056
 
    {
1057
 
    }
1058
 
 
1059
 
    bool perform(asio::error_code& ec,
1060
 
        std::size_t& bytes_transferred)
1061
 
    {
1062
 
      // Check whether the operation was successful.
1063
 
      if (ec)
1064
 
      {
1065
 
        bytes_transferred = 0;
1066
 
        return true;
1067
 
      }
1068
 
 
1069
 
      // Copy buffers into array.
1070
 
      socket_ops::buf bufs[max_buffers];
1071
 
      typename MutableBufferSequence::const_iterator iter = buffers_.begin();
1072
 
      typename MutableBufferSequence::const_iterator end = buffers_.end();
1073
 
      size_t i = 0;
1074
 
      for (; iter != end && i < max_buffers; ++iter, ++i)
1075
 
      {
1076
 
        asio::mutable_buffer buffer(*iter);
1077
 
        socket_ops::init_buf(bufs[i],
1078
 
            asio::buffer_cast<void*>(buffer),
1079
 
            asio::buffer_size(buffer));
1080
 
      }
1081
 
 
1082
 
      // Receive some data.
1083
 
      int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec);
1084
 
      if (bytes == 0 && protocol_type_ == SOCK_STREAM)
1085
 
        ec = asio::error::eof;
1086
 
 
1087
 
      // Check if we need to run the operation again.
1088
 
      if (ec == asio::error::would_block
1089
 
          || ec == asio::error::try_again)
1090
 
        return false;
1091
 
 
1092
 
      bytes_transferred = (bytes < 0 ? 0 : bytes);
1093
 
      return true;
1094
 
    }
1095
 
 
1096
 
    void complete(const asio::error_code& ec,
1097
 
        std::size_t bytes_transferred)
1098
 
    {
1099
 
      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
1100
 
    }
1101
 
 
1102
 
  private:
1103
 
    socket_type socket_;
1104
 
    int protocol_type_;
1105
 
    asio::io_service& io_service_;
1106
 
    asio::io_service::work work_;
1107
 
    MutableBufferSequence buffers_;
1108
 
    socket_base::message_flags flags_;
1109
 
  };
1110
 
 
1111
 
  // Start an asynchronous receive. The buffer for the data being received
1112
 
  // must be valid for the lifetime of the asynchronous operation.
1113
 
  template <typename MutableBufferSequence, typename Handler>
1114
 
  void async_receive(implementation_type& impl,
1115
 
      const MutableBufferSequence& buffers,
1116
 
      socket_base::message_flags flags, Handler handler)
1117
 
  {
1118
 
    if (!is_open(impl))
1119
 
    {
1120
 
      this->get_io_service().post(bind_handler(handler,
1121
 
            asio::error::bad_descriptor, 0));
1122
 
    }
1123
 
    else
1124
 
    {
1125
 
      if (impl.protocol_.type() == SOCK_STREAM)
1126
 
      {
1127
 
        // Determine total size of buffers.
1128
 
        typename MutableBufferSequence::const_iterator iter = buffers.begin();
1129
 
        typename MutableBufferSequence::const_iterator end = buffers.end();
1130
 
        size_t i = 0;
1131
 
        size_t total_buffer_size = 0;
1132
 
        for (; iter != end && i < max_buffers; ++iter, ++i)
1133
 
        {
1134
 
          asio::mutable_buffer buffer(*iter);
1135
 
          total_buffer_size += asio::buffer_size(buffer);
1136
 
        }
1137
 
 
1138
 
        // A request to receive 0 bytes on a stream socket is a no-op.
1139
 
        if (total_buffer_size == 0)
1140
 
        {
1141
 
          this->get_io_service().post(bind_handler(handler,
1142
 
                asio::error_code(), 0));
1143
 
          return;
1144
 
        }
1145
 
      }
1146
 
 
1147
 
      // Make socket non-blocking.
1148
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
1149
 
      {
1150
 
        ioctl_arg_type non_blocking = 1;
1151
 
        asio::error_code ec;
1152
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
1153
 
        {
1154
 
          this->get_io_service().post(bind_handler(handler, ec, 0));
1155
 
          return;
1156
 
        }
1157
 
        impl.flags_ |= implementation_type::internal_non_blocking;
1158
 
      }
1159
 
 
1160
 
      if (flags & socket_base::message_out_of_band)
1161
 
      {
1162
 
        reactor_.start_except_op(impl.socket_, impl.reactor_data_,
1163
 
            receive_operation<MutableBufferSequence, Handler>(
1164
 
              impl.socket_, impl.protocol_.type(),
1165
 
              this->get_io_service(), buffers, flags, handler));
1166
 
      }
1167
 
      else
1168
 
      {
1169
 
        reactor_.start_read_op(impl.socket_, impl.reactor_data_,
1170
 
            receive_operation<MutableBufferSequence, Handler>(
1171
 
              impl.socket_, impl.protocol_.type(),
1172
 
              this->get_io_service(), buffers, flags, handler));
1173
 
      }
1174
 
    }
1175
 
  }
1176
 
 
1177
 
  // Wait until data can be received without blocking.
1178
 
  template <typename Handler>
1179
 
  void async_receive(implementation_type& impl, const null_buffers&,
1180
 
      socket_base::message_flags flags, Handler handler)
1181
 
  {
1182
 
    if (!is_open(impl))
1183
 
    {
1184
 
      this->get_io_service().post(bind_handler(handler,
1185
 
            asio::error::bad_descriptor, 0));
1186
 
    }
1187
 
    else if (flags & socket_base::message_out_of_band)
1188
 
    {
1189
 
      reactor_.start_except_op(impl.socket_, impl.reactor_data_,
1190
 
          null_buffers_operation<Handler>(this->get_io_service(), handler));
1191
 
    }
1192
 
    else
1193
 
    {
1194
 
      reactor_.start_read_op(impl.socket_, impl.reactor_data_,
1195
 
          null_buffers_operation<Handler>(this->get_io_service(), handler),
1196
 
          false);
1197
 
    }
1198
 
  }
1199
 
 
1200
 
  // Receive a datagram with the endpoint of the sender. Returns the number of
1201
 
  // bytes received.
1202
 
  template <typename MutableBufferSequence>
1203
 
  size_t receive_from(implementation_type& impl,
1204
 
      const MutableBufferSequence& buffers,
1205
 
      endpoint_type& sender_endpoint, socket_base::message_flags flags,
1206
 
      asio::error_code& ec)
1207
 
  {
1208
 
    if (!is_open(impl))
1209
 
    {
1210
 
      ec = asio::error::bad_descriptor;
1211
 
      return 0;
1212
 
    }
1213
 
 
1214
 
    // Copy buffers into array.
1215
 
    socket_ops::buf bufs[max_buffers];
1216
 
    typename MutableBufferSequence::const_iterator iter = buffers.begin();
1217
 
    typename MutableBufferSequence::const_iterator end = buffers.end();
1218
 
    size_t i = 0;
1219
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
1220
 
    {
1221
 
      asio::mutable_buffer buffer(*iter);
1222
 
      socket_ops::init_buf(bufs[i],
1223
 
          asio::buffer_cast<void*>(buffer),
1224
 
          asio::buffer_size(buffer));
1225
 
    }
1226
 
 
1227
 
    // Make socket non-blocking if user wants non-blocking.
1228
 
    if (impl.flags_ & implementation_type::user_set_non_blocking)
1229
 
    {
1230
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
1231
 
      {
1232
 
        ioctl_arg_type non_blocking = 1;
1233
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
1234
 
          return 0;
1235
 
        impl.flags_ |= implementation_type::internal_non_blocking;
1236
 
      }
1237
 
    }
1238
 
 
1239
 
    // Receive some data.
1240
 
    for (;;)
1241
 
    {
1242
 
      // Try to complete the operation without blocking.
1243
 
      std::size_t addr_len = sender_endpoint.capacity();
1244
 
      int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags,
1245
 
          sender_endpoint.data(), &addr_len, ec);
1246
 
 
1247
 
      // Check if operation succeeded.
1248
 
      if (bytes_recvd > 0)
1249
 
      {
1250
 
        sender_endpoint.resize(addr_len);
1251
 
        return bytes_recvd;
1252
 
      }
1253
 
 
1254
 
      // Check for EOF.
1255
 
      if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM)
1256
 
      {
1257
 
        ec = asio::error::eof;
1258
 
        return 0;
1259
 
      }
1260
 
 
1261
 
      // Operation failed.
1262
 
      if ((impl.flags_ & implementation_type::user_set_non_blocking)
1263
 
          || (ec != asio::error::would_block
1264
 
            && ec != asio::error::try_again))
1265
 
        return 0;
1266
 
 
1267
 
      // Wait for socket to become ready.
1268
 
      if (socket_ops::poll_read(impl.socket_, ec) < 0)
1269
 
        return 0;
1270
 
    }
1271
 
  }
1272
 
 
1273
 
  // Wait until data can be received without blocking.
1274
 
  size_t receive_from(implementation_type& impl, const null_buffers&,
1275
 
      endpoint_type& sender_endpoint, socket_base::message_flags,
1276
 
      asio::error_code& ec)
1277
 
  {
1278
 
    if (!is_open(impl))
1279
 
    {
1280
 
      ec = asio::error::bad_descriptor;
1281
 
      return 0;
1282
 
    }
1283
 
 
1284
 
    // Wait for socket to become ready.
1285
 
    socket_ops::poll_read(impl.socket_, ec);
1286
 
 
1287
 
    // Reset endpoint since it can be given no sensible value at this time.
1288
 
    sender_endpoint = endpoint_type();
1289
 
 
1290
 
    return 0;
1291
 
  }
1292
 
 
1293
 
  template <typename MutableBufferSequence, typename Handler>
1294
 
  class receive_from_operation :
1295
 
    public handler_base_from_member<Handler>
1296
 
  {
1297
 
  public:
1298
 
    receive_from_operation(socket_type socket, int protocol_type,
1299
 
        asio::io_service& io_service,
1300
 
        const MutableBufferSequence& buffers, endpoint_type& endpoint,
1301
 
        socket_base::message_flags flags, Handler handler)
1302
 
      : handler_base_from_member<Handler>(handler),
1303
 
        socket_(socket),
1304
 
        protocol_type_(protocol_type),
1305
 
        io_service_(io_service),
1306
 
        work_(io_service),
1307
 
        buffers_(buffers),
1308
 
        sender_endpoint_(endpoint),
1309
 
        flags_(flags)
1310
 
    {
1311
 
    }
1312
 
 
1313
 
    bool perform(asio::error_code& ec,
1314
 
        std::size_t& bytes_transferred)
1315
 
    {
1316
 
      // Check whether the operation was successful.
1317
 
      if (ec)
1318
 
      {
1319
 
        bytes_transferred = 0;
1320
 
        return true;
1321
 
      }
1322
 
 
1323
 
      // Copy buffers into array.
1324
 
      socket_ops::buf bufs[max_buffers];
1325
 
      typename MutableBufferSequence::const_iterator iter = buffers_.begin();
1326
 
      typename MutableBufferSequence::const_iterator end = buffers_.end();
1327
 
      size_t i = 0;
1328
 
      for (; iter != end && i < max_buffers; ++iter, ++i)
1329
 
      {
1330
 
        asio::mutable_buffer buffer(*iter);
1331
 
        socket_ops::init_buf(bufs[i],
1332
 
            asio::buffer_cast<void*>(buffer),
1333
 
            asio::buffer_size(buffer));
1334
 
      }
1335
 
 
1336
 
      // Receive some data.
1337
 
      std::size_t addr_len = sender_endpoint_.capacity();
1338
 
      int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
1339
 
          sender_endpoint_.data(), &addr_len, ec);
1340
 
      if (bytes == 0 && protocol_type_ == SOCK_STREAM)
1341
 
        ec = asio::error::eof;
1342
 
 
1343
 
      // Check if we need to run the operation again.
1344
 
      if (ec == asio::error::would_block
1345
 
          || ec == asio::error::try_again)
1346
 
        return false;
1347
 
 
1348
 
      sender_endpoint_.resize(addr_len);
1349
 
      bytes_transferred = (bytes < 0 ? 0 : bytes);
1350
 
      return true;
1351
 
    }
1352
 
 
1353
 
    void complete(const asio::error_code& ec,
1354
 
        std::size_t bytes_transferred)
1355
 
    {
1356
 
      io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
1357
 
    }
1358
 
 
1359
 
  private:
1360
 
    socket_type socket_;
1361
 
    int protocol_type_;
1362
 
    asio::io_service& io_service_;
1363
 
    asio::io_service::work work_;
1364
 
    MutableBufferSequence buffers_;
1365
 
    endpoint_type& sender_endpoint_;
1366
 
    socket_base::message_flags flags_;
1367
 
  };
1368
 
 
1369
 
  // Start an asynchronous receive. The buffer for the data being received and
1370
 
  // the sender_endpoint object must both be valid for the lifetime of the
1371
 
  // asynchronous operation.
1372
 
  template <typename MutableBufferSequence, typename Handler>
1373
 
  void async_receive_from(implementation_type& impl,
1374
 
      const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
1375
 
      socket_base::message_flags flags, Handler handler)
1376
 
  {
1377
 
    if (!is_open(impl))
1378
 
    {
1379
 
      this->get_io_service().post(bind_handler(handler,
1380
 
            asio::error::bad_descriptor, 0));
1381
 
    }
1382
 
    else
1383
 
    {
1384
 
      // Make socket non-blocking.
1385
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
1386
 
      {
1387
 
        ioctl_arg_type non_blocking = 1;
1388
 
        asio::error_code ec;
1389
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
1390
 
        {
1391
 
          this->get_io_service().post(bind_handler(handler, ec, 0));
1392
 
          return;
1393
 
        }
1394
 
        impl.flags_ |= implementation_type::internal_non_blocking;
1395
 
      }
1396
 
 
1397
 
      reactor_.start_read_op(impl.socket_, impl.reactor_data_,
1398
 
          receive_from_operation<MutableBufferSequence, Handler>(
1399
 
            impl.socket_, impl.protocol_.type(), this->get_io_service(),
1400
 
            buffers, sender_endpoint, flags, handler));
1401
 
    }
1402
 
  }
1403
 
 
1404
 
  // Wait until data can be received without blocking.
1405
 
  template <typename Handler>
1406
 
  void async_receive_from(implementation_type& impl,
1407
 
      const null_buffers&, endpoint_type& sender_endpoint,
1408
 
      socket_base::message_flags flags, Handler handler)
1409
 
  {
1410
 
    if (!is_open(impl))
1411
 
    {
1412
 
      this->get_io_service().post(bind_handler(handler,
1413
 
            asio::error::bad_descriptor, 0));
1414
 
    }
1415
 
    else
1416
 
    {
1417
 
      // Reset endpoint since it can be given no sensible value at this time.
1418
 
      sender_endpoint = endpoint_type();
1419
 
 
1420
 
      if (flags & socket_base::message_out_of_band)
1421
 
      {
1422
 
        reactor_.start_except_op(impl.socket_, impl.reactor_data_,
1423
 
            null_buffers_operation<Handler>(this->get_io_service(), handler));
1424
 
      }
1425
 
      else
1426
 
      {
1427
 
        reactor_.start_read_op(impl.socket_, impl.reactor_data_,
1428
 
            null_buffers_operation<Handler>(this->get_io_service(), handler),
1429
 
            false);
1430
 
      }
1431
 
    }
1432
 
  }
1433
 
 
1434
 
  // Accept a new connection.
1435
 
  template <typename Socket>
1436
 
  asio::error_code accept(implementation_type& impl,
1437
 
      Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec)
1438
 
  {
1439
 
    if (!is_open(impl))
1440
 
    {
1441
 
      ec = asio::error::bad_descriptor;
1442
 
      return ec;
1443
 
    }
1444
 
 
1445
 
    // We cannot accept a socket that is already open.
1446
 
    if (peer.is_open())
1447
 
    {
1448
 
      ec = asio::error::already_open;
1449
 
      return ec;
1450
 
    }
1451
 
 
1452
 
    // Make socket non-blocking if user wants non-blocking.
1453
 
    if (impl.flags_ & implementation_type::user_set_non_blocking)
1454
 
    {
1455
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
1456
 
      {
1457
 
        ioctl_arg_type non_blocking = 1;
1458
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
1459
 
          return ec;
1460
 
        impl.flags_ |= implementation_type::internal_non_blocking;
1461
 
      }
1462
 
    }
1463
 
 
1464
 
    // Accept a socket.
1465
 
    for (;;)
1466
 
    {
1467
 
      // Try to complete the operation without blocking.
1468
 
      asio::error_code ec;
1469
 
      socket_holder new_socket;
1470
 
      std::size_t addr_len = 0;
1471
 
      if (peer_endpoint)
1472
 
      {
1473
 
        addr_len = peer_endpoint->capacity();
1474
 
        new_socket.reset(socket_ops::accept(impl.socket_,
1475
 
              peer_endpoint->data(), &addr_len, ec));
1476
 
      }
1477
 
      else
1478
 
      {
1479
 
        new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
1480
 
      }
1481
 
 
1482
 
      // Check if operation succeeded.
1483
 
      if (new_socket.get() >= 0)
1484
 
      {
1485
 
        if (peer_endpoint)
1486
 
          peer_endpoint->resize(addr_len);
1487
 
        peer.assign(impl.protocol_, new_socket.get(), ec);
1488
 
        if (!ec)
1489
 
          new_socket.release();
1490
 
        return ec;
1491
 
      }
1492
 
 
1493
 
      // Operation failed.
1494
 
      if (ec == asio::error::would_block
1495
 
          || ec == asio::error::try_again)
1496
 
      {
1497
 
        if (impl.flags_ & implementation_type::user_set_non_blocking)
1498
 
          return ec;
1499
 
        // Fall through to retry operation.
1500
 
      }
1501
 
      else if (ec == asio::error::connection_aborted)
1502
 
      {
1503
 
        if (impl.flags_ & implementation_type::enable_connection_aborted)
1504
 
          return ec;
1505
 
        // Fall through to retry operation.
1506
 
      }
1507
 
#if defined(EPROTO)
1508
 
      else if (ec.value() == EPROTO)
1509
 
      {
1510
 
        if (impl.flags_ & implementation_type::enable_connection_aborted)
1511
 
          return ec;
1512
 
        // Fall through to retry operation.
1513
 
      }
1514
 
#endif // defined(EPROTO)
1515
 
      else
1516
 
        return ec;
1517
 
 
1518
 
      // Wait for socket to become ready.
1519
 
      if (socket_ops::poll_read(impl.socket_, ec) < 0)
1520
 
        return ec;
1521
 
    }
1522
 
  }
1523
 
 
1524
 
  template <typename Socket, typename Handler>
1525
 
  class accept_operation :
1526
 
    public handler_base_from_member<Handler>
1527
 
  {
1528
 
  public:
1529
 
    accept_operation(socket_type socket, asio::io_service& io_service,
1530
 
        Socket& peer, const protocol_type& protocol,
1531
 
        endpoint_type* peer_endpoint, bool enable_connection_aborted,
1532
 
        Handler handler)
1533
 
      : handler_base_from_member<Handler>(handler),
1534
 
        socket_(socket),
1535
 
        io_service_(io_service),
1536
 
        work_(io_service),
1537
 
        peer_(peer),
1538
 
        protocol_(protocol),
1539
 
        peer_endpoint_(peer_endpoint),
1540
 
        enable_connection_aborted_(enable_connection_aborted)
1541
 
    {
1542
 
    }
1543
 
 
1544
 
    bool perform(asio::error_code& ec, std::size_t&)
1545
 
    {
1546
 
      // Check whether the operation was successful.
1547
 
      if (ec)
1548
 
        return true;
1549
 
 
1550
 
      // Accept the waiting connection.
1551
 
      socket_holder new_socket;
1552
 
      std::size_t addr_len = 0;
1553
 
      if (peer_endpoint_)
1554
 
      {
1555
 
        addr_len = peer_endpoint_->capacity();
1556
 
        new_socket.reset(socket_ops::accept(socket_,
1557
 
              peer_endpoint_->data(), &addr_len, ec));
1558
 
      }
1559
 
      else
1560
 
      {
1561
 
        new_socket.reset(socket_ops::accept(socket_, 0, 0, ec));
1562
 
      }
1563
 
 
1564
 
      // Check if we need to run the operation again.
1565
 
      if (ec == asio::error::would_block
1566
 
          || ec == asio::error::try_again)
1567
 
        return false;
1568
 
      if (ec == asio::error::connection_aborted
1569
 
          && !enable_connection_aborted_)
1570
 
        return false;
1571
 
#if defined(EPROTO)
1572
 
      if (ec.value() == EPROTO && !enable_connection_aborted_)
1573
 
        return false;
1574
 
#endif // defined(EPROTO)
1575
 
 
1576
 
      // Transfer ownership of the new socket to the peer object.
1577
 
      if (!ec)
1578
 
      {
1579
 
        if (peer_endpoint_)
1580
 
          peer_endpoint_->resize(addr_len);
1581
 
        peer_.assign(protocol_, new_socket.get(), ec);
1582
 
        if (!ec)
1583
 
          new_socket.release();
1584
 
      }
1585
 
 
1586
 
      return true;
1587
 
    }
1588
 
 
1589
 
    void complete(const asio::error_code& ec, std::size_t)
1590
 
    {
1591
 
      io_service_.post(bind_handler(this->handler_, ec));
1592
 
    }
1593
 
 
1594
 
  private:
1595
 
    socket_type socket_;
1596
 
    asio::io_service& io_service_;
1597
 
    asio::io_service::work work_;
1598
 
    Socket& peer_;
1599
 
    protocol_type protocol_;
1600
 
    endpoint_type* peer_endpoint_;
1601
 
    bool enable_connection_aborted_;
1602
 
  };
1603
 
 
1604
 
  // Start an asynchronous accept. The peer and peer_endpoint objects
1605
 
  // must be valid until the accept's handler is invoked.
1606
 
  template <typename Socket, typename Handler>
1607
 
  void async_accept(implementation_type& impl, Socket& peer,
1608
 
      endpoint_type* peer_endpoint, Handler handler)
1609
 
  {
1610
 
    if (!is_open(impl))
1611
 
    {
1612
 
      this->get_io_service().post(bind_handler(handler,
1613
 
            asio::error::bad_descriptor));
1614
 
    }
1615
 
    else if (peer.is_open())
1616
 
    {
1617
 
      this->get_io_service().post(bind_handler(handler,
1618
 
            asio::error::already_open));
1619
 
    }
1620
 
    else
1621
 
    {
1622
 
      // Make socket non-blocking.
1623
 
      if (!(impl.flags_ & implementation_type::internal_non_blocking))
1624
 
      {
1625
 
        ioctl_arg_type non_blocking = 1;
1626
 
        asio::error_code ec;
1627
 
        if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
1628
 
        {
1629
 
          this->get_io_service().post(bind_handler(handler, ec));
1630
 
          return;
1631
 
        }
1632
 
        impl.flags_ |= implementation_type::internal_non_blocking;
1633
 
      }
1634
 
 
1635
 
      reactor_.start_read_op(impl.socket_, impl.reactor_data_,
1636
 
          accept_operation<Socket, Handler>(
1637
 
            impl.socket_, this->get_io_service(),
1638
 
            peer, impl.protocol_, peer_endpoint,
1639
 
            (impl.flags_ & implementation_type::enable_connection_aborted) != 0,
1640
 
            handler));
1641
 
    }
1642
 
  }
1643
 
 
1644
 
  // Connect the socket to the specified endpoint.
1645
 
  asio::error_code connect(implementation_type& impl,
1646
 
      const endpoint_type& peer_endpoint, asio::error_code& ec)
1647
 
  {
1648
 
    if (!is_open(impl))
1649
 
    {
1650
 
      ec = asio::error::bad_descriptor;
1651
 
      return ec;
1652
 
    }
1653
 
 
1654
 
    if (impl.flags_ & implementation_type::internal_non_blocking)
1655
 
    {
1656
 
      // Mark the socket as blocking while we perform the connect.
1657
 
      ioctl_arg_type non_blocking = 0;
1658
 
      if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
1659
 
        return ec;
1660
 
      impl.flags_ &= ~implementation_type::internal_non_blocking;
1661
 
    }
1662
 
 
1663
 
    // Perform the connect operation.
1664
 
    socket_ops::connect(impl.socket_,
1665
 
        peer_endpoint.data(), peer_endpoint.size(), ec);
1666
 
    return ec;
1667
 
  }
1668
 
 
1669
 
  template <typename Handler>
1670
 
  class connect_operation :
1671
 
    public handler_base_from_member<Handler>
1672
 
  {
1673
 
  public:
1674
 
    connect_operation(socket_type socket,
1675
 
        asio::io_service& io_service, Handler handler)
1676
 
      : handler_base_from_member<Handler>(handler),
1677
 
        socket_(socket),
1678
 
        io_service_(io_service),
1679
 
        work_(io_service)
1680
 
    {
1681
 
    }
1682
 
 
1683
 
    bool perform(asio::error_code& ec, std::size_t&)
1684
 
    {
1685
 
      // Check whether the operation was successful.
1686
 
      if (ec)
1687
 
        return true;
1688
 
 
1689
 
      // Get the error code from the connect operation.
1690
 
      int connect_error = 0;
1691
 
      size_t connect_error_len = sizeof(connect_error);
1692
 
      if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
1693
 
            &connect_error, &connect_error_len, ec) == socket_error_retval)
1694
 
        return true;
1695
 
 
1696
 
      // The connection failed so the handler will be posted with an error code.
1697
 
      if (connect_error)
1698
 
      {
1699
 
        ec = asio::error_code(connect_error,
1700
 
            asio::error::get_system_category());
1701
 
        return true;
1702
 
      }
1703
 
 
1704
 
      return true;
1705
 
    }
1706
 
 
1707
 
    void complete(const asio::error_code& ec, std::size_t)
1708
 
    {
1709
 
      io_service_.post(bind_handler(this->handler_, ec));
1710
 
    }
1711
 
 
1712
 
  private:
1713
 
    socket_type socket_;
1714
 
    asio::io_service& io_service_;
1715
 
    asio::io_service::work work_;
1716
 
  };
1717
 
 
1718
 
  // Start an asynchronous connect.
1719
 
  template <typename Handler>
1720
 
  void async_connect(implementation_type& impl,
1721
 
      const endpoint_type& peer_endpoint, Handler handler)
1722
 
  {
1723
 
    if (!is_open(impl))
1724
 
    {
1725
 
      this->get_io_service().post(bind_handler(handler,
1726
 
            asio::error::bad_descriptor));
1727
 
      return;
1728
 
    }
1729
 
 
1730
 
    // Make socket non-blocking.
1731
 
    if (!(impl.flags_ & implementation_type::internal_non_blocking))
1732
 
    {
1733
 
      ioctl_arg_type non_blocking = 1;
1734
 
      asio::error_code ec;
1735
 
      if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
1736
 
      {
1737
 
        this->get_io_service().post(bind_handler(handler, ec));
1738
 
        return;
1739
 
      }
1740
 
      impl.flags_ |= implementation_type::internal_non_blocking;
1741
 
    }
1742
 
 
1743
 
    // Start the connect operation. The socket is already marked as non-blocking
1744
 
    // so the connection will take place asynchronously.
1745
 
    asio::error_code ec;
1746
 
    if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
1747
 
          peer_endpoint.size(), ec) == 0)
1748
 
    {
1749
 
      // The connect operation has finished successfully so we need to post the
1750
 
      // handler immediately.
1751
 
      this->get_io_service().post(bind_handler(handler,
1752
 
            asio::error_code()));
1753
 
    }
1754
 
    else if (ec == asio::error::in_progress
1755
 
        || ec == asio::error::would_block)
1756
 
    {
1757
 
      // The connection is happening in the background, and we need to wait
1758
 
      // until the socket becomes writeable.
1759
 
      reactor_.start_connect_op(impl.socket_, impl.reactor_data_,
1760
 
          connect_operation<Handler>(impl.socket_,
1761
 
            this->get_io_service(), handler));
1762
 
    }
1763
 
    else
1764
 
    {
1765
 
      // The connect operation has failed, so post the handler immediately.
1766
 
      this->get_io_service().post(bind_handler(handler, ec));
1767
 
    }
1768
 
  }
1769
 
 
1770
 
private:
1771
 
  // The selector that performs event demultiplexing for the service.
1772
 
  Reactor& reactor_;
1773
 
};
1774
 
 
1775
 
} // namespace detail
1776
 
} // namespace asio
1777
 
 
1778
 
#include "asio/detail/pop_options.hpp"
1779
 
 
1780
 
#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP