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

« back to all changes in this revision

Viewing changes to include/libtorrent/asio/detail/win_iocp_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
 
// win_iocp_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_WIN_IOCP_SOCKET_SERVICE_HPP
12
 
#define ASIO_DETAIL_WIN_IOCP_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/win_iocp_io_service_fwd.hpp"
21
 
 
22
 
#if defined(ASIO_HAS_IOCP)
23
 
 
24
 
#include "asio/detail/push_options.hpp"
25
 
#include <cstring>
26
 
#include <boost/shared_ptr.hpp>
27
 
#include <boost/type_traits/is_same.hpp>
28
 
#include <boost/weak_ptr.hpp>
29
 
#include "asio/detail/pop_options.hpp"
30
 
 
31
 
#include "asio/buffer.hpp"
32
 
#include "asio/error.hpp"
33
 
#include "asio/io_service.hpp"
34
 
#include "asio/socket_base.hpp"
35
 
#include "asio/detail/bind_handler.hpp"
36
 
#include "asio/detail/handler_alloc_helpers.hpp"
37
 
#include "asio/detail/handler_invoke_helpers.hpp"
38
 
#include "asio/detail/mutex.hpp"
39
 
#include "asio/detail/select_reactor.hpp"
40
 
#include "asio/detail/socket_holder.hpp"
41
 
#include "asio/detail/socket_ops.hpp"
42
 
#include "asio/detail/socket_types.hpp"
43
 
#include "asio/detail/win_iocp_io_service.hpp"
44
 
 
45
 
namespace asio {
46
 
namespace detail {
47
 
 
48
 
template <typename Protocol>
49
 
class win_iocp_socket_service
50
 
  : public asio::detail::service_base<win_iocp_socket_service<Protocol> >
51
 
{
52
 
public:
53
 
  // The protocol type.
54
 
  typedef Protocol protocol_type;
55
 
 
56
 
  // The endpoint type.
57
 
  typedef typename Protocol::endpoint endpoint_type;
58
 
 
59
 
  // Base class for all operations.
60
 
  typedef win_iocp_io_service::operation operation;
61
 
 
62
 
  struct noop_deleter { void operator()(void*) {} };
63
 
  typedef boost::shared_ptr<void> shared_cancel_token_type;
64
 
  typedef boost::weak_ptr<void> weak_cancel_token_type;
65
 
 
66
 
  // The native type of a socket.
67
 
  class native_type
68
 
  {
69
 
  public:
70
 
    native_type(socket_type s)
71
 
      : socket_(s),
72
 
        have_remote_endpoint_(false)
73
 
    {
74
 
    }
75
 
 
76
 
    native_type(socket_type s, const endpoint_type& ep)
77
 
      : socket_(s),
78
 
        have_remote_endpoint_(true),
79
 
        remote_endpoint_(ep)
80
 
    {
81
 
    }
82
 
 
83
 
    void operator=(socket_type s)
84
 
    {
85
 
      socket_ = s;
86
 
      have_remote_endpoint_ = false;
87
 
      remote_endpoint_ = endpoint_type();
88
 
    }
89
 
 
90
 
    operator socket_type() const
91
 
    {
92
 
      return socket_;
93
 
    }
94
 
 
95
 
    HANDLE as_handle() const
96
 
    {
97
 
      return reinterpret_cast<HANDLE>(socket_);
98
 
    }
99
 
 
100
 
    bool have_remote_endpoint() const
101
 
    {
102
 
      return have_remote_endpoint_;
103
 
    }
104
 
 
105
 
    endpoint_type remote_endpoint() const
106
 
    {
107
 
      return remote_endpoint_;
108
 
    }
109
 
 
110
 
  private:
111
 
    socket_type socket_;
112
 
    bool have_remote_endpoint_;
113
 
    endpoint_type remote_endpoint_;
114
 
  };
115
 
 
116
 
  // The type of the reactor used for connect operations.
117
 
  typedef detail::select_reactor<true> reactor_type;
118
 
 
119
 
  // The implementation type of the socket.
120
 
  class implementation_type
121
 
  {
122
 
  public:
123
 
    // Default constructor.
124
 
    implementation_type()
125
 
      : socket_(invalid_socket),
126
 
        flags_(0),
127
 
        cancel_token_(),
128
 
        protocol_(endpoint_type().protocol()),
129
 
        next_(0),
130
 
        prev_(0)
131
 
    {
132
 
    }
133
 
 
134
 
  private:
135
 
    // Only this service will have access to the internal values.
136
 
    friend class win_iocp_socket_service;
137
 
 
138
 
    // The native socket representation.
139
 
    native_type socket_;
140
 
 
141
 
    enum
142
 
    {
143
 
      enable_connection_aborted = 1, // User wants connection_aborted errors.
144
 
      close_might_block = 2, // User set linger option for blocking close.
145
 
      user_set_non_blocking = 4 // The user wants a non-blocking socket.
146
 
    };
147
 
 
148
 
    // Flags indicating the current state of the socket.
149
 
    unsigned char flags_;
150
 
 
151
 
    // We use a shared pointer as a cancellation token here to work around the
152
 
    // broken Windows support for cancellation. MSDN says that when you call
153
 
    // closesocket any outstanding WSARecv or WSASend operations will complete
154
 
    // with the error ERROR_OPERATION_ABORTED. In practice they complete with
155
 
    // ERROR_NETNAME_DELETED, which means you can't tell the difference between
156
 
    // a local cancellation and the socket being hard-closed by the peer.
157
 
    shared_cancel_token_type cancel_token_;
158
 
 
159
 
    // The protocol associated with the socket.
160
 
    protocol_type protocol_;
161
 
 
162
 
    // Per-descriptor data used by the reactor.
163
 
    reactor_type::per_descriptor_data reactor_data_;
164
 
 
165
 
#if defined(ASIO_ENABLE_CANCELIO)
166
 
    // The ID of the thread from which it is safe to cancel asynchronous
167
 
    // operations. 0 means no asynchronous operations have been started yet.
168
 
    // ~0 means asynchronous operations have been started from more than one
169
 
    // thread, and cancellation is not supported for the socket.
170
 
    DWORD safe_cancellation_thread_id_;
171
 
#endif // defined(ASIO_ENABLE_CANCELIO)
172
 
 
173
 
    // Pointers to adjacent socket implementations in linked list.
174
 
    implementation_type* next_;
175
 
    implementation_type* prev_;
176
 
  };
177
 
 
178
 
  // The maximum number of buffers to support in a single operation.
179
 
  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
180
 
 
181
 
  // Constructor.
182
 
  win_iocp_socket_service(asio::io_service& io_service)
183
 
    : asio::detail::service_base<
184
 
        win_iocp_socket_service<Protocol> >(io_service),
185
 
      iocp_service_(asio::use_service<win_iocp_io_service>(io_service)),
186
 
      reactor_(0),
187
 
      mutex_(),
188
 
      impl_list_(0)
189
 
  {
190
 
  }
191
 
 
192
 
  // Destroy all user-defined handler objects owned by the service.
193
 
  void shutdown_service()
194
 
  {
195
 
    // Close all implementations, causing all operations to complete.
196
 
    asio::detail::mutex::scoped_lock lock(mutex_);
197
 
    implementation_type* impl = impl_list_;
198
 
    while (impl)
199
 
    {
200
 
      asio::error_code ignored_ec;
201
 
      close_for_destruction(*impl);
202
 
      impl = impl->next_;
203
 
    }
204
 
  }
205
 
 
206
 
  // Construct a new socket implementation.
207
 
  void construct(implementation_type& impl)
208
 
  {
209
 
    impl.socket_ = invalid_socket;
210
 
    impl.flags_ = 0;
211
 
    impl.cancel_token_.reset();
212
 
#if defined(ASIO_ENABLE_CANCELIO)
213
 
    impl.safe_cancellation_thread_id_ = 0;
214
 
#endif // defined(ASIO_ENABLE_CANCELIO)
215
 
 
216
 
    // Insert implementation into linked list of all implementations.
217
 
    asio::detail::mutex::scoped_lock lock(mutex_);
218
 
    impl.next_ = impl_list_;
219
 
    impl.prev_ = 0;
220
 
    if (impl_list_)
221
 
      impl_list_->prev_ = &impl;
222
 
    impl_list_ = &impl;
223
 
  }
224
 
 
225
 
  // Destroy a socket implementation.
226
 
  void destroy(implementation_type& impl)
227
 
  {
228
 
    close_for_destruction(impl);
229
 
 
230
 
    // Remove implementation from linked list of all implementations.
231
 
    asio::detail::mutex::scoped_lock lock(mutex_);
232
 
    if (impl_list_ == &impl)
233
 
      impl_list_ = impl.next_;
234
 
    if (impl.prev_)
235
 
      impl.prev_->next_ = impl.next_;
236
 
    if (impl.next_)
237
 
      impl.next_->prev_= impl.prev_;
238
 
    impl.next_ = 0;
239
 
    impl.prev_ = 0;
240
 
  }
241
 
 
242
 
  // Open a new socket implementation.
243
 
  asio::error_code open(implementation_type& impl,
244
 
      const protocol_type& protocol, asio::error_code& ec)
245
 
  {
246
 
    if (is_open(impl))
247
 
    {
248
 
      ec = asio::error::already_open;
249
 
      return ec;
250
 
    }
251
 
 
252
 
    socket_holder sock(socket_ops::socket(protocol.family(), protocol.type(),
253
 
          protocol.protocol(), ec));
254
 
    if (sock.get() == invalid_socket)
255
 
      return ec;
256
 
 
257
 
    HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());
258
 
    if (iocp_service_.register_handle(sock_as_handle, ec))
259
 
      return ec;
260
 
 
261
 
    impl.socket_ = sock.release();
262
 
    impl.flags_ = 0;
263
 
    impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
264
 
    impl.protocol_ = protocol;
265
 
    ec = asio::error_code();
266
 
    return ec;
267
 
  }
268
 
 
269
 
  // Assign a native socket to a socket implementation.
270
 
  asio::error_code assign(implementation_type& impl,
271
 
      const protocol_type& protocol, const native_type& native_socket,
272
 
      asio::error_code& ec)
273
 
  {
274
 
    if (is_open(impl))
275
 
    {
276
 
      ec = asio::error::already_open;
277
 
      return ec;
278
 
    }
279
 
 
280
 
    if (iocp_service_.register_handle(native_socket.as_handle(), ec))
281
 
      return ec;
282
 
 
283
 
    impl.socket_ = native_socket;
284
 
    impl.flags_ = 0;
285
 
    impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
286
 
    impl.protocol_ = protocol;
287
 
    ec = asio::error_code();
288
 
    return ec;
289
 
  }
290
 
 
291
 
  // Determine whether the socket is open.
292
 
  bool is_open(const implementation_type& impl) const
293
 
  {
294
 
    return impl.socket_ != invalid_socket;
295
 
  }
296
 
 
297
 
  // Destroy a socket implementation.
298
 
  asio::error_code close(implementation_type& impl,
299
 
      asio::error_code& ec)
300
 
  {
301
 
    if (is_open(impl))
302
 
    {
303
 
      // Check if the reactor was created, in which case we need to close the
304
 
      // socket on the reactor as well to cancel any operations that might be
305
 
      // running there.
306
 
      reactor_type* reactor = static_cast<reactor_type*>(
307
 
            interlocked_compare_exchange_pointer(
308
 
              reinterpret_cast<void**>(&reactor_), 0, 0));
309
 
      if (reactor)
310
 
        reactor->close_descriptor(impl.socket_, impl.reactor_data_);
311
 
 
312
 
      if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
313
 
        return ec;
314
 
 
315
 
      impl.socket_ = invalid_socket;
316
 
      impl.flags_ = 0;
317
 
      impl.cancel_token_.reset();
318
 
#if defined(ASIO_ENABLE_CANCELIO)
319
 
      impl.safe_cancellation_thread_id_ = 0;
320
 
#endif // defined(ASIO_ENABLE_CANCELIO)
321
 
    }
322
 
 
323
 
    ec = asio::error_code();
324
 
    return ec;
325
 
  }
326
 
 
327
 
  // Get the native socket representation.
328
 
  native_type native(implementation_type& impl)
329
 
  {
330
 
    return impl.socket_;
331
 
  }
332
 
 
333
 
  // Cancel all operations associated with the socket.
334
 
  asio::error_code cancel(implementation_type& impl,
335
 
      asio::error_code& ec)
336
 
  {
337
 
    if (!is_open(impl))
338
 
    {
339
 
      ec = asio::error::bad_descriptor;
340
 
      return ec;
341
 
    }
342
 
    else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
343
 
          ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
344
 
    {
345
 
      // The version of Windows supports cancellation from any thread.
346
 
      typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
347
 
      cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
348
 
      socket_type sock = impl.socket_;
349
 
      HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
350
 
      if (!cancel_io_ex(sock_as_handle, 0))
351
 
      {
352
 
        DWORD last_error = ::GetLastError();
353
 
        if (last_error == ERROR_NOT_FOUND)
354
 
        {
355
 
          // ERROR_NOT_FOUND means that there were no operations to be
356
 
          // cancelled. We swallow this error to match the behaviour on other
357
 
          // platforms.
358
 
          ec = asio::error_code();
359
 
        }
360
 
        else
361
 
        {
362
 
          ec = asio::error_code(last_error,
363
 
              asio::error::get_system_category());
364
 
        }
365
 
      }
366
 
      else
367
 
      {
368
 
        ec = asio::error_code();
369
 
      }
370
 
    }
371
 
#if defined(ASIO_ENABLE_CANCELIO)
372
 
    else if (impl.safe_cancellation_thread_id_ == 0)
373
 
    {
374
 
      // No operations have been started, so there's nothing to cancel.
375
 
      ec = asio::error_code();
376
 
    }
377
 
    else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
378
 
    {
379
 
      // Asynchronous operations have been started from the current thread only,
380
 
      // so it is safe to try to cancel them using CancelIo.
381
 
      socket_type sock = impl.socket_;
382
 
      HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
383
 
      if (!::CancelIo(sock_as_handle))
384
 
      {
385
 
        DWORD last_error = ::GetLastError();
386
 
        ec = asio::error_code(last_error,
387
 
            asio::error::get_system_category());
388
 
      }
389
 
      else
390
 
      {
391
 
        ec = asio::error_code();
392
 
      }
393
 
    }
394
 
    else
395
 
    {
396
 
      // Asynchronous operations have been started from more than one thread,
397
 
      // so cancellation is not safe.
398
 
      ec = asio::error::operation_not_supported;
399
 
    }
400
 
#else // defined(ASIO_ENABLE_CANCELIO)
401
 
    else
402
 
    {
403
 
      // Cancellation is not supported as CancelIo may not be used.
404
 
      ec = asio::error::operation_not_supported;
405
 
    }
406
 
#endif // defined(ASIO_ENABLE_CANCELIO)
407
 
 
408
 
    return ec;
409
 
  }
410
 
 
411
 
  // Determine whether the socket is at the out-of-band data mark.
412
 
  bool at_mark(const implementation_type& impl,
413
 
      asio::error_code& ec) const
414
 
  {
415
 
    if (!is_open(impl))
416
 
    {
417
 
      ec = asio::error::bad_descriptor;
418
 
      return false;
419
 
    }
420
 
 
421
 
    asio::detail::ioctl_arg_type value = 0;
422
 
    socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
423
 
    return ec ? false : value != 0;
424
 
  }
425
 
 
426
 
  // Determine the number of bytes available for reading.
427
 
  std::size_t available(const implementation_type& impl,
428
 
      asio::error_code& ec) const
429
 
  {
430
 
    if (!is_open(impl))
431
 
    {
432
 
      ec = asio::error::bad_descriptor;
433
 
      return 0;
434
 
    }
435
 
 
436
 
    asio::detail::ioctl_arg_type value = 0;
437
 
    socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
438
 
    return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
439
 
  }
440
 
 
441
 
  // Bind the socket to the specified local endpoint.
442
 
  asio::error_code bind(implementation_type& impl,
443
 
      const endpoint_type& endpoint, asio::error_code& ec)
444
 
  {
445
 
    if (!is_open(impl))
446
 
    {
447
 
      ec = asio::error::bad_descriptor;
448
 
      return ec;
449
 
    }
450
 
 
451
 
    socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
452
 
    return ec;
453
 
  }
454
 
 
455
 
  // Place the socket into the state where it will listen for new connections.
456
 
  asio::error_code listen(implementation_type& impl, int backlog,
457
 
      asio::error_code& ec)
458
 
  {
459
 
    if (!is_open(impl))
460
 
    {
461
 
      ec = asio::error::bad_descriptor;
462
 
      return ec;
463
 
    }
464
 
 
465
 
    socket_ops::listen(impl.socket_, backlog, ec);
466
 
    return ec;
467
 
  }
468
 
 
469
 
  // Set a socket option.
470
 
  template <typename Option>
471
 
  asio::error_code set_option(implementation_type& impl,
472
 
      const Option& option, asio::error_code& ec)
473
 
  {
474
 
    if (!is_open(impl))
475
 
    {
476
 
      ec = asio::error::bad_descriptor;
477
 
      return ec;
478
 
    }
479
 
 
480
 
    if (option.level(impl.protocol_) == custom_socket_option_level
481
 
        && option.name(impl.protocol_) == enable_connection_aborted_option)
482
 
    {
483
 
      if (option.size(impl.protocol_) != sizeof(int))
484
 
      {
485
 
        ec = asio::error::invalid_argument;
486
 
      }
487
 
      else
488
 
      {
489
 
        if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
490
 
          impl.flags_ |= implementation_type::enable_connection_aborted;
491
 
        else
492
 
          impl.flags_ &= ~implementation_type::enable_connection_aborted;
493
 
        ec = asio::error_code();
494
 
      }
495
 
      return ec;
496
 
    }
497
 
    else
498
 
    {
499
 
      if (option.level(impl.protocol_) == SOL_SOCKET
500
 
          && option.name(impl.protocol_) == SO_LINGER)
501
 
      {
502
 
        const ::linger* linger_option =
503
 
          reinterpret_cast<const ::linger*>(option.data(impl.protocol_));
504
 
        if (linger_option->l_onoff != 0 && linger_option->l_linger != 0)
505
 
          impl.flags_ |= implementation_type::close_might_block;
506
 
        else
507
 
          impl.flags_ &= ~implementation_type::close_might_block;
508
 
      }
509
 
 
510
 
      socket_ops::setsockopt(impl.socket_,
511
 
          option.level(impl.protocol_), option.name(impl.protocol_),
512
 
          option.data(impl.protocol_), option.size(impl.protocol_), ec);
513
 
      return ec;
514
 
    }
515
 
  }
516
 
 
517
 
  // Set a socket option.
518
 
  template <typename Option>
519
 
  asio::error_code get_option(const implementation_type& impl,
520
 
      Option& option, asio::error_code& ec) const
521
 
  {
522
 
    if (!is_open(impl))
523
 
    {
524
 
      ec = asio::error::bad_descriptor;
525
 
      return ec;
526
 
    }
527
 
 
528
 
    if (option.level(impl.protocol_) == custom_socket_option_level
529
 
        && option.name(impl.protocol_) == enable_connection_aborted_option)
530
 
    {
531
 
      if (option.size(impl.protocol_) != sizeof(int))
532
 
      {
533
 
        ec = asio::error::invalid_argument;
534
 
      }
535
 
      else
536
 
      {
537
 
        int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
538
 
        if (impl.flags_ & implementation_type::enable_connection_aborted)
539
 
          *target = 1;
540
 
        else
541
 
          *target = 0;
542
 
        option.resize(impl.protocol_, sizeof(int));
543
 
        ec = asio::error_code();
544
 
      }
545
 
      return ec;
546
 
    }
547
 
    else
548
 
    {
549
 
      size_t size = option.size(impl.protocol_);
550
 
      socket_ops::getsockopt(impl.socket_,
551
 
          option.level(impl.protocol_), option.name(impl.protocol_),
552
 
          option.data(impl.protocol_), &size, ec);
553
 
      if (!ec)
554
 
        option.resize(impl.protocol_, size);
555
 
      return ec;
556
 
    }
557
 
  }
558
 
 
559
 
  // Perform an IO control command on the socket.
560
 
  template <typename IO_Control_Command>
561
 
  asio::error_code io_control(implementation_type& impl,
562
 
      IO_Control_Command& command, asio::error_code& ec)
563
 
  {
564
 
    if (!is_open(impl))
565
 
    {
566
 
      ec = asio::error::bad_descriptor;
567
 
      return ec;
568
 
    }
569
 
 
570
 
    socket_ops::ioctl(impl.socket_, command.name(),
571
 
        static_cast<ioctl_arg_type*>(command.data()), ec);
572
 
 
573
 
    if (!ec && command.name() == static_cast<int>(FIONBIO))
574
 
    {
575
 
      if (command.get())
576
 
        impl.flags_ |= implementation_type::user_set_non_blocking;
577
 
      else
578
 
        impl.flags_ &= ~implementation_type::user_set_non_blocking;
579
 
    }
580
 
 
581
 
    return ec;
582
 
  }
583
 
 
584
 
  // Get the local endpoint.
585
 
  endpoint_type local_endpoint(const implementation_type& impl,
586
 
      asio::error_code& ec) const
587
 
  {
588
 
    if (!is_open(impl))
589
 
    {
590
 
      ec = asio::error::bad_descriptor;
591
 
      return endpoint_type();
592
 
    }
593
 
 
594
 
    endpoint_type endpoint;
595
 
    std::size_t addr_len = endpoint.capacity();
596
 
    if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
597
 
      return endpoint_type();
598
 
    endpoint.resize(addr_len);
599
 
    return endpoint;
600
 
  }
601
 
 
602
 
  // Get the remote endpoint.
603
 
  endpoint_type remote_endpoint(const implementation_type& impl,
604
 
      asio::error_code& ec) const
605
 
  {
606
 
    if (!is_open(impl))
607
 
    {
608
 
      ec = asio::error::bad_descriptor;
609
 
      return endpoint_type();
610
 
    }
611
 
 
612
 
    if (impl.socket_.have_remote_endpoint())
613
 
    {
614
 
      // Check if socket is still connected.
615
 
      DWORD connect_time = 0;
616
 
      size_t connect_time_len = sizeof(connect_time);
617
 
      if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_CONNECT_TIME,
618
 
            &connect_time, &connect_time_len, ec) == socket_error_retval)
619
 
      {
620
 
        return endpoint_type();
621
 
      }
622
 
      if (connect_time == 0xFFFFFFFF)
623
 
      {
624
 
        ec = asio::error::not_connected;
625
 
        return endpoint_type();
626
 
      }
627
 
 
628
 
      ec = asio::error_code();
629
 
      return impl.socket_.remote_endpoint();
630
 
    }
631
 
    else
632
 
    {
633
 
      endpoint_type endpoint;
634
 
      std::size_t addr_len = endpoint.capacity();
635
 
      if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
636
 
        return endpoint_type();
637
 
      endpoint.resize(addr_len);
638
 
      return endpoint;
639
 
    }
640
 
  }
641
 
 
642
 
  /// Disable sends or receives on the socket.
643
 
  asio::error_code shutdown(implementation_type& impl,
644
 
      socket_base::shutdown_type what, asio::error_code& ec)
645
 
  {
646
 
    if (!is_open(impl))
647
 
    {
648
 
      ec = asio::error::bad_descriptor;
649
 
      return ec;
650
 
    }
651
 
 
652
 
    socket_ops::shutdown(impl.socket_, what, ec);
653
 
    return ec;
654
 
  }
655
 
 
656
 
  // Send the given data to the peer. Returns the number of bytes sent.
657
 
  template <typename ConstBufferSequence>
658
 
  size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
659
 
      socket_base::message_flags flags, asio::error_code& ec)
660
 
  {
661
 
    if (!is_open(impl))
662
 
    {
663
 
      ec = asio::error::bad_descriptor;
664
 
      return 0;
665
 
    }
666
 
 
667
 
    // Copy buffers into WSABUF array.
668
 
    ::WSABUF bufs[max_buffers];
669
 
    typename ConstBufferSequence::const_iterator iter = buffers.begin();
670
 
    typename ConstBufferSequence::const_iterator end = buffers.end();
671
 
    DWORD i = 0;
672
 
    size_t total_buffer_size = 0;
673
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
674
 
    {
675
 
      asio::const_buffer buffer(*iter);
676
 
      bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
677
 
      bufs[i].buf = const_cast<char*>(
678
 
          asio::buffer_cast<const char*>(buffer));
679
 
      total_buffer_size += asio::buffer_size(buffer);
680
 
    }
681
 
 
682
 
    // A request to receive 0 bytes on a stream socket is a no-op.
683
 
    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
684
 
    {
685
 
      ec = asio::error_code();
686
 
      return 0;
687
 
    }
688
 
 
689
 
    // Send the data.
690
 
    DWORD bytes_transferred = 0;
691
 
    int result = ::WSASend(impl.socket_, bufs,
692
 
        i, &bytes_transferred, flags, 0, 0);
693
 
    if (result != 0)
694
 
    {
695
 
      DWORD last_error = ::WSAGetLastError();
696
 
      if (last_error == ERROR_NETNAME_DELETED)
697
 
        last_error = WSAECONNRESET;
698
 
      else if (last_error == ERROR_PORT_UNREACHABLE)
699
 
        last_error = WSAECONNREFUSED;
700
 
      ec = asio::error_code(last_error,
701
 
          asio::error::get_system_category());
702
 
      return 0;
703
 
    }
704
 
 
705
 
    ec = asio::error_code();
706
 
    return bytes_transferred;
707
 
  }
708
 
 
709
 
  // Wait until data can be sent without blocking.
710
 
  size_t send(implementation_type& impl, const null_buffers&,
711
 
      socket_base::message_flags, asio::error_code& ec)
712
 
  {
713
 
    if (!is_open(impl))
714
 
    {
715
 
      ec = asio::error::bad_descriptor;
716
 
      return 0;
717
 
    }
718
 
 
719
 
    // Wait for socket to become ready.
720
 
    socket_ops::poll_write(impl.socket_, ec);
721
 
 
722
 
    return 0;
723
 
  }
724
 
 
725
 
  template <typename ConstBufferSequence, typename Handler>
726
 
  class send_operation
727
 
    : public operation
728
 
  {
729
 
  public:
730
 
    send_operation(win_iocp_io_service& io_service,
731
 
        weak_cancel_token_type cancel_token,
732
 
        const ConstBufferSequence& buffers, Handler handler)
733
 
      : operation(io_service,
734
 
          &send_operation<ConstBufferSequence, Handler>::do_completion_impl,
735
 
          &send_operation<ConstBufferSequence, Handler>::destroy_impl),
736
 
        work_(io_service.get_io_service()),
737
 
        cancel_token_(cancel_token),
738
 
        buffers_(buffers),
739
 
        handler_(handler)
740
 
    {
741
 
    }
742
 
 
743
 
  private:
744
 
    static void do_completion_impl(operation* op,
745
 
        DWORD last_error, size_t bytes_transferred)
746
 
    {
747
 
      // Take ownership of the operation object.
748
 
      typedef send_operation<ConstBufferSequence, Handler> op_type;
749
 
      op_type* handler_op(static_cast<op_type*>(op));
750
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
751
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
752
 
 
753
 
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
754
 
      // Check whether buffers are still valid.
755
 
      typename ConstBufferSequence::const_iterator iter
756
 
        = handler_op->buffers_.begin();
757
 
      typename ConstBufferSequence::const_iterator end
758
 
        = handler_op->buffers_.end();
759
 
      while (iter != end)
760
 
      {
761
 
        asio::const_buffer buffer(*iter);
762
 
        asio::buffer_cast<const char*>(buffer);
763
 
        ++iter;
764
 
      }
765
 
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
766
 
 
767
 
      // Map non-portable errors to their portable counterparts.
768
 
      asio::error_code ec(last_error,
769
 
          asio::error::get_system_category());
770
 
      if (ec.value() == ERROR_NETNAME_DELETED)
771
 
      {
772
 
        if (handler_op->cancel_token_.expired())
773
 
          ec = asio::error::operation_aborted;
774
 
        else
775
 
          ec = asio::error::connection_reset;
776
 
      }
777
 
      else if (ec.value() == ERROR_PORT_UNREACHABLE)
778
 
      {
779
 
        ec = asio::error::connection_refused;
780
 
      }
781
 
 
782
 
      // Make a copy of the handler so that the memory can be deallocated before
783
 
      // the upcall is made.
784
 
      Handler handler(handler_op->handler_);
785
 
 
786
 
      // Free the memory associated with the handler.
787
 
      ptr.reset();
788
 
 
789
 
      // Call the handler.
790
 
      asio_handler_invoke_helpers::invoke(
791
 
          detail::bind_handler(handler, ec, bytes_transferred), &handler);
792
 
    }
793
 
 
794
 
    static void destroy_impl(operation* op)
795
 
    {
796
 
      // Take ownership of the operation object.
797
 
      typedef send_operation<ConstBufferSequence, Handler> op_type;
798
 
      op_type* handler_op(static_cast<op_type*>(op));
799
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
800
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
801
 
 
802
 
      // A sub-object of the handler may be the true owner of the memory
803
 
      // associated with the handler. Consequently, a local copy of the handler
804
 
      // is required to ensure that any owning sub-object remains valid until
805
 
      // after we have deallocated the memory here.
806
 
      Handler handler(handler_op->handler_);
807
 
      (void)handler;
808
 
 
809
 
      // Free the memory associated with the handler.
810
 
      ptr.reset();
811
 
    }
812
 
 
813
 
    asio::io_service::work work_;
814
 
    weak_cancel_token_type cancel_token_;
815
 
    ConstBufferSequence buffers_;
816
 
    Handler handler_;
817
 
  };
818
 
 
819
 
  // Start an asynchronous send. The data being sent must be valid for the
820
 
  // lifetime of the asynchronous operation.
821
 
  template <typename ConstBufferSequence, typename Handler>
822
 
  void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
823
 
      socket_base::message_flags flags, Handler handler)
824
 
  {
825
 
    if (!is_open(impl))
826
 
    {
827
 
      this->get_io_service().post(bind_handler(handler,
828
 
            asio::error::bad_descriptor, 0));
829
 
      return;
830
 
    }
831
 
 
832
 
#if defined(ASIO_ENABLE_CANCELIO)
833
 
    // Update the ID of the thread from which cancellation is safe.
834
 
    if (impl.safe_cancellation_thread_id_ == 0)
835
 
      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
836
 
    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
837
 
      impl.safe_cancellation_thread_id_ = ~DWORD(0);
838
 
#endif // defined(ASIO_ENABLE_CANCELIO)
839
 
 
840
 
    // Allocate and construct an operation to wrap the handler.
841
 
    typedef send_operation<ConstBufferSequence, Handler> value_type;
842
 
    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
843
 
    raw_handler_ptr<alloc_traits> raw_ptr(handler);
844
 
    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_,
845
 
        impl.cancel_token_, buffers, handler);
846
 
 
847
 
    // Copy buffers into WSABUF array.
848
 
    ::WSABUF bufs[max_buffers];
849
 
    typename ConstBufferSequence::const_iterator iter = buffers.begin();
850
 
    typename ConstBufferSequence::const_iterator end = buffers.end();
851
 
    DWORD i = 0;
852
 
    size_t total_buffer_size = 0;
853
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
854
 
    {
855
 
      asio::const_buffer buffer(*iter);
856
 
      bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
857
 
      bufs[i].buf = const_cast<char*>(
858
 
          asio::buffer_cast<const char*>(buffer));
859
 
      total_buffer_size += asio::buffer_size(buffer);
860
 
    }
861
 
 
862
 
    // A request to receive 0 bytes on a stream socket is a no-op.
863
 
    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
864
 
    {
865
 
      asio::io_service::work work(this->get_io_service());
866
 
      ptr.reset();
867
 
      asio::error_code error;
868
 
      iocp_service_.post(bind_handler(handler, error, 0));
869
 
      return;
870
 
    }
871
 
 
872
 
    // Send the data.
873
 
    DWORD bytes_transferred = 0;
874
 
    int result = ::WSASend(impl.socket_, bufs, i,
875
 
        &bytes_transferred, flags, ptr.get(), 0);
876
 
    DWORD last_error = ::WSAGetLastError();
877
 
 
878
 
    // Check if the operation completed immediately.
879
 
    if (result != 0 && last_error != WSA_IO_PENDING)
880
 
    {
881
 
      asio::io_service::work work(this->get_io_service());
882
 
      ptr.reset();
883
 
      asio::error_code ec(last_error,
884
 
          asio::error::get_system_category());
885
 
      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
886
 
    }
887
 
    else
888
 
    {
889
 
      ptr.release();
890
 
    }
891
 
  }
892
 
 
893
 
  template <typename Handler>
894
 
  class null_buffers_operation
895
 
  {
896
 
  public:
897
 
    null_buffers_operation(asio::io_service& io_service, Handler handler)
898
 
      : work_(io_service),
899
 
        handler_(handler)
900
 
    {
901
 
    }
902
 
 
903
 
    bool perform(asio::error_code&,
904
 
        std::size_t& bytes_transferred)
905
 
    {
906
 
      bytes_transferred = 0;
907
 
      return true;
908
 
    }
909
 
 
910
 
    void complete(const asio::error_code& ec,
911
 
        std::size_t bytes_transferred)
912
 
    {
913
 
      work_.get_io_service().post(bind_handler(
914
 
            handler_, ec, bytes_transferred));
915
 
    }
916
 
 
917
 
  private:
918
 
    asio::io_service::work work_;
919
 
    Handler handler_;
920
 
  };
921
 
 
922
 
  // Start an asynchronous wait until data can be sent without blocking.
923
 
  template <typename Handler>
924
 
  void async_send(implementation_type& impl, const null_buffers&,
925
 
      socket_base::message_flags, Handler handler)
926
 
  {
927
 
    if (!is_open(impl))
928
 
    {
929
 
      this->get_io_service().post(bind_handler(handler,
930
 
            asio::error::bad_descriptor, 0));
931
 
    }
932
 
    else
933
 
    {
934
 
      // Check if the reactor was already obtained from the io_service.
935
 
      reactor_type* reactor = static_cast<reactor_type*>(
936
 
            interlocked_compare_exchange_pointer(
937
 
              reinterpret_cast<void**>(&reactor_), 0, 0));
938
 
      if (!reactor)
939
 
      {
940
 
        reactor = &(asio::use_service<reactor_type>(
941
 
              this->get_io_service()));
942
 
        interlocked_exchange_pointer(
943
 
            reinterpret_cast<void**>(&reactor_), reactor);
944
 
      }
945
 
 
946
 
      reactor->start_write_op(impl.socket_, impl.reactor_data_,
947
 
          null_buffers_operation<Handler>(this->get_io_service(), handler),
948
 
          false);
949
 
    }
950
 
  }
951
 
 
952
 
  // Send a datagram to the specified endpoint. Returns the number of bytes
953
 
  // sent.
954
 
  template <typename ConstBufferSequence>
955
 
  size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
956
 
      const endpoint_type& destination, socket_base::message_flags flags,
957
 
      asio::error_code& ec)
958
 
  {
959
 
    if (!is_open(impl))
960
 
    {
961
 
      ec = asio::error::bad_descriptor;
962
 
      return 0;
963
 
    }
964
 
 
965
 
    // Copy buffers into WSABUF array.
966
 
    ::WSABUF bufs[max_buffers];
967
 
    typename ConstBufferSequence::const_iterator iter = buffers.begin();
968
 
    typename ConstBufferSequence::const_iterator end = buffers.end();
969
 
    DWORD i = 0;
970
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
971
 
    {
972
 
      asio::const_buffer buffer(*iter);
973
 
      bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
974
 
      bufs[i].buf = const_cast<char*>(
975
 
          asio::buffer_cast<const char*>(buffer));
976
 
    }
977
 
 
978
 
    // Send the data.
979
 
    DWORD bytes_transferred = 0;
980
 
    int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred,
981
 
        flags, destination.data(), static_cast<int>(destination.size()), 0, 0);
982
 
    if (result != 0)
983
 
    {
984
 
      DWORD last_error = ::WSAGetLastError();
985
 
      if (last_error == ERROR_PORT_UNREACHABLE)
986
 
        last_error = WSAECONNREFUSED;
987
 
      ec = asio::error_code(last_error,
988
 
          asio::error::get_system_category());
989
 
      return 0;
990
 
    }
991
 
 
992
 
    ec = asio::error_code();
993
 
    return bytes_transferred;
994
 
  }
995
 
 
996
 
  // Wait until data can be sent without blocking.
997
 
  size_t send_to(implementation_type& impl, const null_buffers&,
998
 
      socket_base::message_flags, const endpoint_type&,
999
 
      asio::error_code& ec)
1000
 
  {
1001
 
    if (!is_open(impl))
1002
 
    {
1003
 
      ec = asio::error::bad_descriptor;
1004
 
      return 0;
1005
 
    }
1006
 
 
1007
 
    // Wait for socket to become ready.
1008
 
    socket_ops::poll_write(impl.socket_, ec);
1009
 
 
1010
 
    return 0;
1011
 
  }
1012
 
 
1013
 
  template <typename ConstBufferSequence, typename Handler>
1014
 
  class send_to_operation
1015
 
    : public operation
1016
 
  {
1017
 
  public:
1018
 
    send_to_operation(win_iocp_io_service& io_service,
1019
 
        const ConstBufferSequence& buffers, Handler handler)
1020
 
      : operation(io_service,
1021
 
          &send_to_operation<ConstBufferSequence, Handler>::do_completion_impl,
1022
 
          &send_to_operation<ConstBufferSequence, Handler>::destroy_impl),
1023
 
        work_(io_service.get_io_service()),
1024
 
        buffers_(buffers),
1025
 
        handler_(handler)
1026
 
    {
1027
 
    }
1028
 
 
1029
 
  private:
1030
 
    static void do_completion_impl(operation* op,
1031
 
        DWORD last_error, size_t bytes_transferred)
1032
 
    {
1033
 
      // Take ownership of the operation object.
1034
 
      typedef send_to_operation<ConstBufferSequence, Handler> op_type;
1035
 
      op_type* handler_op(static_cast<op_type*>(op));
1036
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
1037
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
1038
 
 
1039
 
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1040
 
      // Check whether buffers are still valid.
1041
 
      typename ConstBufferSequence::const_iterator iter
1042
 
        = handler_op->buffers_.begin();
1043
 
      typename ConstBufferSequence::const_iterator end
1044
 
        = handler_op->buffers_.end();
1045
 
      while (iter != end)
1046
 
      {
1047
 
        asio::const_buffer buffer(*iter);
1048
 
        asio::buffer_cast<const char*>(buffer);
1049
 
        ++iter;
1050
 
      }
1051
 
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1052
 
 
1053
 
      // Map non-portable errors to their portable counterparts.
1054
 
      asio::error_code ec(last_error,
1055
 
          asio::error::get_system_category());
1056
 
      if (ec.value() == ERROR_PORT_UNREACHABLE)
1057
 
      {
1058
 
        ec = asio::error::connection_refused;
1059
 
      }
1060
 
 
1061
 
      // Make a copy of the handler so that the memory can be deallocated before
1062
 
      // the upcall is made.
1063
 
      Handler handler(handler_op->handler_);
1064
 
 
1065
 
      // Free the memory associated with the handler.
1066
 
      ptr.reset();
1067
 
 
1068
 
      // Call the handler.
1069
 
      asio_handler_invoke_helpers::invoke(
1070
 
          detail::bind_handler(handler, ec, bytes_transferred), &handler);
1071
 
    }
1072
 
 
1073
 
    static void destroy_impl(operation* op)
1074
 
    {
1075
 
      // Take ownership of the operation object.
1076
 
      typedef send_to_operation<ConstBufferSequence, Handler> op_type;
1077
 
      op_type* handler_op(static_cast<op_type*>(op));
1078
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
1079
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
1080
 
 
1081
 
      // A sub-object of the handler may be the true owner of the memory
1082
 
      // associated with the handler. Consequently, a local copy of the handler
1083
 
      // is required to ensure that any owning sub-object remains valid until
1084
 
      // after we have deallocated the memory here.
1085
 
      Handler handler(handler_op->handler_);
1086
 
      (void)handler;
1087
 
 
1088
 
      // Free the memory associated with the handler.
1089
 
      ptr.reset();
1090
 
    }
1091
 
 
1092
 
    asio::io_service::work work_;
1093
 
    ConstBufferSequence buffers_;
1094
 
    Handler handler_;
1095
 
  };
1096
 
 
1097
 
  // Start an asynchronous send. The data being sent must be valid for the
1098
 
  // lifetime of the asynchronous operation.
1099
 
  template <typename ConstBufferSequence, typename Handler>
1100
 
  void async_send_to(implementation_type& impl,
1101
 
      const ConstBufferSequence& buffers, const endpoint_type& destination,
1102
 
      socket_base::message_flags flags, Handler handler)
1103
 
  {
1104
 
    if (!is_open(impl))
1105
 
    {
1106
 
      this->get_io_service().post(bind_handler(handler,
1107
 
            asio::error::bad_descriptor, 0));
1108
 
      return;
1109
 
    }
1110
 
 
1111
 
#if defined(ASIO_ENABLE_CANCELIO)
1112
 
    // Update the ID of the thread from which cancellation is safe.
1113
 
    if (impl.safe_cancellation_thread_id_ == 0)
1114
 
      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
1115
 
    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
1116
 
      impl.safe_cancellation_thread_id_ = ~DWORD(0);
1117
 
#endif // defined(ASIO_ENABLE_CANCELIO)
1118
 
 
1119
 
    // Allocate and construct an operation to wrap the handler.
1120
 
    typedef send_to_operation<ConstBufferSequence, Handler> value_type;
1121
 
    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
1122
 
    raw_handler_ptr<alloc_traits> raw_ptr(handler);
1123
 
    handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
1124
 
 
1125
 
    // Copy buffers into WSABUF array.
1126
 
    ::WSABUF bufs[max_buffers];
1127
 
    typename ConstBufferSequence::const_iterator iter = buffers.begin();
1128
 
    typename ConstBufferSequence::const_iterator end = buffers.end();
1129
 
    DWORD i = 0;
1130
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
1131
 
    {
1132
 
      asio::const_buffer buffer(*iter);
1133
 
      bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
1134
 
      bufs[i].buf = const_cast<char*>(
1135
 
          asio::buffer_cast<const char*>(buffer));
1136
 
    }
1137
 
 
1138
 
    // Send the data.
1139
 
    DWORD bytes_transferred = 0;
1140
 
    int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, flags,
1141
 
        destination.data(), static_cast<int>(destination.size()), ptr.get(), 0);
1142
 
    DWORD last_error = ::WSAGetLastError();
1143
 
 
1144
 
    // Check if the operation completed immediately.
1145
 
    if (result != 0 && last_error != WSA_IO_PENDING)
1146
 
    {
1147
 
      asio::io_service::work work(this->get_io_service());
1148
 
      ptr.reset();
1149
 
      asio::error_code ec(last_error,
1150
 
          asio::error::get_system_category());
1151
 
      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
1152
 
    }
1153
 
    else
1154
 
    {
1155
 
      ptr.release();
1156
 
    }
1157
 
  }
1158
 
 
1159
 
  // Start an asynchronous wait until data can be sent without blocking.
1160
 
  template <typename Handler>
1161
 
  void async_send_to(implementation_type& impl, const null_buffers&,
1162
 
      socket_base::message_flags, const endpoint_type&, Handler handler)
1163
 
  {
1164
 
    if (!is_open(impl))
1165
 
    {
1166
 
      this->get_io_service().post(bind_handler(handler,
1167
 
            asio::error::bad_descriptor, 0));
1168
 
    }
1169
 
    else
1170
 
    {
1171
 
      // Check if the reactor was already obtained from the io_service.
1172
 
      reactor_type* reactor = static_cast<reactor_type*>(
1173
 
            interlocked_compare_exchange_pointer(
1174
 
              reinterpret_cast<void**>(&reactor_), 0, 0));
1175
 
      if (!reactor)
1176
 
      {
1177
 
        reactor = &(asio::use_service<reactor_type>(
1178
 
              this->get_io_service()));
1179
 
        interlocked_exchange_pointer(
1180
 
            reinterpret_cast<void**>(&reactor_), reactor);
1181
 
      }
1182
 
 
1183
 
      reactor->start_write_op(impl.socket_, impl.reactor_data_,
1184
 
          null_buffers_operation<Handler>(this->get_io_service(), handler),
1185
 
          false);
1186
 
    }
1187
 
  }
1188
 
 
1189
 
  // Receive some data from the peer. Returns the number of bytes received.
1190
 
  template <typename MutableBufferSequence>
1191
 
  size_t receive(implementation_type& impl,
1192
 
      const MutableBufferSequence& buffers,
1193
 
      socket_base::message_flags flags, asio::error_code& ec)
1194
 
  {
1195
 
    if (!is_open(impl))
1196
 
    {
1197
 
      ec = asio::error::bad_descriptor;
1198
 
      return 0;
1199
 
    }
1200
 
 
1201
 
    // Copy buffers into WSABUF array.
1202
 
    ::WSABUF bufs[max_buffers];
1203
 
    typename MutableBufferSequence::const_iterator iter = buffers.begin();
1204
 
    typename MutableBufferSequence::const_iterator end = buffers.end();
1205
 
    DWORD i = 0;
1206
 
    size_t total_buffer_size = 0;
1207
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
1208
 
    {
1209
 
      asio::mutable_buffer buffer(*iter);
1210
 
      bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
1211
 
      bufs[i].buf = asio::buffer_cast<char*>(buffer);
1212
 
      total_buffer_size += asio::buffer_size(buffer);
1213
 
    }
1214
 
 
1215
 
    // A request to receive 0 bytes on a stream socket is a no-op.
1216
 
    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
1217
 
    {
1218
 
      ec = asio::error_code();
1219
 
      return 0;
1220
 
    }
1221
 
 
1222
 
    // Receive some data.
1223
 
    DWORD bytes_transferred = 0;
1224
 
    DWORD recv_flags = flags;
1225
 
    int result = ::WSARecv(impl.socket_, bufs, i,
1226
 
        &bytes_transferred, &recv_flags, 0, 0);
1227
 
    if (result != 0)
1228
 
    {
1229
 
      DWORD last_error = ::WSAGetLastError();
1230
 
      if (last_error == ERROR_NETNAME_DELETED)
1231
 
        last_error = WSAECONNRESET;
1232
 
      else if (last_error == ERROR_PORT_UNREACHABLE)
1233
 
        last_error = WSAECONNREFUSED;
1234
 
      ec = asio::error_code(last_error,
1235
 
          asio::error::get_system_category());
1236
 
      return 0;
1237
 
    }
1238
 
    if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)
1239
 
    {
1240
 
      ec = asio::error::eof;
1241
 
      return 0;
1242
 
    }
1243
 
 
1244
 
    ec = asio::error_code();
1245
 
    return bytes_transferred;
1246
 
  }
1247
 
 
1248
 
  // Wait until data can be received without blocking.
1249
 
  size_t receive(implementation_type& impl, const null_buffers&,
1250
 
      socket_base::message_flags, asio::error_code& ec)
1251
 
  {
1252
 
    if (!is_open(impl))
1253
 
    {
1254
 
      ec = asio::error::bad_descriptor;
1255
 
      return 0;
1256
 
    }
1257
 
 
1258
 
    // Wait for socket to become ready.
1259
 
    socket_ops::poll_read(impl.socket_, ec);
1260
 
 
1261
 
    return 0;
1262
 
  }
1263
 
 
1264
 
  template <typename MutableBufferSequence, typename Handler>
1265
 
  class receive_operation
1266
 
    : public operation
1267
 
  {
1268
 
  public:
1269
 
    receive_operation(int protocol_type, win_iocp_io_service& io_service,
1270
 
        weak_cancel_token_type cancel_token,
1271
 
        const MutableBufferSequence& buffers, Handler handler)
1272
 
      : operation(io_service,
1273
 
          &receive_operation<
1274
 
            MutableBufferSequence, Handler>::do_completion_impl,
1275
 
          &receive_operation<
1276
 
            MutableBufferSequence, Handler>::destroy_impl),
1277
 
        protocol_type_(protocol_type),
1278
 
        work_(io_service.get_io_service()),
1279
 
        cancel_token_(cancel_token),
1280
 
        buffers_(buffers),
1281
 
        handler_(handler)
1282
 
    {
1283
 
    }
1284
 
 
1285
 
  private:
1286
 
    static void do_completion_impl(operation* op,
1287
 
        DWORD last_error, size_t bytes_transferred)
1288
 
    {
1289
 
      // Take ownership of the operation object.
1290
 
      typedef receive_operation<MutableBufferSequence, Handler> op_type;
1291
 
      op_type* handler_op(static_cast<op_type*>(op));
1292
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
1293
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
1294
 
 
1295
 
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1296
 
      // Check whether buffers are still valid.
1297
 
      typename MutableBufferSequence::const_iterator iter
1298
 
        = handler_op->buffers_.begin();
1299
 
      typename MutableBufferSequence::const_iterator end
1300
 
        = handler_op->buffers_.end();
1301
 
      while (iter != end)
1302
 
      {
1303
 
        asio::mutable_buffer buffer(*iter);
1304
 
        asio::buffer_cast<char*>(buffer);
1305
 
        ++iter;
1306
 
      }
1307
 
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1308
 
 
1309
 
      // Map non-portable errors to their portable counterparts.
1310
 
      asio::error_code ec(last_error,
1311
 
          asio::error::get_system_category());
1312
 
      if (ec.value() == ERROR_NETNAME_DELETED)
1313
 
      {
1314
 
        if (handler_op->cancel_token_.expired())
1315
 
          ec = asio::error::operation_aborted;
1316
 
        else
1317
 
          ec = asio::error::connection_reset;
1318
 
      }
1319
 
      else if (ec.value() == ERROR_PORT_UNREACHABLE)
1320
 
      {
1321
 
        ec = asio::error::connection_refused;
1322
 
      }
1323
 
 
1324
 
      // Check for connection closed.
1325
 
      else if (!ec && bytes_transferred == 0
1326
 
          && handler_op->protocol_type_ == SOCK_STREAM
1327
 
          && !boost::is_same<MutableBufferSequence, null_buffers>::value)
1328
 
      {
1329
 
        ec = asio::error::eof;
1330
 
      }
1331
 
 
1332
 
      // Make a copy of the handler so that the memory can be deallocated before
1333
 
      // the upcall is made.
1334
 
      Handler handler(handler_op->handler_);
1335
 
 
1336
 
      // Free the memory associated with the handler.
1337
 
      ptr.reset();
1338
 
 
1339
 
      // Call the handler.
1340
 
      asio_handler_invoke_helpers::invoke(
1341
 
          detail::bind_handler(handler, ec, bytes_transferred), &handler);
1342
 
    }
1343
 
 
1344
 
    static void destroy_impl(operation* op)
1345
 
    {
1346
 
      // Take ownership of the operation object.
1347
 
      typedef receive_operation<MutableBufferSequence, Handler> op_type;
1348
 
      op_type* handler_op(static_cast<op_type*>(op));
1349
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
1350
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
1351
 
 
1352
 
      // A sub-object of the handler may be the true owner of the memory
1353
 
      // associated with the handler. Consequently, a local copy of the handler
1354
 
      // is required to ensure that any owning sub-object remains valid until
1355
 
      // after we have deallocated the memory here.
1356
 
      Handler handler(handler_op->handler_);
1357
 
      (void)handler;
1358
 
 
1359
 
      // Free the memory associated with the handler.
1360
 
      ptr.reset();
1361
 
    }
1362
 
 
1363
 
    int protocol_type_;
1364
 
    asio::io_service::work work_;
1365
 
    weak_cancel_token_type cancel_token_;
1366
 
    MutableBufferSequence buffers_;
1367
 
    Handler handler_;
1368
 
  };
1369
 
 
1370
 
  // Start an asynchronous receive. The buffer for the data being received
1371
 
  // must be valid for the lifetime of the asynchronous operation.
1372
 
  template <typename MutableBufferSequence, typename Handler>
1373
 
  void async_receive(implementation_type& impl,
1374
 
      const MutableBufferSequence& buffers,
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
 
      return;
1382
 
    }
1383
 
 
1384
 
#if defined(ASIO_ENABLE_CANCELIO)
1385
 
    // Update the ID of the thread from which cancellation is safe.
1386
 
    if (impl.safe_cancellation_thread_id_ == 0)
1387
 
      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
1388
 
    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
1389
 
      impl.safe_cancellation_thread_id_ = ~DWORD(0);
1390
 
#endif // defined(ASIO_ENABLE_CANCELIO)
1391
 
 
1392
 
    // Allocate and construct an operation to wrap the handler.
1393
 
    typedef receive_operation<MutableBufferSequence, Handler> value_type;
1394
 
    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
1395
 
    raw_handler_ptr<alloc_traits> raw_ptr(handler);
1396
 
    int protocol_type = impl.protocol_.type();
1397
 
    handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
1398
 
        iocp_service_, impl.cancel_token_, buffers, handler);
1399
 
 
1400
 
    // Copy buffers into WSABUF array.
1401
 
    ::WSABUF bufs[max_buffers];
1402
 
    typename MutableBufferSequence::const_iterator iter = buffers.begin();
1403
 
    typename MutableBufferSequence::const_iterator end = buffers.end();
1404
 
    DWORD i = 0;
1405
 
    size_t total_buffer_size = 0;
1406
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
1407
 
    {
1408
 
      asio::mutable_buffer buffer(*iter);
1409
 
      bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
1410
 
      bufs[i].buf = asio::buffer_cast<char*>(buffer);
1411
 
      total_buffer_size += asio::buffer_size(buffer);
1412
 
    }
1413
 
 
1414
 
    // A request to receive 0 bytes on a stream socket is a no-op.
1415
 
    if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
1416
 
    {
1417
 
      asio::io_service::work work(this->get_io_service());
1418
 
      ptr.reset();
1419
 
      asio::error_code error;
1420
 
      iocp_service_.post(bind_handler(handler, error, 0));
1421
 
      return;
1422
 
    }
1423
 
 
1424
 
    // Receive some data.
1425
 
    DWORD bytes_transferred = 0;
1426
 
    DWORD recv_flags = flags;
1427
 
    int result = ::WSARecv(impl.socket_, bufs, i,
1428
 
        &bytes_transferred, &recv_flags, ptr.get(), 0);
1429
 
    DWORD last_error = ::WSAGetLastError();
1430
 
    if (result != 0 && last_error != WSA_IO_PENDING)
1431
 
    {
1432
 
      asio::io_service::work work(this->get_io_service());
1433
 
      ptr.reset();
1434
 
      asio::error_code ec(last_error,
1435
 
          asio::error::get_system_category());
1436
 
      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
1437
 
    }
1438
 
    else
1439
 
    {
1440
 
      ptr.release();
1441
 
    }
1442
 
  }
1443
 
 
1444
 
  // Wait until data can be received without blocking.
1445
 
  template <typename Handler>
1446
 
  void async_receive(implementation_type& impl, const null_buffers& buffers,
1447
 
      socket_base::message_flags flags, Handler handler)
1448
 
  {
1449
 
    if (!is_open(impl))
1450
 
    {
1451
 
      this->get_io_service().post(bind_handler(handler,
1452
 
            asio::error::bad_descriptor, 0));
1453
 
    }
1454
 
    else if (impl.protocol_.type() == SOCK_STREAM)
1455
 
    {
1456
 
      // For stream sockets on Windows, we may issue a 0-byte overlapped
1457
 
      // WSARecv to wait until there is data available on the socket.
1458
 
 
1459
 
#if defined(ASIO_ENABLE_CANCELIO)
1460
 
      // Update the ID of the thread from which cancellation is safe.
1461
 
      if (impl.safe_cancellation_thread_id_ == 0)
1462
 
        impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
1463
 
      else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
1464
 
        impl.safe_cancellation_thread_id_ = ~DWORD(0);
1465
 
#endif // defined(ASIO_ENABLE_CANCELIO)
1466
 
 
1467
 
      // Allocate and construct an operation to wrap the handler.
1468
 
      typedef receive_operation<null_buffers, Handler> value_type;
1469
 
      typedef handler_alloc_traits<Handler, value_type> alloc_traits;
1470
 
      raw_handler_ptr<alloc_traits> raw_ptr(handler);
1471
 
      int protocol_type = impl.protocol_.type();
1472
 
      handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
1473
 
          iocp_service_, impl.cancel_token_, buffers, handler);
1474
 
 
1475
 
      // Issue a receive operation with an empty buffer.
1476
 
      ::WSABUF buf = { 0, 0 };
1477
 
      DWORD bytes_transferred = 0;
1478
 
      DWORD recv_flags = flags;
1479
 
      int result = ::WSARecv(impl.socket_, &buf, 1,
1480
 
          &bytes_transferred, &recv_flags, ptr.get(), 0);
1481
 
      DWORD last_error = ::WSAGetLastError();
1482
 
      if (result != 0 && last_error != WSA_IO_PENDING)
1483
 
      {
1484
 
        asio::io_service::work work(this->get_io_service());
1485
 
        ptr.reset();
1486
 
        asio::error_code ec(last_error,
1487
 
            asio::error::get_system_category());
1488
 
        iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
1489
 
      }
1490
 
      else
1491
 
      {
1492
 
        ptr.release();
1493
 
      }
1494
 
    }
1495
 
    else
1496
 
    {
1497
 
      // Check if the reactor was already obtained from the io_service.
1498
 
      reactor_type* reactor = static_cast<reactor_type*>(
1499
 
            interlocked_compare_exchange_pointer(
1500
 
              reinterpret_cast<void**>(&reactor_), 0, 0));
1501
 
      if (!reactor)
1502
 
      {
1503
 
        reactor = &(asio::use_service<reactor_type>(
1504
 
              this->get_io_service()));
1505
 
        interlocked_exchange_pointer(
1506
 
            reinterpret_cast<void**>(&reactor_), reactor);
1507
 
      }
1508
 
 
1509
 
      if (flags & socket_base::message_out_of_band)
1510
 
      {
1511
 
        reactor->start_except_op(impl.socket_, impl.reactor_data_,
1512
 
            null_buffers_operation<Handler>(this->get_io_service(), handler));
1513
 
      }
1514
 
      else
1515
 
      {
1516
 
        reactor->start_read_op(impl.socket_, impl.reactor_data_,
1517
 
            null_buffers_operation<Handler>(this->get_io_service(), handler),
1518
 
            false);
1519
 
      }
1520
 
    }
1521
 
  }
1522
 
 
1523
 
  // Receive a datagram with the endpoint of the sender. Returns the number of
1524
 
  // bytes received.
1525
 
  template <typename MutableBufferSequence>
1526
 
  size_t receive_from(implementation_type& impl,
1527
 
      const MutableBufferSequence& buffers,
1528
 
      endpoint_type& sender_endpoint, socket_base::message_flags flags,
1529
 
      asio::error_code& ec)
1530
 
  {
1531
 
    if (!is_open(impl))
1532
 
    {
1533
 
      ec = asio::error::bad_descriptor;
1534
 
      return 0;
1535
 
    }
1536
 
 
1537
 
    // Copy buffers into WSABUF array.
1538
 
    ::WSABUF bufs[max_buffers];
1539
 
    typename MutableBufferSequence::const_iterator iter = buffers.begin();
1540
 
    typename MutableBufferSequence::const_iterator end = buffers.end();
1541
 
    DWORD i = 0;
1542
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
1543
 
    {
1544
 
      asio::mutable_buffer buffer(*iter);
1545
 
      bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
1546
 
      bufs[i].buf = asio::buffer_cast<char*>(buffer);
1547
 
    }
1548
 
 
1549
 
    // Receive some data.
1550
 
    DWORD bytes_transferred = 0;
1551
 
    DWORD recv_flags = flags;
1552
 
    int endpoint_size = static_cast<int>(sender_endpoint.capacity());
1553
 
    int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
1554
 
        &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0);
1555
 
    if (result != 0)
1556
 
    {
1557
 
      DWORD last_error = ::WSAGetLastError();
1558
 
      if (last_error == ERROR_PORT_UNREACHABLE)
1559
 
        last_error = WSAECONNREFUSED;
1560
 
      ec = asio::error_code(last_error,
1561
 
          asio::error::get_system_category());
1562
 
      return 0;
1563
 
    }
1564
 
    if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)
1565
 
    {
1566
 
      ec = asio::error::eof;
1567
 
      return 0;
1568
 
    }
1569
 
 
1570
 
    sender_endpoint.resize(static_cast<std::size_t>(endpoint_size));
1571
 
 
1572
 
    ec = asio::error_code();
1573
 
    return bytes_transferred;
1574
 
  }
1575
 
 
1576
 
  // Wait until data can be received without blocking.
1577
 
  size_t receive_from(implementation_type& impl,
1578
 
      const null_buffers&, endpoint_type& sender_endpoint,
1579
 
      socket_base::message_flags, asio::error_code& ec)
1580
 
  {
1581
 
    if (!is_open(impl))
1582
 
    {
1583
 
      ec = asio::error::bad_descriptor;
1584
 
      return 0;
1585
 
    }
1586
 
 
1587
 
    // Wait for socket to become ready.
1588
 
    socket_ops::poll_read(impl.socket_, ec);
1589
 
 
1590
 
    // Reset endpoint since it can be given no sensible value at this time.
1591
 
    sender_endpoint = endpoint_type();
1592
 
 
1593
 
    return 0;
1594
 
  }
1595
 
 
1596
 
  template <typename MutableBufferSequence, typename Handler>
1597
 
  class receive_from_operation
1598
 
    : public operation
1599
 
  {
1600
 
  public:
1601
 
    receive_from_operation(int protocol_type, win_iocp_io_service& io_service,
1602
 
        endpoint_type& endpoint, const MutableBufferSequence& buffers,
1603
 
        Handler handler)
1604
 
      : operation(io_service,
1605
 
          &receive_from_operation<
1606
 
            MutableBufferSequence, Handler>::do_completion_impl,
1607
 
          &receive_from_operation<
1608
 
            MutableBufferSequence, Handler>::destroy_impl),
1609
 
        protocol_type_(protocol_type),
1610
 
        endpoint_(endpoint),
1611
 
        endpoint_size_(static_cast<int>(endpoint.capacity())),
1612
 
        work_(io_service.get_io_service()),
1613
 
        buffers_(buffers),
1614
 
        handler_(handler)
1615
 
    {
1616
 
    }
1617
 
 
1618
 
    int& endpoint_size()
1619
 
    {
1620
 
      return endpoint_size_;
1621
 
    }
1622
 
 
1623
 
  private:
1624
 
    static void do_completion_impl(operation* op,
1625
 
        DWORD last_error, size_t bytes_transferred)
1626
 
    {
1627
 
      // Take ownership of the operation object.
1628
 
      typedef receive_from_operation<MutableBufferSequence, Handler> op_type;
1629
 
      op_type* handler_op(static_cast<op_type*>(op));
1630
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
1631
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
1632
 
 
1633
 
#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1634
 
      // Check whether buffers are still valid.
1635
 
      typename MutableBufferSequence::const_iterator iter
1636
 
        = handler_op->buffers_.begin();
1637
 
      typename MutableBufferSequence::const_iterator end
1638
 
        = handler_op->buffers_.end();
1639
 
      while (iter != end)
1640
 
      {
1641
 
        asio::mutable_buffer buffer(*iter);
1642
 
        asio::buffer_cast<char*>(buffer);
1643
 
        ++iter;
1644
 
      }
1645
 
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
1646
 
 
1647
 
      // Map non-portable errors to their portable counterparts.
1648
 
      asio::error_code ec(last_error,
1649
 
          asio::error::get_system_category());
1650
 
      if (ec.value() == ERROR_PORT_UNREACHABLE)
1651
 
      {
1652
 
        ec = asio::error::connection_refused;
1653
 
      }
1654
 
 
1655
 
      // Check for connection closed.
1656
 
      if (!ec && bytes_transferred == 0
1657
 
          && handler_op->protocol_type_ == SOCK_STREAM)
1658
 
      {
1659
 
        ec = asio::error::eof;
1660
 
      }
1661
 
 
1662
 
      // Record the size of the endpoint returned by the operation.
1663
 
      handler_op->endpoint_.resize(handler_op->endpoint_size_);
1664
 
 
1665
 
      // Make a copy of the handler so that the memory can be deallocated before
1666
 
      // the upcall is made.
1667
 
      Handler handler(handler_op->handler_);
1668
 
 
1669
 
      // Free the memory associated with the handler.
1670
 
      ptr.reset();
1671
 
 
1672
 
      // Call the handler.
1673
 
      asio_handler_invoke_helpers::invoke(
1674
 
          detail::bind_handler(handler, ec, bytes_transferred), &handler);
1675
 
    }
1676
 
 
1677
 
    static void destroy_impl(operation* op)
1678
 
    {
1679
 
      // Take ownership of the operation object.
1680
 
      typedef receive_from_operation<MutableBufferSequence, Handler> op_type;
1681
 
      op_type* handler_op(static_cast<op_type*>(op));
1682
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
1683
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
1684
 
 
1685
 
      // A sub-object of the handler may be the true owner of the memory
1686
 
      // associated with the handler. Consequently, a local copy of the handler
1687
 
      // is required to ensure that any owning sub-object remains valid until
1688
 
      // after we have deallocated the memory here.
1689
 
      Handler handler(handler_op->handler_);
1690
 
      (void)handler;
1691
 
 
1692
 
      // Free the memory associated with the handler.
1693
 
      ptr.reset();
1694
 
    }
1695
 
 
1696
 
    int protocol_type_;
1697
 
    endpoint_type& endpoint_;
1698
 
    int endpoint_size_;
1699
 
    asio::io_service::work work_;
1700
 
    MutableBufferSequence buffers_;
1701
 
    Handler handler_;
1702
 
  };
1703
 
 
1704
 
  // Start an asynchronous receive. The buffer for the data being received and
1705
 
  // the sender_endpoint object must both be valid for the lifetime of the
1706
 
  // asynchronous operation.
1707
 
  template <typename MutableBufferSequence, typename Handler>
1708
 
  void async_receive_from(implementation_type& impl,
1709
 
      const MutableBufferSequence& buffers, endpoint_type& sender_endp,
1710
 
      socket_base::message_flags flags, Handler handler)
1711
 
  {
1712
 
    if (!is_open(impl))
1713
 
    {
1714
 
      this->get_io_service().post(bind_handler(handler,
1715
 
            asio::error::bad_descriptor, 0));
1716
 
      return;
1717
 
    }
1718
 
 
1719
 
#if defined(ASIO_ENABLE_CANCELIO)
1720
 
    // Update the ID of the thread from which cancellation is safe.
1721
 
    if (impl.safe_cancellation_thread_id_ == 0)
1722
 
      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
1723
 
    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
1724
 
      impl.safe_cancellation_thread_id_ = ~DWORD(0);
1725
 
#endif // defined(ASIO_ENABLE_CANCELIO)
1726
 
 
1727
 
    // Allocate and construct an operation to wrap the handler.
1728
 
    typedef receive_from_operation<MutableBufferSequence, Handler> value_type;
1729
 
    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
1730
 
    raw_handler_ptr<alloc_traits> raw_ptr(handler);
1731
 
    int protocol_type = impl.protocol_.type();
1732
 
    handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
1733
 
        iocp_service_, sender_endp, buffers, handler);
1734
 
 
1735
 
    // Copy buffers into WSABUF array.
1736
 
    ::WSABUF bufs[max_buffers];
1737
 
    typename MutableBufferSequence::const_iterator iter = buffers.begin();
1738
 
    typename MutableBufferSequence::const_iterator end = buffers.end();
1739
 
    DWORD i = 0;
1740
 
    for (; iter != end && i < max_buffers; ++iter, ++i)
1741
 
    {
1742
 
      asio::mutable_buffer buffer(*iter);
1743
 
      bufs[i].len = static_cast<u_long>(asio::buffer_size(buffer));
1744
 
      bufs[i].buf = asio::buffer_cast<char*>(buffer);
1745
 
    }
1746
 
 
1747
 
    // Receive some data.
1748
 
    DWORD bytes_transferred = 0;
1749
 
    DWORD recv_flags = flags;
1750
 
    int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
1751
 
        &recv_flags, sender_endp.data(), &ptr.get()->endpoint_size(),
1752
 
        ptr.get(), 0);
1753
 
    DWORD last_error = ::WSAGetLastError();
1754
 
    if (result != 0 && last_error != WSA_IO_PENDING)
1755
 
    {
1756
 
      asio::io_service::work work(this->get_io_service());
1757
 
      ptr.reset();
1758
 
      asio::error_code ec(last_error,
1759
 
          asio::error::get_system_category());
1760
 
      iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
1761
 
    }
1762
 
    else
1763
 
    {
1764
 
      ptr.release();
1765
 
    }
1766
 
  }
1767
 
 
1768
 
  // Wait until data can be received without blocking.
1769
 
  template <typename Handler>
1770
 
  void async_receive_from(implementation_type& impl,
1771
 
      const null_buffers&, endpoint_type& sender_endpoint,
1772
 
      socket_base::message_flags flags, Handler handler)
1773
 
  {
1774
 
    if (!is_open(impl))
1775
 
    {
1776
 
      this->get_io_service().post(bind_handler(handler,
1777
 
            asio::error::bad_descriptor, 0));
1778
 
    }
1779
 
    else
1780
 
    {
1781
 
      // Check if the reactor was already obtained from the io_service.
1782
 
      reactor_type* reactor = static_cast<reactor_type*>(
1783
 
            interlocked_compare_exchange_pointer(
1784
 
              reinterpret_cast<void**>(&reactor_), 0, 0));
1785
 
      if (!reactor)
1786
 
      {
1787
 
        reactor = &(asio::use_service<reactor_type>(
1788
 
              this->get_io_service()));
1789
 
        interlocked_exchange_pointer(
1790
 
            reinterpret_cast<void**>(&reactor_), reactor);
1791
 
      }
1792
 
 
1793
 
      // Reset endpoint since it can be given no sensible value at this time.
1794
 
      sender_endpoint = endpoint_type();
1795
 
 
1796
 
      if (flags & socket_base::message_out_of_band)
1797
 
      {
1798
 
        reactor->start_except_op(impl.socket_, impl.reactor_data_,
1799
 
            null_buffers_operation<Handler>(this->get_io_service(), handler));
1800
 
      }
1801
 
      else
1802
 
      {
1803
 
        reactor->start_read_op(impl.socket_, impl.reactor_data_,
1804
 
            null_buffers_operation<Handler>(this->get_io_service(), handler),
1805
 
            false);
1806
 
      }
1807
 
    }
1808
 
  }
1809
 
 
1810
 
  // Accept a new connection.
1811
 
  template <typename Socket>
1812
 
  asio::error_code accept(implementation_type& impl, Socket& peer,
1813
 
      endpoint_type* peer_endpoint, asio::error_code& ec)
1814
 
  {
1815
 
    if (!is_open(impl))
1816
 
    {
1817
 
      ec = asio::error::bad_descriptor;
1818
 
      return ec;
1819
 
    }
1820
 
 
1821
 
    // We cannot accept a socket that is already open.
1822
 
    if (peer.is_open())
1823
 
    {
1824
 
      ec = asio::error::already_open;
1825
 
      return ec;
1826
 
    }
1827
 
 
1828
 
    for (;;)
1829
 
    {
1830
 
      socket_holder new_socket;
1831
 
      std::size_t addr_len = 0;
1832
 
      if (peer_endpoint)
1833
 
      {
1834
 
        addr_len = peer_endpoint->capacity();
1835
 
        new_socket.reset(socket_ops::accept(impl.socket_,
1836
 
              peer_endpoint->data(), &addr_len, ec));
1837
 
      }
1838
 
      else
1839
 
      {
1840
 
        new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
1841
 
      }
1842
 
 
1843
 
      if (ec)
1844
 
      {
1845
 
        if (ec == asio::error::connection_aborted
1846
 
            && !(impl.flags_ & implementation_type::enable_connection_aborted))
1847
 
        {
1848
 
          // Retry accept operation.
1849
 
          continue;
1850
 
        }
1851
 
        else
1852
 
        {
1853
 
          return ec;
1854
 
        }
1855
 
      }
1856
 
 
1857
 
      if (peer_endpoint)
1858
 
        peer_endpoint->resize(addr_len);
1859
 
 
1860
 
      peer.assign(impl.protocol_, new_socket.get(), ec);
1861
 
      if (!ec)
1862
 
        new_socket.release();
1863
 
      return ec;
1864
 
    }
1865
 
  }
1866
 
 
1867
 
  template <typename Socket, typename Handler>
1868
 
  class accept_operation
1869
 
    : public operation
1870
 
  {
1871
 
  public:
1872
 
    accept_operation(win_iocp_io_service& io_service,
1873
 
        socket_type socket, socket_type new_socket, Socket& peer,
1874
 
        const protocol_type& protocol, endpoint_type* peer_endpoint,
1875
 
        bool enable_connection_aborted, Handler handler)
1876
 
      : operation(io_service,
1877
 
          &accept_operation<Socket, Handler>::do_completion_impl,
1878
 
          &accept_operation<Socket, Handler>::destroy_impl),
1879
 
        io_service_(io_service),
1880
 
        socket_(socket),
1881
 
        new_socket_(new_socket),
1882
 
        peer_(peer),
1883
 
        protocol_(protocol),
1884
 
        peer_endpoint_(peer_endpoint),
1885
 
        work_(io_service.get_io_service()),
1886
 
        enable_connection_aborted_(enable_connection_aborted),
1887
 
        handler_(handler)
1888
 
    {
1889
 
    }
1890
 
 
1891
 
    socket_type new_socket()
1892
 
    {
1893
 
      return new_socket_.get();
1894
 
    }
1895
 
 
1896
 
    void* output_buffer()
1897
 
    {
1898
 
      return output_buffer_;
1899
 
    }
1900
 
 
1901
 
    DWORD address_length()
1902
 
    {
1903
 
      return sizeof(sockaddr_storage_type) + 16;
1904
 
    }
1905
 
 
1906
 
  private:
1907
 
    static void do_completion_impl(operation* op, DWORD last_error, size_t)
1908
 
    {
1909
 
      // Take ownership of the operation object.
1910
 
      typedef accept_operation<Socket, Handler> op_type;
1911
 
      op_type* handler_op(static_cast<op_type*>(op));
1912
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
1913
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
1914
 
 
1915
 
      // Map Windows error ERROR_NETNAME_DELETED to connection_aborted.
1916
 
      if (last_error == ERROR_NETNAME_DELETED)
1917
 
      {
1918
 
        last_error = WSAECONNABORTED;
1919
 
      }
1920
 
 
1921
 
      // Restart the accept operation if we got the connection_aborted error
1922
 
      // and the enable_connection_aborted socket option is not set.
1923
 
      if (last_error == WSAECONNABORTED
1924
 
          && !ptr.get()->enable_connection_aborted_)
1925
 
      {
1926
 
        // Reset OVERLAPPED structure.
1927
 
        ptr.get()->Internal = 0;
1928
 
        ptr.get()->InternalHigh = 0;
1929
 
        ptr.get()->Offset = 0;
1930
 
        ptr.get()->OffsetHigh = 0;
1931
 
        ptr.get()->hEvent = 0;
1932
 
 
1933
 
        // Create a new socket for the next connection, since the AcceptEx call
1934
 
        // fails with WSAEINVAL if we try to reuse the same socket.
1935
 
        asio::error_code ec;
1936
 
        ptr.get()->new_socket_.reset();
1937
 
        ptr.get()->new_socket_.reset(socket_ops::socket(
1938
 
              ptr.get()->protocol_.family(), ptr.get()->protocol_.type(),
1939
 
              ptr.get()->protocol_.protocol(), ec));
1940
 
        if (ptr.get()->new_socket() != invalid_socket)
1941
 
        {
1942
 
          // Accept a connection.
1943
 
          DWORD bytes_read = 0;
1944
 
          BOOL result = ::AcceptEx(ptr.get()->socket_, ptr.get()->new_socket(),
1945
 
              ptr.get()->output_buffer(), 0, ptr.get()->address_length(),
1946
 
              ptr.get()->address_length(), &bytes_read, ptr.get());
1947
 
          last_error = ::WSAGetLastError();
1948
 
 
1949
 
          // Check if the operation completed immediately.
1950
 
          if (!result && last_error != WSA_IO_PENDING)
1951
 
          {
1952
 
            if (last_error == ERROR_NETNAME_DELETED
1953
 
                || last_error == WSAECONNABORTED)
1954
 
            {
1955
 
              // Post this handler so that operation will be restarted again.
1956
 
              ptr.get()->io_service_.post_completion(ptr.get(), last_error, 0);
1957
 
              ptr.release();
1958
 
              return;
1959
 
            }
1960
 
            else
1961
 
            {
1962
 
              // Operation already complete. Continue with rest of this handler.
1963
 
            }
1964
 
          }
1965
 
          else
1966
 
          {
1967
 
            // Asynchronous operation has been successfully restarted.
1968
 
            ptr.release();
1969
 
            return;
1970
 
          }
1971
 
        }
1972
 
      }
1973
 
 
1974
 
      // Get the address of the peer.
1975
 
      endpoint_type peer_endpoint;
1976
 
      if (last_error == 0)
1977
 
      {
1978
 
        LPSOCKADDR local_addr = 0;
1979
 
        int local_addr_length = 0;
1980
 
        LPSOCKADDR remote_addr = 0;
1981
 
        int remote_addr_length = 0;
1982
 
        GetAcceptExSockaddrs(handler_op->output_buffer(), 0,
1983
 
            handler_op->address_length(), handler_op->address_length(),
1984
 
            &local_addr, &local_addr_length, &remote_addr, &remote_addr_length);
1985
 
        if (static_cast<std::size_t>(remote_addr_length)
1986
 
            > peer_endpoint.capacity())
1987
 
        {
1988
 
          last_error = WSAEINVAL;
1989
 
        }
1990
 
        else
1991
 
        {
1992
 
          using namespace std; // For memcpy.
1993
 
          memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
1994
 
          peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));
1995
 
        }
1996
 
      }
1997
 
 
1998
 
      // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
1999
 
      // and getpeername will work on the accepted socket.
2000
 
      if (last_error == 0)
2001
 
      {
2002
 
        SOCKET update_ctx_param = handler_op->socket_;
2003
 
        asio::error_code ec;
2004
 
        if (socket_ops::setsockopt(handler_op->new_socket_.get(),
2005
 
              SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
2006
 
              &update_ctx_param, sizeof(SOCKET), ec) != 0)
2007
 
        {
2008
 
          last_error = ec.value();
2009
 
        }
2010
 
      }
2011
 
 
2012
 
      // If the socket was successfully accepted, transfer ownership of the
2013
 
      // socket to the peer object.
2014
 
      if (last_error == 0)
2015
 
      {
2016
 
        asio::error_code ec;
2017
 
        handler_op->peer_.assign(handler_op->protocol_,
2018
 
            native_type(handler_op->new_socket_.get(), peer_endpoint), ec);
2019
 
        if (ec)
2020
 
          last_error = ec.value();
2021
 
        else
2022
 
          handler_op->new_socket_.release();
2023
 
      }
2024
 
 
2025
 
      // Pass endpoint back to caller.
2026
 
      if (handler_op->peer_endpoint_)
2027
 
        *handler_op->peer_endpoint_ = peer_endpoint;
2028
 
 
2029
 
      // Make a copy of the handler so that the memory can be deallocated before
2030
 
      // the upcall is made.
2031
 
      Handler handler(handler_op->handler_);
2032
 
 
2033
 
      // Free the memory associated with the handler.
2034
 
      ptr.reset();
2035
 
 
2036
 
      // Call the handler.
2037
 
      asio::error_code ec(last_error,
2038
 
          asio::error::get_system_category());
2039
 
      asio_handler_invoke_helpers::invoke(
2040
 
          detail::bind_handler(handler, ec), &handler);
2041
 
    }
2042
 
 
2043
 
    static void destroy_impl(operation* op)
2044
 
    {
2045
 
      // Take ownership of the operation object.
2046
 
      typedef accept_operation<Socket, Handler> op_type;
2047
 
      op_type* handler_op(static_cast<op_type*>(op));
2048
 
      typedef handler_alloc_traits<Handler, op_type> alloc_traits;
2049
 
      handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
2050
 
 
2051
 
      // A sub-object of the handler may be the true owner of the memory
2052
 
      // associated with the handler. Consequently, a local copy of the handler
2053
 
      // is required to ensure that any owning sub-object remains valid until
2054
 
      // after we have deallocated the memory here.
2055
 
      Handler handler(handler_op->handler_);
2056
 
      (void)handler;
2057
 
 
2058
 
      // Free the memory associated with the handler.
2059
 
      ptr.reset();
2060
 
    }
2061
 
 
2062
 
    win_iocp_io_service& io_service_;
2063
 
    socket_type socket_;
2064
 
    socket_holder new_socket_;
2065
 
    Socket& peer_;
2066
 
    protocol_type protocol_;
2067
 
    endpoint_type* peer_endpoint_;
2068
 
    asio::io_service::work work_;
2069
 
    unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
2070
 
    bool enable_connection_aborted_;
2071
 
    Handler handler_;
2072
 
  };
2073
 
 
2074
 
  // Start an asynchronous accept. The peer and peer_endpoint objects
2075
 
  // must be valid until the accept's handler is invoked.
2076
 
  template <typename Socket, typename Handler>
2077
 
  void async_accept(implementation_type& impl, Socket& peer,
2078
 
      endpoint_type* peer_endpoint, Handler handler)
2079
 
  {
2080
 
    // Check whether acceptor has been initialised.
2081
 
    if (!is_open(impl))
2082
 
    {
2083
 
      this->get_io_service().post(bind_handler(handler,
2084
 
            asio::error::bad_descriptor));
2085
 
      return;
2086
 
    }
2087
 
 
2088
 
    // Check that peer socket has not already been opened.
2089
 
    if (peer.is_open())
2090
 
    {
2091
 
      this->get_io_service().post(bind_handler(handler,
2092
 
            asio::error::already_open));
2093
 
      return;
2094
 
    }
2095
 
 
2096
 
#if defined(ASIO_ENABLE_CANCELIO)
2097
 
    // Update the ID of the thread from which cancellation is safe.
2098
 
    if (impl.safe_cancellation_thread_id_ == 0)
2099
 
      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
2100
 
    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
2101
 
      impl.safe_cancellation_thread_id_ = ~DWORD(0);
2102
 
#endif // defined(ASIO_ENABLE_CANCELIO)
2103
 
 
2104
 
    // Create a new socket for the connection.
2105
 
    asio::error_code ec;
2106
 
    socket_holder sock(socket_ops::socket(impl.protocol_.family(),
2107
 
          impl.protocol_.type(), impl.protocol_.protocol(), ec));
2108
 
    if (sock.get() == invalid_socket)
2109
 
    {
2110
 
      this->get_io_service().post(bind_handler(handler, ec));
2111
 
      return;
2112
 
    }
2113
 
 
2114
 
    // Allocate and construct an operation to wrap the handler.
2115
 
    typedef accept_operation<Socket, Handler> value_type;
2116
 
    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
2117
 
    raw_handler_ptr<alloc_traits> raw_ptr(handler);
2118
 
    socket_type new_socket = sock.get();
2119
 
    bool enable_connection_aborted =
2120
 
      (impl.flags_ & implementation_type::enable_connection_aborted);
2121
 
    handler_ptr<alloc_traits> ptr(raw_ptr,
2122
 
        iocp_service_, impl.socket_, new_socket, peer, impl.protocol_,
2123
 
        peer_endpoint, enable_connection_aborted, handler);
2124
 
    sock.release();
2125
 
 
2126
 
    // Accept a connection.
2127
 
    DWORD bytes_read = 0;
2128
 
    BOOL result = ::AcceptEx(impl.socket_, ptr.get()->new_socket(),
2129
 
        ptr.get()->output_buffer(), 0, ptr.get()->address_length(),
2130
 
        ptr.get()->address_length(), &bytes_read, ptr.get());
2131
 
    DWORD last_error = ::WSAGetLastError();
2132
 
 
2133
 
    // Check if the operation completed immediately.
2134
 
    if (!result && last_error != WSA_IO_PENDING)
2135
 
    {
2136
 
      if (!enable_connection_aborted
2137
 
          && (last_error == ERROR_NETNAME_DELETED
2138
 
            || last_error == WSAECONNABORTED))
2139
 
      {
2140
 
        // Post handler so that operation will be restarted again. We do not
2141
 
        // perform the AcceptEx again here to avoid the possibility of starving
2142
 
        // other handlers.
2143
 
        iocp_service_.post_completion(ptr.get(), last_error, 0);
2144
 
        ptr.release();
2145
 
      }
2146
 
      else
2147
 
      {
2148
 
        asio::io_service::work work(this->get_io_service());
2149
 
        ptr.reset();
2150
 
        asio::error_code ec(last_error,
2151
 
            asio::error::get_system_category());
2152
 
        iocp_service_.post(bind_handler(handler, ec));
2153
 
      }
2154
 
    }
2155
 
    else
2156
 
    {
2157
 
      ptr.release();
2158
 
    }
2159
 
  }
2160
 
 
2161
 
  // Connect the socket to the specified endpoint.
2162
 
  asio::error_code connect(implementation_type& impl,
2163
 
      const endpoint_type& peer_endpoint, asio::error_code& ec)
2164
 
  {
2165
 
    if (!is_open(impl))
2166
 
    {
2167
 
      ec = asio::error::bad_descriptor;
2168
 
      return ec;
2169
 
    }
2170
 
 
2171
 
    // Perform the connect operation.
2172
 
    socket_ops::connect(impl.socket_,
2173
 
        peer_endpoint.data(), peer_endpoint.size(), ec);
2174
 
    return ec;
2175
 
  }
2176
 
 
2177
 
  template <typename Handler>
2178
 
  class connect_operation
2179
 
  {
2180
 
  public:
2181
 
    connect_operation(socket_type socket, bool user_set_non_blocking,
2182
 
        asio::io_service& io_service, Handler handler)
2183
 
      : socket_(socket),
2184
 
        user_set_non_blocking_(user_set_non_blocking),
2185
 
        io_service_(io_service),
2186
 
        work_(io_service),
2187
 
        handler_(handler)
2188
 
    {
2189
 
    }
2190
 
 
2191
 
    bool perform(asio::error_code& ec,
2192
 
        std::size_t& bytes_transferred)
2193
 
    {
2194
 
      // Check whether the operation was successful.
2195
 
      if (ec)
2196
 
        return true;
2197
 
 
2198
 
      // Get the error code from the connect operation.
2199
 
      int connect_error = 0;
2200
 
      size_t connect_error_len = sizeof(connect_error);
2201
 
      if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
2202
 
            &connect_error, &connect_error_len, ec) == socket_error_retval)
2203
 
        return true;
2204
 
 
2205
 
      // If connection failed then post the handler with the error code.
2206
 
      if (connect_error)
2207
 
      {
2208
 
        ec = asio::error_code(connect_error,
2209
 
            asio::error::get_system_category());
2210
 
        return true;
2211
 
      }
2212
 
 
2213
 
      // Revert socket to blocking mode unless the user requested otherwise.
2214
 
      if (!user_set_non_blocking_)
2215
 
      {
2216
 
        ioctl_arg_type non_blocking = 0;
2217
 
        if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec))
2218
 
          return true;
2219
 
      }
2220
 
 
2221
 
      // Post the result of the successful connection operation.
2222
 
      ec = asio::error_code();
2223
 
      return true;
2224
 
    }
2225
 
 
2226
 
    void complete(const asio::error_code& ec, std::size_t)
2227
 
    {
2228
 
      io_service_.post(bind_handler(handler_, ec));
2229
 
    }
2230
 
 
2231
 
  private:
2232
 
    socket_type socket_;
2233
 
    bool user_set_non_blocking_;
2234
 
    asio::io_service& io_service_;
2235
 
    asio::io_service::work work_;
2236
 
    Handler handler_;
2237
 
  };
2238
 
 
2239
 
  // Start an asynchronous connect.
2240
 
  template <typename Handler>
2241
 
  void async_connect(implementation_type& impl,
2242
 
      const endpoint_type& peer_endpoint, Handler handler)
2243
 
  {
2244
 
    if (!is_open(impl))
2245
 
    {
2246
 
      this->get_io_service().post(bind_handler(handler,
2247
 
            asio::error::bad_descriptor));
2248
 
      return;
2249
 
    }
2250
 
 
2251
 
#if defined(ASIO_ENABLE_CANCELIO)
2252
 
    // Update the ID of the thread from which cancellation is safe.
2253
 
    if (impl.safe_cancellation_thread_id_ == 0)
2254
 
      impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
2255
 
    else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
2256
 
      impl.safe_cancellation_thread_id_ = ~DWORD(0);
2257
 
#endif // defined(ASIO_ENABLE_CANCELIO)
2258
 
 
2259
 
    // Check if the reactor was already obtained from the io_service.
2260
 
    reactor_type* reactor = static_cast<reactor_type*>(
2261
 
          interlocked_compare_exchange_pointer(
2262
 
            reinterpret_cast<void**>(&reactor_), 0, 0));
2263
 
    if (!reactor)
2264
 
    {
2265
 
      reactor = &(asio::use_service<reactor_type>(
2266
 
            this->get_io_service()));
2267
 
      interlocked_exchange_pointer(
2268
 
          reinterpret_cast<void**>(&reactor_), reactor);
2269
 
    }
2270
 
 
2271
 
    // Mark the socket as non-blocking so that the connection will take place
2272
 
    // asynchronously.
2273
 
    ioctl_arg_type non_blocking = 1;
2274
 
    asio::error_code ec;
2275
 
    if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
2276
 
    {
2277
 
      this->get_io_service().post(bind_handler(handler, ec));
2278
 
      return;
2279
 
    }
2280
 
 
2281
 
    // Start the connect operation.
2282
 
    if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
2283
 
          peer_endpoint.size(), ec) == 0)
2284
 
    {
2285
 
      // Revert socket to blocking mode unless the user requested otherwise.
2286
 
      if (!(impl.flags_ & implementation_type::user_set_non_blocking))
2287
 
      {
2288
 
        non_blocking = 0;
2289
 
        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec);
2290
 
      }
2291
 
 
2292
 
      // The connect operation has finished successfully so we need to post the
2293
 
      // handler immediately.
2294
 
      this->get_io_service().post(bind_handler(handler, ec));
2295
 
    }
2296
 
    else if (ec == asio::error::in_progress
2297
 
        || ec == asio::error::would_block)
2298
 
    {
2299
 
      // The connection is happening in the background, and we need to wait
2300
 
      // until the socket becomes writeable.
2301
 
      boost::shared_ptr<bool> completed(new bool(false));
2302
 
      reactor->start_connect_op(impl.socket_, impl.reactor_data_,
2303
 
          connect_operation<Handler>(
2304
 
            impl.socket_,
2305
 
            (impl.flags_ & implementation_type::user_set_non_blocking) != 0,
2306
 
            this->get_io_service(), handler));
2307
 
    }
2308
 
    else
2309
 
    {
2310
 
      // Revert socket to blocking mode unless the user requested otherwise.
2311
 
      if (!(impl.flags_ & implementation_type::user_set_non_blocking))
2312
 
      {
2313
 
        non_blocking = 0;
2314
 
        asio::error_code ignored_ec;
2315
 
        socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
2316
 
      }
2317
 
 
2318
 
      // The connect operation has failed, so post the handler immediately.
2319
 
      this->get_io_service().post(bind_handler(handler, ec));
2320
 
    }
2321
 
  }
2322
 
 
2323
 
private:
2324
 
  // Helper function to close a socket when the associated object is being
2325
 
  // destroyed.
2326
 
  void close_for_destruction(implementation_type& impl)
2327
 
  {
2328
 
    if (is_open(impl))
2329
 
    {
2330
 
      // Check if the reactor was created, in which case we need to close the
2331
 
      // socket on the reactor as well to cancel any operations that might be
2332
 
      // running there.
2333
 
      reactor_type* reactor = static_cast<reactor_type*>(
2334
 
            interlocked_compare_exchange_pointer(
2335
 
              reinterpret_cast<void**>(&reactor_), 0, 0));
2336
 
      if (reactor)
2337
 
        reactor->close_descriptor(impl.socket_, impl.reactor_data_);
2338
 
 
2339
 
      // The socket destructor must not block. If the user has changed the
2340
 
      // linger option to block in the foreground, we will change it back to the
2341
 
      // default so that the closure is performed in the background.
2342
 
      if (impl.flags_ & implementation_type::close_might_block)
2343
 
      {
2344
 
        ::linger opt;
2345
 
        opt.l_onoff = 0;
2346
 
        opt.l_linger = 0;
2347
 
        asio::error_code ignored_ec;
2348
 
        socket_ops::setsockopt(impl.socket_,
2349
 
            SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
2350
 
      }
2351
 
 
2352
 
      asio::error_code ignored_ec;
2353
 
      socket_ops::close(impl.socket_, ignored_ec);
2354
 
      impl.socket_ = invalid_socket;
2355
 
      impl.flags_ = 0;
2356
 
      impl.cancel_token_.reset();
2357
 
#if defined(ASIO_ENABLE_CANCELIO)
2358
 
      impl.safe_cancellation_thread_id_ = 0;
2359
 
#endif // defined(ASIO_ENABLE_CANCELIO)
2360
 
    }
2361
 
  }
2362
 
 
2363
 
  // Helper function to emulate InterlockedCompareExchangePointer functionality
2364
 
  // for:
2365
 
  // - very old Platform SDKs; and
2366
 
  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
2367
 
  void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp)
2368
 
  {
2369
 
#if defined(_M_IX86)
2370
 
    return reinterpret_cast<void*>(InterlockedCompareExchange(
2371
 
          reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),
2372
 
          reinterpret_cast<LONG>(cmp)));
2373
 
#else
2374
 
    return InterlockedCompareExchangePointer(dest, exch, cmp);
2375
 
#endif
2376
 
  }
2377
 
 
2378
 
  // Helper function to emulate InterlockedExchangePointer functionality for:
2379
 
  // - very old Platform SDKs; and
2380
 
  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
2381
 
  void* interlocked_exchange_pointer(void** dest, void* val)
2382
 
  {
2383
 
#if defined(_M_IX86)
2384
 
    return reinterpret_cast<void*>(InterlockedExchange(
2385
 
          reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));
2386
 
#else
2387
 
    return InterlockedExchangePointer(dest, val);
2388
 
#endif
2389
 
  }
2390
 
 
2391
 
  // The IOCP service used for running asynchronous operations and dispatching
2392
 
  // handlers.
2393
 
  win_iocp_io_service& iocp_service_;
2394
 
 
2395
 
  // The reactor used for performing connect operations. This object is created
2396
 
  // only if needed.
2397
 
  reactor_type* reactor_;
2398
 
 
2399
 
  // Mutex to protect access to the linked list of implementations. 
2400
 
  asio::detail::mutex mutex_;
2401
 
 
2402
 
  // The head of a linked list of all implementations.
2403
 
  implementation_type* impl_list_;
2404
 
};
2405
 
 
2406
 
} // namespace detail
2407
 
} // namespace asio
2408
 
 
2409
 
#endif // defined(ASIO_HAS_IOCP)
2410
 
 
2411
 
#include "asio/detail/pop_options.hpp"
2412
 
 
2413
 
#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP