Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:46

0001 //
0002 // detail/win_iocp_socket_service.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
0012 #define BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if defined(BOOST_ASIO_HAS_IOCP)
0021 
0022 #include <cstring>
0023 #include <boost/asio/error.hpp>
0024 #include <boost/asio/execution_context.hpp>
0025 #include <boost/asio/socket_base.hpp>
0026 #include <boost/asio/detail/bind_handler.hpp>
0027 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0028 #include <boost/asio/detail/fenced_block.hpp>
0029 #include <boost/asio/detail/handler_alloc_helpers.hpp>
0030 #include <boost/asio/detail/memory.hpp>
0031 #include <boost/asio/detail/mutex.hpp>
0032 #include <boost/asio/detail/operation.hpp>
0033 #include <boost/asio/detail/reactor_op.hpp>
0034 #include <boost/asio/detail/select_reactor.hpp>
0035 #include <boost/asio/detail/socket_holder.hpp>
0036 #include <boost/asio/detail/socket_ops.hpp>
0037 #include <boost/asio/detail/socket_types.hpp>
0038 #include <boost/asio/detail/win_iocp_io_context.hpp>
0039 #include <boost/asio/detail/win_iocp_null_buffers_op.hpp>
0040 #include <boost/asio/detail/win_iocp_socket_accept_op.hpp>
0041 #include <boost/asio/detail/win_iocp_socket_connect_op.hpp>
0042 #include <boost/asio/detail/win_iocp_socket_recvfrom_op.hpp>
0043 #include <boost/asio/detail/win_iocp_socket_send_op.hpp>
0044 #include <boost/asio/detail/win_iocp_socket_service_base.hpp>
0045 
0046 #include <boost/asio/detail/push_options.hpp>
0047 
0048 namespace boost {
0049 namespace asio {
0050 namespace detail {
0051 
0052 template <typename Protocol>
0053 class win_iocp_socket_service :
0054   public execution_context_service_base<win_iocp_socket_service<Protocol>>,
0055   public win_iocp_socket_service_base
0056 {
0057 public:
0058   // The protocol type.
0059   typedef Protocol protocol_type;
0060 
0061   // The endpoint type.
0062   typedef typename Protocol::endpoint endpoint_type;
0063 
0064   // The native type of a socket.
0065   class native_handle_type
0066   {
0067   public:
0068     native_handle_type(socket_type s)
0069       : socket_(s),
0070         have_remote_endpoint_(false)
0071     {
0072     }
0073 
0074     native_handle_type(socket_type s, const endpoint_type& ep)
0075       : socket_(s),
0076         have_remote_endpoint_(true),
0077         remote_endpoint_(ep)
0078     {
0079     }
0080 
0081     void operator=(socket_type s)
0082     {
0083       socket_ = s;
0084       have_remote_endpoint_ = false;
0085       remote_endpoint_ = endpoint_type();
0086     }
0087 
0088     operator socket_type() const
0089     {
0090       return socket_;
0091     }
0092 
0093     bool have_remote_endpoint() const
0094     {
0095       return have_remote_endpoint_;
0096     }
0097 
0098     endpoint_type remote_endpoint() const
0099     {
0100       return remote_endpoint_;
0101     }
0102 
0103   private:
0104     socket_type socket_;
0105     bool have_remote_endpoint_;
0106     endpoint_type remote_endpoint_;
0107   };
0108 
0109   // The implementation type of the socket.
0110   struct implementation_type :
0111     win_iocp_socket_service_base::base_implementation_type
0112   {
0113     // Default constructor.
0114     implementation_type()
0115       : protocol_(endpoint_type().protocol()),
0116         have_remote_endpoint_(false),
0117         remote_endpoint_()
0118     {
0119     }
0120 
0121     // The protocol associated with the socket.
0122     protocol_type protocol_;
0123 
0124     // Whether we have a cached remote endpoint.
0125     bool have_remote_endpoint_;
0126 
0127     // A cached remote endpoint.
0128     endpoint_type remote_endpoint_;
0129   };
0130 
0131   // Constructor.
0132   win_iocp_socket_service(execution_context& context)
0133     : execution_context_service_base<
0134         win_iocp_socket_service<Protocol>>(context),
0135       win_iocp_socket_service_base(context)
0136   {
0137   }
0138 
0139   // Destroy all user-defined handler objects owned by the service.
0140   void shutdown()
0141   {
0142     this->base_shutdown();
0143   }
0144 
0145   // Move-construct a new socket implementation.
0146   void move_construct(implementation_type& impl,
0147       implementation_type& other_impl) noexcept
0148   {
0149     this->base_move_construct(impl, other_impl);
0150 
0151     impl.protocol_ = other_impl.protocol_;
0152     other_impl.protocol_ = endpoint_type().protocol();
0153 
0154     impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
0155     other_impl.have_remote_endpoint_ = false;
0156 
0157     impl.remote_endpoint_ = other_impl.remote_endpoint_;
0158     other_impl.remote_endpoint_ = endpoint_type();
0159   }
0160 
0161   // Move-assign from another socket implementation.
0162   void move_assign(implementation_type& impl,
0163       win_iocp_socket_service_base& other_service,
0164       implementation_type& other_impl)
0165   {
0166     this->base_move_assign(impl, other_service, other_impl);
0167 
0168     impl.protocol_ = other_impl.protocol_;
0169     other_impl.protocol_ = endpoint_type().protocol();
0170 
0171     impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
0172     other_impl.have_remote_endpoint_ = false;
0173 
0174     impl.remote_endpoint_ = other_impl.remote_endpoint_;
0175     other_impl.remote_endpoint_ = endpoint_type();
0176   }
0177 
0178   // Move-construct a new socket implementation from another protocol type.
0179   template <typename Protocol1>
0180   void converting_move_construct(implementation_type& impl,
0181       win_iocp_socket_service<Protocol1>&,
0182       typename win_iocp_socket_service<
0183         Protocol1>::implementation_type& other_impl)
0184   {
0185     this->base_move_construct(impl, other_impl);
0186 
0187     impl.protocol_ = protocol_type(other_impl.protocol_);
0188     other_impl.protocol_ = typename Protocol1::endpoint().protocol();
0189 
0190     impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;
0191     other_impl.have_remote_endpoint_ = false;
0192 
0193     impl.remote_endpoint_ = other_impl.remote_endpoint_;
0194     other_impl.remote_endpoint_ = typename Protocol1::endpoint();
0195   }
0196 
0197   // Open a new socket implementation.
0198   boost::system::error_code open(implementation_type& impl,
0199       const protocol_type& protocol, boost::system::error_code& ec)
0200   {
0201     if (!do_open(impl, protocol.family(),
0202           protocol.type(), protocol.protocol(), ec))
0203     {
0204       impl.protocol_ = protocol;
0205       impl.have_remote_endpoint_ = false;
0206       impl.remote_endpoint_ = endpoint_type();
0207     }
0208 
0209     BOOST_ASIO_ERROR_LOCATION(ec);
0210     return ec;
0211   }
0212 
0213   // Assign a native socket to a socket implementation.
0214   boost::system::error_code assign(implementation_type& impl,
0215       const protocol_type& protocol, const native_handle_type& native_socket,
0216       boost::system::error_code& ec)
0217   {
0218     if (!do_assign(impl, protocol.type(), native_socket, ec))
0219     {
0220       impl.protocol_ = protocol;
0221       impl.have_remote_endpoint_ = native_socket.have_remote_endpoint();
0222       impl.remote_endpoint_ = native_socket.remote_endpoint();
0223     }
0224 
0225     BOOST_ASIO_ERROR_LOCATION(ec);
0226     return ec;
0227   }
0228 
0229   // Get the native socket representation.
0230   native_handle_type native_handle(implementation_type& impl)
0231   {
0232     if (impl.have_remote_endpoint_)
0233       return native_handle_type(impl.socket_, impl.remote_endpoint_);
0234     return native_handle_type(impl.socket_);
0235   }
0236 
0237   // Bind the socket to the specified local endpoint.
0238   boost::system::error_code bind(implementation_type& impl,
0239       const endpoint_type& endpoint, boost::system::error_code& ec)
0240   {
0241     socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
0242 
0243     BOOST_ASIO_ERROR_LOCATION(ec);
0244     return ec;
0245   }
0246 
0247   // Set a socket option.
0248   template <typename Option>
0249   boost::system::error_code set_option(implementation_type& impl,
0250       const Option& option, boost::system::error_code& ec)
0251   {
0252     socket_ops::setsockopt(impl.socket_, impl.state_,
0253         option.level(impl.protocol_), option.name(impl.protocol_),
0254         option.data(impl.protocol_), option.size(impl.protocol_), ec);
0255 
0256     BOOST_ASIO_ERROR_LOCATION(ec);
0257     return ec;
0258   }
0259 
0260   // Set a socket option.
0261   template <typename Option>
0262   boost::system::error_code get_option(const implementation_type& impl,
0263       Option& option, boost::system::error_code& ec) const
0264   {
0265     std::size_t size = option.size(impl.protocol_);
0266     socket_ops::getsockopt(impl.socket_, impl.state_,
0267         option.level(impl.protocol_), option.name(impl.protocol_),
0268         option.data(impl.protocol_), &size, ec);
0269     if (!ec)
0270       option.resize(impl.protocol_, size);
0271 
0272     BOOST_ASIO_ERROR_LOCATION(ec);
0273     return ec;
0274   }
0275 
0276   // Get the local endpoint.
0277   endpoint_type local_endpoint(const implementation_type& impl,
0278       boost::system::error_code& ec) const
0279   {
0280     endpoint_type endpoint;
0281     std::size_t addr_len = endpoint.capacity();
0282     if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
0283     {
0284       BOOST_ASIO_ERROR_LOCATION(ec);
0285       return endpoint_type();
0286     }
0287     endpoint.resize(addr_len);
0288     return endpoint;
0289   }
0290 
0291   // Get the remote endpoint.
0292   endpoint_type remote_endpoint(const implementation_type& impl,
0293       boost::system::error_code& ec) const
0294   {
0295     endpoint_type endpoint = impl.remote_endpoint_;
0296     std::size_t addr_len = endpoint.capacity();
0297     if (socket_ops::getpeername(impl.socket_, endpoint.data(),
0298           &addr_len, impl.have_remote_endpoint_, ec))
0299     {
0300       BOOST_ASIO_ERROR_LOCATION(ec);
0301       return endpoint_type();
0302     }
0303     endpoint.resize(addr_len);
0304     return endpoint;
0305   }
0306 
0307   // Disable sends or receives on the socket.
0308   boost::system::error_code shutdown(base_implementation_type& impl,
0309       socket_base::shutdown_type what, boost::system::error_code& ec)
0310   {
0311     socket_ops::shutdown(impl.socket_, what, ec);
0312     return ec;
0313   }
0314 
0315   // Send a datagram to the specified endpoint. Returns the number of bytes
0316   // sent.
0317   template <typename ConstBufferSequence>
0318   size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
0319       const endpoint_type& destination, socket_base::message_flags flags,
0320       boost::system::error_code& ec)
0321   {
0322     buffer_sequence_adapter<boost::asio::const_buffer,
0323         ConstBufferSequence> bufs(buffers);
0324 
0325     size_t n = socket_ops::sync_sendto(impl.socket_,
0326         impl.state_, bufs.buffers(), bufs.count(), flags,
0327         destination.data(), destination.size(), ec);
0328 
0329     BOOST_ASIO_ERROR_LOCATION(ec);
0330     return n;
0331   }
0332 
0333   // Wait until data can be sent without blocking.
0334   size_t send_to(implementation_type& impl, const null_buffers&,
0335       const endpoint_type&, socket_base::message_flags,
0336       boost::system::error_code& ec)
0337   {
0338     // Wait for socket to become ready.
0339     socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
0340     BOOST_ASIO_ERROR_LOCATION(ec);
0341     return 0;
0342   }
0343 
0344   // Start an asynchronous send. The data being sent must be valid for the
0345   // lifetime of the asynchronous operation.
0346   template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
0347   void async_send_to(implementation_type& impl,
0348       const ConstBufferSequence& buffers, const endpoint_type& destination,
0349       socket_base::message_flags flags, Handler& handler,
0350       const IoExecutor& io_ex)
0351   {
0352     associated_cancellation_slot_t<Handler> slot
0353       = boost::asio::get_associated_cancellation_slot(handler);
0354 
0355     // Allocate and construct an operation to wrap the handler.
0356     typedef win_iocp_socket_send_op<
0357         ConstBufferSequence, Handler, IoExecutor> op;
0358     typename op::ptr p = { boost::asio::detail::addressof(handler),
0359       op::ptr::allocate(handler), 0 };
0360     operation* o = p.p = new (p.v) op(
0361         impl.cancel_token_, buffers, handler, io_ex);
0362 
0363     BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0364           &impl, impl.socket_, "async_send_to"));
0365 
0366     buffer_sequence_adapter<boost::asio::const_buffer,
0367         ConstBufferSequence> bufs(buffers);
0368 
0369     // Optionally register for per-operation cancellation.
0370     if (slot.is_connected())
0371       o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);
0372 
0373     start_send_to_op(impl, bufs.buffers(), bufs.count(),
0374         destination.data(), static_cast<int>(destination.size()),
0375         flags, o);
0376     p.v = p.p = 0;
0377   }
0378 
0379   // Start an asynchronous wait until data can be sent without blocking.
0380   template <typename Handler, typename IoExecutor>
0381   void async_send_to(implementation_type& impl, const null_buffers&,
0382       const endpoint_type&, socket_base::message_flags, Handler& handler,
0383       const IoExecutor& io_ex)
0384   {
0385     // Allocate and construct an operation to wrap the handler.
0386     typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
0387     typename op::ptr p = { boost::asio::detail::addressof(handler),
0388       op::ptr::allocate(handler), 0 };
0389     reactor_op* o = p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
0390 
0391     BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0392           &impl, impl.socket_, "async_send_to(null_buffers)"));
0393 
0394     start_reactor_op(impl, select_reactor::write_op, o);
0395     p.v = p.p = 0;
0396   }
0397 
0398   // Receive a datagram with the endpoint of the sender. Returns the number of
0399   // bytes received.
0400   template <typename MutableBufferSequence>
0401   size_t receive_from(implementation_type& impl,
0402       const MutableBufferSequence& buffers,
0403       endpoint_type& sender_endpoint, socket_base::message_flags flags,
0404       boost::system::error_code& ec)
0405   {
0406     buffer_sequence_adapter<boost::asio::mutable_buffer,
0407         MutableBufferSequence> bufs(buffers);
0408 
0409     std::size_t addr_len = sender_endpoint.capacity();
0410     std::size_t n = socket_ops::sync_recvfrom(impl.socket_,
0411         impl.state_, bufs.buffers(), bufs.count(), flags,
0412         sender_endpoint.data(), &addr_len, ec);
0413 
0414     if (!ec)
0415       sender_endpoint.resize(addr_len);
0416 
0417     BOOST_ASIO_ERROR_LOCATION(ec);
0418     return n;
0419   }
0420 
0421   // Wait until data can be received without blocking.
0422   size_t receive_from(implementation_type& impl,
0423       const null_buffers&, endpoint_type& sender_endpoint,
0424       socket_base::message_flags, boost::system::error_code& ec)
0425   {
0426     // Wait for socket to become ready.
0427     socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
0428 
0429     // Reset endpoint since it can be given no sensible value at this time.
0430     sender_endpoint = endpoint_type();
0431 
0432     BOOST_ASIO_ERROR_LOCATION(ec);
0433     return 0;
0434   }
0435 
0436   // Start an asynchronous receive. The buffer for the data being received and
0437   // the sender_endpoint object must both be valid for the lifetime of the
0438   // asynchronous operation.
0439   template <typename MutableBufferSequence,
0440       typename Handler, typename IoExecutor>
0441   void async_receive_from(implementation_type& impl,
0442       const MutableBufferSequence& buffers, endpoint_type& sender_endp,
0443       socket_base::message_flags flags, Handler& handler,
0444       const IoExecutor& io_ex)
0445   {
0446     associated_cancellation_slot_t<Handler> slot
0447       = boost::asio::get_associated_cancellation_slot(handler);
0448 
0449     // Allocate and construct an operation to wrap the handler.
0450     typedef win_iocp_socket_recvfrom_op<MutableBufferSequence,
0451         endpoint_type, Handler, IoExecutor> op;
0452     typename op::ptr p = { boost::asio::detail::addressof(handler),
0453       op::ptr::allocate(handler), 0 };
0454     operation* o = p.p = new (p.v) op(sender_endp,
0455         impl.cancel_token_, buffers, handler, io_ex);
0456 
0457     BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0458           &impl, impl.socket_, "async_receive_from"));
0459 
0460     buffer_sequence_adapter<boost::asio::mutable_buffer,
0461         MutableBufferSequence> bufs(buffers);
0462 
0463     // Optionally register for per-operation cancellation.
0464     if (slot.is_connected())
0465       o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);
0466 
0467     start_receive_from_op(impl, bufs.buffers(), bufs.count(),
0468         sender_endp.data(), flags, &p.p->endpoint_size(), o);
0469     p.v = p.p = 0;
0470   }
0471 
0472   // Wait until data can be received without blocking.
0473   template <typename Handler, typename IoExecutor>
0474   void async_receive_from(implementation_type& impl, const null_buffers&,
0475       endpoint_type& sender_endpoint, socket_base::message_flags flags,
0476       Handler& handler, const IoExecutor& io_ex)
0477   {
0478     associated_cancellation_slot_t<Handler> slot
0479       = boost::asio::get_associated_cancellation_slot(handler);
0480 
0481     // Allocate and construct an operation to wrap the handler.
0482     typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;
0483     typename op::ptr p = { boost::asio::detail::addressof(handler),
0484       op::ptr::allocate(handler), 0 };
0485     p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);
0486 
0487     BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0488           &impl, impl.socket_, "async_receive_from(null_buffers)"));
0489 
0490     // Reset endpoint since it can be given no sensible value at this time.
0491     sender_endpoint = endpoint_type();
0492 
0493     // Optionally register for per-operation cancellation.
0494     operation* iocp_op = p.p;
0495     if (slot.is_connected())
0496     {
0497       p.p->cancellation_key_ = iocp_op =
0498         &slot.template emplace<reactor_op_cancellation>(
0499             impl.socket_, iocp_op);
0500     }
0501 
0502     int op_type = start_null_buffers_receive_op(impl, flags, p.p, iocp_op);
0503     p.v = p.p = 0;
0504 
0505     // Update cancellation method if the reactor was used.
0506     if (slot.is_connected() && op_type != -1)
0507     {
0508       static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(
0509           &get_reactor(), &impl.reactor_data_, op_type);
0510     }
0511   }
0512 
0513   // Accept a new connection.
0514   template <typename Socket>
0515   boost::system::error_code accept(implementation_type& impl, Socket& peer,
0516       endpoint_type* peer_endpoint, boost::system::error_code& ec)
0517   {
0518     // We cannot accept a socket that is already open.
0519     if (peer.is_open())
0520     {
0521       ec = boost::asio::error::already_open;
0522       BOOST_ASIO_ERROR_LOCATION(ec);
0523       return ec;
0524     }
0525 
0526     std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
0527     socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
0528           impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
0529           peer_endpoint ? &addr_len : 0, ec));
0530 
0531     // On success, assign new connection to peer socket object.
0532     if (new_socket.get() != invalid_socket)
0533     {
0534       if (peer_endpoint)
0535         peer_endpoint->resize(addr_len);
0536       peer.assign(impl.protocol_, new_socket.get(), ec);
0537       if (!ec)
0538         new_socket.release();
0539     }
0540 
0541     BOOST_ASIO_ERROR_LOCATION(ec);
0542     return ec;
0543   }
0544 
0545   // Start an asynchronous accept. The peer and peer_endpoint objects
0546   // must be valid until the accept's handler is invoked.
0547   template <typename Socket, typename Handler, typename IoExecutor>
0548   void async_accept(implementation_type& impl, Socket& peer,
0549       endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)
0550   {
0551     associated_cancellation_slot_t<Handler> slot
0552       = boost::asio::get_associated_cancellation_slot(handler);
0553 
0554     // Allocate and construct an operation to wrap the handler.
0555     typedef win_iocp_socket_accept_op<Socket,
0556         protocol_type, Handler, IoExecutor> op;
0557     typename op::ptr p = { boost::asio::detail::addressof(handler),
0558       op::ptr::allocate(handler), 0 };
0559     bool enable_connection_aborted =
0560       (impl.state_ & socket_ops::enable_connection_aborted) != 0;
0561     operation* o = p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,
0562         peer_endpoint, enable_connection_aborted, handler, io_ex);
0563 
0564     BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0565           &impl, impl.socket_, "async_accept"));
0566 
0567     // Optionally register for per-operation cancellation.
0568     if (slot.is_connected())
0569     {
0570       accept_op_cancellation* c =
0571         &slot.template emplace<accept_op_cancellation>(impl.socket_, o);
0572       p.p->enable_cancellation(c->get_cancel_requested(), c);
0573       o = c;
0574     }
0575 
0576     start_accept_op(impl, peer.is_open(), p.p->new_socket(),
0577         impl.protocol_.family(), impl.protocol_.type(),
0578         impl.protocol_.protocol(), p.p->output_buffer(),
0579         p.p->address_length(), o);
0580     p.v = p.p = 0;
0581   }
0582 
0583   // Start an asynchronous accept. The peer and peer_endpoint objects
0584   // must be valid until the accept's handler is invoked.
0585   template <typename PeerIoExecutor, typename Handler, typename IoExecutor>
0586   void async_move_accept(implementation_type& impl,
0587       const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,
0588       Handler& handler, const IoExecutor& io_ex)
0589   {
0590     associated_cancellation_slot_t<Handler> slot
0591       = boost::asio::get_associated_cancellation_slot(handler);
0592 
0593     // Allocate and construct an operation to wrap the handler.
0594     typedef win_iocp_socket_move_accept_op<
0595         protocol_type, PeerIoExecutor, Handler, IoExecutor> op;
0596     typename op::ptr p = { boost::asio::detail::addressof(handler),
0597       op::ptr::allocate(handler), 0 };
0598     bool enable_connection_aborted =
0599       (impl.state_ & socket_ops::enable_connection_aborted) != 0;
0600     operation* o = p.p = new (p.v) op(*this, impl.socket_, impl.protocol_,
0601         peer_io_ex, peer_endpoint, enable_connection_aborted,
0602         handler, io_ex);
0603 
0604     BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0605           &impl, impl.socket_, "async_accept"));
0606 
0607     // Optionally register for per-operation cancellation.
0608     if (slot.is_connected())
0609     {
0610       accept_op_cancellation* c =
0611         &slot.template emplace<accept_op_cancellation>(impl.socket_, o);
0612       p.p->enable_cancellation(c->get_cancel_requested(), c);
0613       o = c;
0614     }
0615 
0616     start_accept_op(impl, false, p.p->new_socket(),
0617         impl.protocol_.family(), impl.protocol_.type(),
0618         impl.protocol_.protocol(), p.p->output_buffer(),
0619         p.p->address_length(), o);
0620     p.v = p.p = 0;
0621   }
0622 
0623   // Connect the socket to the specified endpoint.
0624   boost::system::error_code connect(implementation_type& impl,
0625       const endpoint_type& peer_endpoint, boost::system::error_code& ec)
0626   {
0627     socket_ops::sync_connect(impl.socket_,
0628         peer_endpoint.data(), peer_endpoint.size(), ec);
0629     BOOST_ASIO_ERROR_LOCATION(ec);
0630     return ec;
0631   }
0632 
0633   // Start an asynchronous connect.
0634   template <typename Handler, typename IoExecutor>
0635   void async_connect(implementation_type& impl,
0636       const endpoint_type& peer_endpoint, Handler& handler,
0637       const IoExecutor& io_ex)
0638   {
0639     associated_cancellation_slot_t<Handler> slot
0640       = boost::asio::get_associated_cancellation_slot(handler);
0641 
0642     // Allocate and construct an operation to wrap the handler.
0643     typedef win_iocp_socket_connect_op<Handler, IoExecutor> op;
0644     typename op::ptr p = { boost::asio::detail::addressof(handler),
0645       op::ptr::allocate(handler), 0 };
0646     p.p = new (p.v) op(impl.socket_, handler, io_ex);
0647 
0648     BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket",
0649           &impl, impl.socket_, "async_connect"));
0650 
0651     // Optionally register for per-operation cancellation.
0652     operation* iocp_op = p.p;
0653     if (slot.is_connected())
0654     {
0655       p.p->cancellation_key_ = iocp_op =
0656         &slot.template emplace<reactor_op_cancellation>(
0657             impl.socket_, iocp_op);
0658     }
0659 
0660     int op_type = start_connect_op(impl, impl.protocol_.family(),
0661         impl.protocol_.type(), peer_endpoint.data(),
0662         static_cast<int>(peer_endpoint.size()), p.p, iocp_op);
0663     p.v = p.p = 0;
0664 
0665     // Update cancellation method if the reactor was used.
0666     if (slot.is_connected() && op_type != -1)
0667     {
0668       static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(
0669           &get_reactor(), &impl.reactor_data_, op_type);
0670     }
0671   }
0672 };
0673 
0674 } // namespace detail
0675 } // namespace asio
0676 } // namespace boost
0677 
0678 #include <boost/asio/detail/pop_options.hpp>
0679 
0680 #endif // defined(BOOST_ASIO_HAS_IOCP)
0681 
0682 #endif // BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP