1 // 2 // detail/win_iocp_socket_service.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP 12 #define BOOST_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 <boost/asio/detail/config.hpp> 19 20 #if defined(BOOST_ASIO_HAS_IOCP) 21 22 #include <cstring> 23 #include <boost/asio/error.hpp> 24 #include <boost/asio/execution_context.hpp> 25 #include <boost/asio/socket_base.hpp> 26 #include <boost/asio/detail/bind_handler.hpp> 27 #include <boost/asio/detail/buffer_sequence_adapter.hpp> 28 #include <boost/asio/detail/fenced_block.hpp> 29 #include <boost/asio/detail/handler_alloc_helpers.hpp> 30 #include <boost/asio/detail/handler_invoke_helpers.hpp> 31 #include <boost/asio/detail/memory.hpp> 32 #include <boost/asio/detail/mutex.hpp> 33 #include <boost/asio/detail/operation.hpp> 34 #include <boost/asio/detail/reactor_op.hpp> 35 #include <boost/asio/detail/select_reactor.hpp> 36 #include <boost/asio/detail/socket_holder.hpp> 37 #include <boost/asio/detail/socket_ops.hpp> 38 #include <boost/asio/detail/socket_types.hpp> 39 #include <boost/asio/detail/win_iocp_io_context.hpp> 40 #include <boost/asio/detail/win_iocp_null_buffers_op.hpp> 41 #include <boost/asio/detail/win_iocp_socket_accept_op.hpp> 42 #include <boost/asio/detail/win_iocp_socket_connect_op.hpp> 43 #include <boost/asio/detail/win_iocp_socket_recvfrom_op.hpp> 44 #include <boost/asio/detail/win_iocp_socket_send_op.hpp> 45 #include <boost/asio/detail/win_iocp_socket_service_base.hpp> 46 47 #include <boost/asio/detail/push_options.hpp> 48 49 namespace boost { 50 namespace asio { 51 namespace detail { 52 53 template <typename Protocol> 54 class win_iocp_socket_service : 55 public execution_context_service_base<win_iocp_socket_service<Protocol> >, 56 public win_iocp_socket_service_base 57 { 58 public: 59 // The protocol type. 60 typedef Protocol protocol_type; 61 62 // The endpoint type. 63 typedef typename Protocol::endpoint endpoint_type; 64 65 // The native type of a socket. 66 class native_handle_type 67 { 68 public: native_handle_type(socket_type s)69 native_handle_type(socket_type s) 70 : socket_(s), 71 have_remote_endpoint_(false) 72 { 73 } 74 native_handle_type(socket_type s,const endpoint_type & ep)75 native_handle_type(socket_type s, const endpoint_type& ep) 76 : socket_(s), 77 have_remote_endpoint_(true), 78 remote_endpoint_(ep) 79 { 80 } 81 operator =(socket_type s)82 void operator=(socket_type s) 83 { 84 socket_ = s; 85 have_remote_endpoint_ = false; 86 remote_endpoint_ = endpoint_type(); 87 } 88 operator socket_type() const89 operator socket_type() const 90 { 91 return socket_; 92 } 93 have_remote_endpoint() const94 bool have_remote_endpoint() const 95 { 96 return have_remote_endpoint_; 97 } 98 remote_endpoint() const99 endpoint_type remote_endpoint() const 100 { 101 return remote_endpoint_; 102 } 103 104 private: 105 socket_type socket_; 106 bool have_remote_endpoint_; 107 endpoint_type remote_endpoint_; 108 }; 109 110 // The implementation type of the socket. 111 struct implementation_type : 112 win_iocp_socket_service_base::base_implementation_type 113 { 114 // Default constructor. implementation_typeboost::asio::detail::win_iocp_socket_service::implementation_type115 implementation_type() 116 : protocol_(endpoint_type().protocol()), 117 have_remote_endpoint_(false), 118 remote_endpoint_() 119 { 120 } 121 122 // The protocol associated with the socket. 123 protocol_type protocol_; 124 125 // Whether we have a cached remote endpoint. 126 bool have_remote_endpoint_; 127 128 // A cached remote endpoint. 129 endpoint_type remote_endpoint_; 130 }; 131 132 // Constructor. win_iocp_socket_service(execution_context & context)133 win_iocp_socket_service(execution_context& context) 134 : execution_context_service_base< 135 win_iocp_socket_service<Protocol> >(context), 136 win_iocp_socket_service_base(context) 137 { 138 } 139 140 // Destroy all user-defined handler objects owned by the service. shutdown()141 void shutdown() 142 { 143 this->base_shutdown(); 144 } 145 146 // Move-construct a new socket implementation. move_construct(implementation_type & impl,implementation_type & other_impl)147 void move_construct(implementation_type& impl, 148 implementation_type& other_impl) BOOST_ASIO_NOEXCEPT 149 { 150 this->base_move_construct(impl, other_impl); 151 152 impl.protocol_ = other_impl.protocol_; 153 other_impl.protocol_ = endpoint_type().protocol(); 154 155 impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_; 156 other_impl.have_remote_endpoint_ = false; 157 158 impl.remote_endpoint_ = other_impl.remote_endpoint_; 159 other_impl.remote_endpoint_ = endpoint_type(); 160 } 161 162 // Move-assign from another socket implementation. move_assign(implementation_type & impl,win_iocp_socket_service_base & other_service,implementation_type & other_impl)163 void move_assign(implementation_type& impl, 164 win_iocp_socket_service_base& other_service, 165 implementation_type& other_impl) 166 { 167 this->base_move_assign(impl, other_service, other_impl); 168 169 impl.protocol_ = other_impl.protocol_; 170 other_impl.protocol_ = endpoint_type().protocol(); 171 172 impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_; 173 other_impl.have_remote_endpoint_ = false; 174 175 impl.remote_endpoint_ = other_impl.remote_endpoint_; 176 other_impl.remote_endpoint_ = endpoint_type(); 177 } 178 179 // Move-construct a new socket implementation from another protocol type. 180 template <typename Protocol1> converting_move_construct(implementation_type & impl,win_iocp_socket_service<Protocol1> &,typename win_iocp_socket_service<Protocol1>::implementation_type & other_impl)181 void converting_move_construct(implementation_type& impl, 182 win_iocp_socket_service<Protocol1>&, 183 typename win_iocp_socket_service< 184 Protocol1>::implementation_type& other_impl) 185 { 186 this->base_move_construct(impl, other_impl); 187 188 impl.protocol_ = protocol_type(other_impl.protocol_); 189 other_impl.protocol_ = typename Protocol1::endpoint().protocol(); 190 191 impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_; 192 other_impl.have_remote_endpoint_ = false; 193 194 impl.remote_endpoint_ = other_impl.remote_endpoint_; 195 other_impl.remote_endpoint_ = typename Protocol1::endpoint(); 196 } 197 198 // Open a new socket implementation. open(implementation_type & impl,const protocol_type & protocol,boost::system::error_code & ec)199 boost::system::error_code open(implementation_type& impl, 200 const protocol_type& protocol, boost::system::error_code& ec) 201 { 202 if (!do_open(impl, protocol.family(), 203 protocol.type(), protocol.protocol(), ec)) 204 { 205 impl.protocol_ = protocol; 206 impl.have_remote_endpoint_ = false; 207 impl.remote_endpoint_ = endpoint_type(); 208 } 209 return ec; 210 } 211 212 // Assign a native socket to a socket implementation. assign(implementation_type & impl,const protocol_type & protocol,const native_handle_type & native_socket,boost::system::error_code & ec)213 boost::system::error_code assign(implementation_type& impl, 214 const protocol_type& protocol, const native_handle_type& native_socket, 215 boost::system::error_code& ec) 216 { 217 if (!do_assign(impl, protocol.type(), native_socket, ec)) 218 { 219 impl.protocol_ = protocol; 220 impl.have_remote_endpoint_ = native_socket.have_remote_endpoint(); 221 impl.remote_endpoint_ = native_socket.remote_endpoint(); 222 } 223 return ec; 224 } 225 226 // Get the native socket representation. native_handle(implementation_type & impl)227 native_handle_type native_handle(implementation_type& impl) 228 { 229 if (impl.have_remote_endpoint_) 230 return native_handle_type(impl.socket_, impl.remote_endpoint_); 231 return native_handle_type(impl.socket_); 232 } 233 234 // Bind the socket to the specified local endpoint. bind(implementation_type & impl,const endpoint_type & endpoint,boost::system::error_code & ec)235 boost::system::error_code bind(implementation_type& impl, 236 const endpoint_type& endpoint, boost::system::error_code& ec) 237 { 238 socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); 239 return ec; 240 } 241 242 // Set a socket option. 243 template <typename Option> set_option(implementation_type & impl,const Option & option,boost::system::error_code & ec)244 boost::system::error_code set_option(implementation_type& impl, 245 const Option& option, boost::system::error_code& ec) 246 { 247 socket_ops::setsockopt(impl.socket_, impl.state_, 248 option.level(impl.protocol_), option.name(impl.protocol_), 249 option.data(impl.protocol_), option.size(impl.protocol_), ec); 250 return ec; 251 } 252 253 // Set a socket option. 254 template <typename Option> get_option(const implementation_type & impl,Option & option,boost::system::error_code & ec) const255 boost::system::error_code get_option(const implementation_type& impl, 256 Option& option, boost::system::error_code& ec) const 257 { 258 std::size_t size = option.size(impl.protocol_); 259 socket_ops::getsockopt(impl.socket_, impl.state_, 260 option.level(impl.protocol_), option.name(impl.protocol_), 261 option.data(impl.protocol_), &size, ec); 262 if (!ec) 263 option.resize(impl.protocol_, size); 264 return ec; 265 } 266 267 // Get the local endpoint. local_endpoint(const implementation_type & impl,boost::system::error_code & ec) const268 endpoint_type local_endpoint(const implementation_type& impl, 269 boost::system::error_code& ec) const 270 { 271 endpoint_type endpoint; 272 std::size_t addr_len = endpoint.capacity(); 273 if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) 274 return endpoint_type(); 275 endpoint.resize(addr_len); 276 return endpoint; 277 } 278 279 // Get the remote endpoint. remote_endpoint(const implementation_type & impl,boost::system::error_code & ec) const280 endpoint_type remote_endpoint(const implementation_type& impl, 281 boost::system::error_code& ec) const 282 { 283 endpoint_type endpoint = impl.remote_endpoint_; 284 std::size_t addr_len = endpoint.capacity(); 285 if (socket_ops::getpeername(impl.socket_, endpoint.data(), 286 &addr_len, impl.have_remote_endpoint_, ec)) 287 return endpoint_type(); 288 endpoint.resize(addr_len); 289 return endpoint; 290 } 291 292 // Disable sends or receives on the socket. shutdown(base_implementation_type & impl,socket_base::shutdown_type what,boost::system::error_code & ec)293 boost::system::error_code shutdown(base_implementation_type& impl, 294 socket_base::shutdown_type what, boost::system::error_code& ec) 295 { 296 socket_ops::shutdown(impl.socket_, what, ec); 297 return ec; 298 } 299 300 // Send a datagram to the specified endpoint. Returns the number of bytes 301 // sent. 302 template <typename ConstBufferSequence> send_to(implementation_type & impl,const ConstBufferSequence & buffers,const endpoint_type & destination,socket_base::message_flags flags,boost::system::error_code & ec)303 size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, 304 const endpoint_type& destination, socket_base::message_flags flags, 305 boost::system::error_code& ec) 306 { 307 buffer_sequence_adapter<boost::asio::const_buffer, 308 ConstBufferSequence> bufs(buffers); 309 310 return socket_ops::sync_sendto(impl.socket_, impl.state_, 311 bufs.buffers(), bufs.count(), flags, 312 destination.data(), destination.size(), ec); 313 } 314 315 // Wait until data can be sent without blocking. send_to(implementation_type & impl,const null_buffers &,const endpoint_type &,socket_base::message_flags,boost::system::error_code & ec)316 size_t send_to(implementation_type& impl, const null_buffers&, 317 const endpoint_type&, socket_base::message_flags, 318 boost::system::error_code& ec) 319 { 320 // Wait for socket to become ready. 321 socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); 322 323 return 0; 324 } 325 326 // Start an asynchronous send. The data being sent must be valid for the 327 // lifetime of the asynchronous operation. 328 template <typename ConstBufferSequence, typename Handler, typename IoExecutor> async_send_to(implementation_type & impl,const ConstBufferSequence & buffers,const endpoint_type & destination,socket_base::message_flags flags,Handler & handler,const IoExecutor & io_ex)329 void async_send_to(implementation_type& impl, 330 const ConstBufferSequence& buffers, const endpoint_type& destination, 331 socket_base::message_flags flags, Handler& handler, 332 const IoExecutor& io_ex) 333 { 334 // Allocate and construct an operation to wrap the handler. 335 typedef win_iocp_socket_send_op< 336 ConstBufferSequence, Handler, IoExecutor> op; 337 typename op::ptr p = { boost::asio::detail::addressof(handler), 338 op::ptr::allocate(handler), 0 }; 339 p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex); 340 341 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", 342 &impl, impl.socket_, "async_send_to")); 343 344 buffer_sequence_adapter<boost::asio::const_buffer, 345 ConstBufferSequence> bufs(buffers); 346 347 start_send_to_op(impl, bufs.buffers(), bufs.count(), 348 destination.data(), static_cast<int>(destination.size()), 349 flags, p.p); 350 p.v = p.p = 0; 351 } 352 353 // Start an asynchronous wait until data can be sent without blocking. 354 template <typename Handler, typename IoExecutor> async_send_to(implementation_type & impl,const null_buffers &,const endpoint_type &,socket_base::message_flags,Handler & handler,const IoExecutor & io_ex)355 void async_send_to(implementation_type& impl, const null_buffers&, 356 const endpoint_type&, socket_base::message_flags, Handler& handler, 357 const IoExecutor& io_ex) 358 { 359 // Allocate and construct an operation to wrap the handler. 360 typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; 361 typename op::ptr p = { boost::asio::detail::addressof(handler), 362 op::ptr::allocate(handler), 0 }; 363 p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); 364 365 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", 366 &impl, impl.socket_, "async_send_to(null_buffers)")); 367 368 start_reactor_op(impl, select_reactor::write_op, p.p); 369 p.v = p.p = 0; 370 } 371 372 // Receive a datagram with the endpoint of the sender. Returns the number of 373 // bytes received. 374 template <typename MutableBufferSequence> receive_from(implementation_type & impl,const MutableBufferSequence & buffers,endpoint_type & sender_endpoint,socket_base::message_flags flags,boost::system::error_code & ec)375 size_t receive_from(implementation_type& impl, 376 const MutableBufferSequence& buffers, 377 endpoint_type& sender_endpoint, socket_base::message_flags flags, 378 boost::system::error_code& ec) 379 { 380 buffer_sequence_adapter<boost::asio::mutable_buffer, 381 MutableBufferSequence> bufs(buffers); 382 383 std::size_t addr_len = sender_endpoint.capacity(); 384 std::size_t bytes_recvd = socket_ops::sync_recvfrom( 385 impl.socket_, impl.state_, bufs.buffers(), bufs.count(), 386 flags, sender_endpoint.data(), &addr_len, ec); 387 388 if (!ec) 389 sender_endpoint.resize(addr_len); 390 391 return bytes_recvd; 392 } 393 394 // Wait until data can be received without blocking. receive_from(implementation_type & impl,const null_buffers &,endpoint_type & sender_endpoint,socket_base::message_flags,boost::system::error_code & ec)395 size_t receive_from(implementation_type& impl, 396 const null_buffers&, endpoint_type& sender_endpoint, 397 socket_base::message_flags, boost::system::error_code& ec) 398 { 399 // Wait for socket to become ready. 400 socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); 401 402 // Reset endpoint since it can be given no sensible value at this time. 403 sender_endpoint = endpoint_type(); 404 405 return 0; 406 } 407 408 // Start an asynchronous receive. The buffer for the data being received and 409 // the sender_endpoint object must both be valid for the lifetime of the 410 // asynchronous operation. 411 template <typename MutableBufferSequence, 412 typename Handler, typename IoExecutor> async_receive_from(implementation_type & impl,const MutableBufferSequence & buffers,endpoint_type & sender_endp,socket_base::message_flags flags,Handler & handler,const IoExecutor & io_ex)413 void async_receive_from(implementation_type& impl, 414 const MutableBufferSequence& buffers, endpoint_type& sender_endp, 415 socket_base::message_flags flags, Handler& handler, 416 const IoExecutor& io_ex) 417 { 418 // Allocate and construct an operation to wrap the handler. 419 typedef win_iocp_socket_recvfrom_op<MutableBufferSequence, 420 endpoint_type, Handler, IoExecutor> op; 421 typename op::ptr p = { boost::asio::detail::addressof(handler), 422 op::ptr::allocate(handler), 0 }; 423 p.p = new (p.v) op(sender_endp, impl.cancel_token_, 424 buffers, handler, io_ex); 425 426 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", 427 &impl, impl.socket_, "async_receive_from")); 428 429 buffer_sequence_adapter<boost::asio::mutable_buffer, 430 MutableBufferSequence> bufs(buffers); 431 432 start_receive_from_op(impl, bufs.buffers(), bufs.count(), 433 sender_endp.data(), flags, &p.p->endpoint_size(), p.p); 434 p.v = p.p = 0; 435 } 436 437 // Wait until data can be received without blocking. 438 template <typename Handler, typename IoExecutor> async_receive_from(implementation_type & impl,const null_buffers &,endpoint_type & sender_endpoint,socket_base::message_flags flags,Handler & handler,const IoExecutor & io_ex)439 void async_receive_from(implementation_type& impl, const null_buffers&, 440 endpoint_type& sender_endpoint, socket_base::message_flags flags, 441 Handler& handler, const IoExecutor& io_ex) 442 { 443 // Allocate and construct an operation to wrap the handler. 444 typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; 445 typename op::ptr p = { boost::asio::detail::addressof(handler), 446 op::ptr::allocate(handler), 0 }; 447 p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); 448 449 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", 450 &impl, impl.socket_, "async_receive_from(null_buffers)")); 451 452 // Reset endpoint since it can be given no sensible value at this time. 453 sender_endpoint = endpoint_type(); 454 455 start_null_buffers_receive_op(impl, flags, p.p); 456 p.v = p.p = 0; 457 } 458 459 // Accept a new connection. 460 template <typename Socket> accept(implementation_type & impl,Socket & peer,endpoint_type * peer_endpoint,boost::system::error_code & ec)461 boost::system::error_code accept(implementation_type& impl, Socket& peer, 462 endpoint_type* peer_endpoint, boost::system::error_code& ec) 463 { 464 // We cannot accept a socket that is already open. 465 if (peer.is_open()) 466 { 467 ec = boost::asio::error::already_open; 468 return ec; 469 } 470 471 std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; 472 socket_holder new_socket(socket_ops::sync_accept(impl.socket_, 473 impl.state_, peer_endpoint ? peer_endpoint->data() : 0, 474 peer_endpoint ? &addr_len : 0, ec)); 475 476 // On success, assign new connection to peer socket object. 477 if (new_socket.get() != invalid_socket) 478 { 479 if (peer_endpoint) 480 peer_endpoint->resize(addr_len); 481 peer.assign(impl.protocol_, new_socket.get(), ec); 482 if (!ec) 483 new_socket.release(); 484 } 485 486 return ec; 487 } 488 489 // Start an asynchronous accept. The peer and peer_endpoint objects 490 // must be valid until the accept's handler is invoked. 491 template <typename Socket, typename Handler, typename IoExecutor> async_accept(implementation_type & impl,Socket & peer,endpoint_type * peer_endpoint,Handler & handler,const IoExecutor & io_ex)492 void async_accept(implementation_type& impl, Socket& peer, 493 endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) 494 { 495 // Allocate and construct an operation to wrap the handler. 496 typedef win_iocp_socket_accept_op<Socket, 497 protocol_type, Handler, IoExecutor> op; 498 typename op::ptr p = { boost::asio::detail::addressof(handler), 499 op::ptr::allocate(handler), 0 }; 500 bool enable_connection_aborted = 501 (impl.state_ & socket_ops::enable_connection_aborted) != 0; 502 p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_, 503 peer_endpoint, enable_connection_aborted, handler, io_ex); 504 505 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", 506 &impl, impl.socket_, "async_accept")); 507 508 start_accept_op(impl, peer.is_open(), p.p->new_socket(), 509 impl.protocol_.family(), impl.protocol_.type(), 510 impl.protocol_.protocol(), p.p->output_buffer(), 511 p.p->address_length(), p.p); 512 p.v = p.p = 0; 513 } 514 515 #if defined(BOOST_ASIO_HAS_MOVE) 516 // Start an asynchronous accept. The peer and peer_endpoint objects 517 // must be valid until the accept's handler is invoked. 518 template <typename PeerIoExecutor, typename Handler, typename IoExecutor> async_move_accept(implementation_type & impl,const PeerIoExecutor & peer_io_ex,endpoint_type * peer_endpoint,Handler & handler,const IoExecutor & io_ex)519 void async_move_accept(implementation_type& impl, 520 const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, 521 Handler& handler, const IoExecutor& io_ex) 522 { 523 // Allocate and construct an operation to wrap the handler. 524 typedef win_iocp_socket_move_accept_op< 525 protocol_type, PeerIoExecutor, Handler, IoExecutor> op; 526 typename op::ptr p = { boost::asio::detail::addressof(handler), 527 op::ptr::allocate(handler), 0 }; 528 bool enable_connection_aborted = 529 (impl.state_ & socket_ops::enable_connection_aborted) != 0; 530 p.p = new (p.v) op(*this, impl.socket_, impl.protocol_, 531 peer_io_ex, peer_endpoint, enable_connection_aborted, 532 handler, io_ex); 533 534 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", 535 &impl, impl.socket_, "async_accept")); 536 537 start_accept_op(impl, false, p.p->new_socket(), 538 impl.protocol_.family(), impl.protocol_.type(), 539 impl.protocol_.protocol(), p.p->output_buffer(), 540 p.p->address_length(), p.p); 541 p.v = p.p = 0; 542 } 543 #endif // defined(BOOST_ASIO_HAS_MOVE) 544 545 // Connect the socket to the specified endpoint. connect(implementation_type & impl,const endpoint_type & peer_endpoint,boost::system::error_code & ec)546 boost::system::error_code connect(implementation_type& impl, 547 const endpoint_type& peer_endpoint, boost::system::error_code& ec) 548 { 549 socket_ops::sync_connect(impl.socket_, 550 peer_endpoint.data(), peer_endpoint.size(), ec); 551 return ec; 552 } 553 554 // Start an asynchronous connect. 555 template <typename Handler, typename IoExecutor> async_connect(implementation_type & impl,const endpoint_type & peer_endpoint,Handler & handler,const IoExecutor & io_ex)556 void async_connect(implementation_type& impl, 557 const endpoint_type& peer_endpoint, Handler& handler, 558 const IoExecutor& io_ex) 559 { 560 // Allocate and construct an operation to wrap the handler. 561 typedef win_iocp_socket_connect_op<Handler, IoExecutor> op; 562 typename op::ptr p = { boost::asio::detail::addressof(handler), 563 op::ptr::allocate(handler), 0 }; 564 p.p = new (p.v) op(impl.socket_, handler, io_ex); 565 566 BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", 567 &impl, impl.socket_, "async_connect")); 568 569 start_connect_op(impl, impl.protocol_.family(), impl.protocol_.type(), 570 peer_endpoint.data(), static_cast<int>(peer_endpoint.size()), p.p); 571 p.v = p.p = 0; 572 } 573 }; 574 575 } // namespace detail 576 } // namespace asio 577 } // namespace boost 578 579 #include <boost/asio/detail/pop_options.hpp> 580 581 #endif // defined(BOOST_ASIO_HAS_IOCP) 582 583 #endif // BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP 584