]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // detail/win_iocp_socket_service.hpp | |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
92f5a8d4 | 5 | // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
7c673cae FG |
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> | |
92f5a8d4 | 24 | #include <boost/asio/execution_context.hpp> |
7c673cae | 25 | #include <boost/asio/socket_base.hpp> |
7c673cae FG |
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> | |
b32b8144 | 31 | #include <boost/asio/detail/memory.hpp> |
7c673cae FG |
32 | #include <boost/asio/detail/mutex.hpp> |
33 | #include <boost/asio/detail/operation.hpp> | |
7c673cae | 34 | #include <boost/asio/detail/reactor_op.hpp> |
b32b8144 | 35 | #include <boost/asio/detail/select_reactor.hpp> |
7c673cae FG |
36 | #include <boost/asio/detail/socket_holder.hpp> |
37 | #include <boost/asio/detail/socket_ops.hpp> | |
38 | #include <boost/asio/detail/socket_types.hpp> | |
b32b8144 | 39 | #include <boost/asio/detail/win_iocp_io_context.hpp> |
7c673cae FG |
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> | |
b32b8144 | 54 | class win_iocp_socket_service : |
92f5a8d4 | 55 | public execution_context_service_base<win_iocp_socket_service<Protocol> >, |
b32b8144 | 56 | public win_iocp_socket_service_base |
7c673cae FG |
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: | |
69 | native_handle_type(socket_type s) | |
70 | : socket_(s), | |
71 | have_remote_endpoint_(false) | |
72 | { | |
73 | } | |
74 | ||
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 | ||
82 | void operator=(socket_type s) | |
83 | { | |
84 | socket_ = s; | |
85 | have_remote_endpoint_ = false; | |
86 | remote_endpoint_ = endpoint_type(); | |
87 | } | |
88 | ||
89 | operator socket_type() const | |
90 | { | |
91 | return socket_; | |
92 | } | |
93 | ||
94 | bool have_remote_endpoint() const | |
95 | { | |
96 | return have_remote_endpoint_; | |
97 | } | |
98 | ||
99 | 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. | |
115 | 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. | |
92f5a8d4 TL |
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) | |
7c673cae FG |
137 | { |
138 | } | |
139 | ||
b32b8144 FG |
140 | // Destroy all user-defined handler objects owned by the service. |
141 | void shutdown() | |
142 | { | |
143 | this->base_shutdown(); | |
144 | } | |
145 | ||
7c673cae FG |
146 | // Move-construct a new socket implementation. |
147 | void move_construct(implementation_type& impl, | |
92f5a8d4 | 148 | implementation_type& other_impl) BOOST_ASIO_NOEXCEPT |
7c673cae FG |
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. | |
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> | |
181 | void converting_move_construct(implementation_type& impl, | |
b32b8144 | 182 | win_iocp_socket_service<Protocol1>&, |
7c673cae FG |
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. | |
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. | |
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. | |
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. | |
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> | |
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> | |
255 | 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. | |
268 | 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. | |
280 | 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 | ||
b32b8144 FG |
292 | // Disable sends or receives on the socket. |
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 | ||
7c673cae FG |
300 | // Send a datagram to the specified endpoint. Returns the number of bytes |
301 | // sent. | |
302 | template <typename ConstBufferSequence> | |
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. | |
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. | |
b32b8144 | 321 | socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); |
7c673cae FG |
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. | |
92f5a8d4 | 328 | template <typename ConstBufferSequence, typename Handler, typename IoExecutor> |
7c673cae FG |
329 | void async_send_to(implementation_type& impl, |
330 | const ConstBufferSequence& buffers, const endpoint_type& destination, | |
92f5a8d4 TL |
331 | socket_base::message_flags flags, Handler& handler, |
332 | const IoExecutor& io_ex) | |
7c673cae FG |
333 | { |
334 | // Allocate and construct an operation to wrap the handler. | |
92f5a8d4 TL |
335 | typedef win_iocp_socket_send_op< |
336 | ConstBufferSequence, Handler, IoExecutor> op; | |
7c673cae | 337 | typename op::ptr p = { boost::asio::detail::addressof(handler), |
b32b8144 | 338 | op::ptr::allocate(handler), 0 }; |
92f5a8d4 | 339 | p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex); |
7c673cae | 340 | |
92f5a8d4 | 341 | BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", |
b32b8144 | 342 | &impl, impl.socket_, "async_send_to")); |
7c673cae FG |
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. | |
92f5a8d4 | 354 | template <typename Handler, typename IoExecutor> |
7c673cae | 355 | void async_send_to(implementation_type& impl, const null_buffers&, |
92f5a8d4 TL |
356 | const endpoint_type&, socket_base::message_flags, Handler& handler, |
357 | const IoExecutor& io_ex) | |
7c673cae FG |
358 | { |
359 | // Allocate and construct an operation to wrap the handler. | |
92f5a8d4 | 360 | typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; |
7c673cae | 361 | typename op::ptr p = { boost::asio::detail::addressof(handler), |
b32b8144 | 362 | op::ptr::allocate(handler), 0 }; |
92f5a8d4 | 363 | p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); |
7c673cae | 364 | |
92f5a8d4 | 365 | BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", |
b32b8144 | 366 | &impl, impl.socket_, "async_send_to(null_buffers)")); |
7c673cae | 367 | |
b32b8144 | 368 | start_reactor_op(impl, select_reactor::write_op, p.p); |
7c673cae FG |
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> | |
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. | |
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. | |
b32b8144 | 400 | socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); |
7c673cae FG |
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. | |
92f5a8d4 TL |
411 | template <typename MutableBufferSequence, |
412 | typename Handler, typename IoExecutor> | |
7c673cae FG |
413 | void async_receive_from(implementation_type& impl, |
414 | const MutableBufferSequence& buffers, endpoint_type& sender_endp, | |
92f5a8d4 TL |
415 | socket_base::message_flags flags, Handler& handler, |
416 | const IoExecutor& io_ex) | |
7c673cae FG |
417 | { |
418 | // Allocate and construct an operation to wrap the handler. | |
92f5a8d4 TL |
419 | typedef win_iocp_socket_recvfrom_op<MutableBufferSequence, |
420 | endpoint_type, Handler, IoExecutor> op; | |
7c673cae | 421 | typename op::ptr p = { boost::asio::detail::addressof(handler), |
b32b8144 | 422 | op::ptr::allocate(handler), 0 }; |
92f5a8d4 TL |
423 | p.p = new (p.v) op(sender_endp, impl.cancel_token_, |
424 | buffers, handler, io_ex); | |
7c673cae | 425 | |
92f5a8d4 | 426 | BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", |
b32b8144 | 427 | &impl, impl.socket_, "async_receive_from")); |
7c673cae FG |
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. | |
92f5a8d4 TL |
438 | template <typename Handler, typename IoExecutor> |
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) | |
7c673cae FG |
442 | { |
443 | // Allocate and construct an operation to wrap the handler. | |
92f5a8d4 | 444 | typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; |
7c673cae | 445 | typename op::ptr p = { boost::asio::detail::addressof(handler), |
b32b8144 | 446 | op::ptr::allocate(handler), 0 }; |
92f5a8d4 | 447 | p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); |
7c673cae | 448 | |
92f5a8d4 | 449 | BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", |
b32b8144 | 450 | &impl, impl.socket_, "async_receive_from(null_buffers)")); |
7c673cae FG |
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> | |
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); | |
b32b8144 FG |
481 | peer.assign(impl.protocol_, new_socket.get(), ec); |
482 | if (!ec) | |
7c673cae FG |
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. | |
92f5a8d4 | 491 | template <typename Socket, typename Handler, typename IoExecutor> |
7c673cae | 492 | void async_accept(implementation_type& impl, Socket& peer, |
92f5a8d4 | 493 | endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) |
7c673cae FG |
494 | { |
495 | // Allocate and construct an operation to wrap the handler. | |
92f5a8d4 TL |
496 | typedef win_iocp_socket_accept_op<Socket, |
497 | protocol_type, Handler, IoExecutor> op; | |
7c673cae | 498 | typename op::ptr p = { boost::asio::detail::addressof(handler), |
b32b8144 | 499 | op::ptr::allocate(handler), 0 }; |
7c673cae FG |
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_, | |
92f5a8d4 | 503 | peer_endpoint, enable_connection_aborted, handler, io_ex); |
7c673cae | 504 | |
92f5a8d4 | 505 | BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", |
b32b8144 | 506 | &impl, impl.socket_, "async_accept")); |
7c673cae FG |
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 | ||
b32b8144 FG |
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. | |
92f5a8d4 TL |
518 | template <typename PeerIoExecutor, typename Handler, typename IoExecutor> |
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) | |
b32b8144 FG |
522 | { |
523 | // Allocate and construct an operation to wrap the handler. | |
92f5a8d4 TL |
524 | typedef win_iocp_socket_move_accept_op< |
525 | protocol_type, PeerIoExecutor, Handler, IoExecutor> op; | |
b32b8144 FG |
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_, | |
92f5a8d4 TL |
531 | peer_io_ex, peer_endpoint, enable_connection_aborted, |
532 | handler, io_ex); | |
b32b8144 | 533 | |
92f5a8d4 | 534 | BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", |
b32b8144 FG |
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 | ||
7c673cae FG |
545 | // Connect the socket to the specified endpoint. |
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. | |
92f5a8d4 | 555 | template <typename Handler, typename IoExecutor> |
7c673cae | 556 | void async_connect(implementation_type& impl, |
92f5a8d4 TL |
557 | const endpoint_type& peer_endpoint, Handler& handler, |
558 | const IoExecutor& io_ex) | |
7c673cae FG |
559 | { |
560 | // Allocate and construct an operation to wrap the handler. | |
92f5a8d4 | 561 | typedef win_iocp_socket_connect_op<Handler, IoExecutor> op; |
7c673cae | 562 | typename op::ptr p = { boost::asio::detail::addressof(handler), |
b32b8144 | 563 | op::ptr::allocate(handler), 0 }; |
92f5a8d4 | 564 | p.p = new (p.v) op(impl.socket_, handler, io_ex); |
7c673cae | 565 | |
92f5a8d4 | 566 | BOOST_ASIO_HANDLER_CREATION((context_, *p.p, "socket", |
b32b8144 | 567 | &impl, impl.socket_, "async_connect")); |
7c673cae FG |
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 |