]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/detail/win_iocp_socket_accept_op.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / asio / detail / win_iocp_socket_accept_op.hpp
CommitLineData
7c673cae
FG
1//
2// detail/win_iocp_socket_accept_op.hpp
3// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4//
f67539c2 5// Copyright (c) 2003-2020 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_ACCEPT_OP_HPP
12#define BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_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
7c673cae 22#include <boost/asio/detail/bind_handler.hpp>
7c673cae
FG
23#include <boost/asio/detail/fenced_block.hpp>
24#include <boost/asio/detail/handler_alloc_helpers.hpp>
25#include <boost/asio/detail/handler_invoke_helpers.hpp>
20effc67 26#include <boost/asio/detail/handler_work.hpp>
b32b8144 27#include <boost/asio/detail/memory.hpp>
7c673cae
FG
28#include <boost/asio/detail/operation.hpp>
29#include <boost/asio/detail/socket_ops.hpp>
30#include <boost/asio/detail/win_iocp_socket_service_base.hpp>
31#include <boost/asio/error.hpp>
32
33#include <boost/asio/detail/push_options.hpp>
34
35namespace boost {
36namespace asio {
37namespace detail {
38
92f5a8d4
TL
39template <typename Socket, typename Protocol,
40 typename Handler, typename IoExecutor>
7c673cae
FG
41class win_iocp_socket_accept_op : public operation
42{
43public:
44 BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_accept_op);
45
46 win_iocp_socket_accept_op(win_iocp_socket_service_base& socket_service,
47 socket_type socket, Socket& peer, const Protocol& protocol,
48 typename Protocol::endpoint* peer_endpoint,
92f5a8d4 49 bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex)
7c673cae
FG
50 : operation(&win_iocp_socket_accept_op::do_complete),
51 socket_service_(socket_service),
52 socket_(socket),
53 peer_(peer),
54 protocol_(protocol),
55 peer_endpoint_(peer_endpoint),
56 enable_connection_aborted_(enable_connection_aborted),
92f5a8d4 57 handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
20effc67 58 work_(handler_, io_ex)
7c673cae
FG
59 {
60 }
61
62 socket_holder& new_socket()
63 {
64 return new_socket_;
65 }
66
67 void* output_buffer()
68 {
69 return output_buffer_;
70 }
71
72 DWORD address_length()
73 {
74 return sizeof(sockaddr_storage_type) + 16;
75 }
76
b32b8144 77 static void do_complete(void* owner, operation* base,
7c673cae
FG
78 const boost::system::error_code& result_ec,
79 std::size_t /*bytes_transferred*/)
80 {
81 boost::system::error_code ec(result_ec);
82
83 // Take ownership of the operation object.
84 win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base));
85 ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
86
87 if (owner)
88 {
89 typename Protocol::endpoint peer_endpoint;
90 std::size_t addr_len = peer_endpoint.capacity();
91 socket_ops::complete_iocp_accept(o->socket_,
92 o->output_buffer(), o->address_length(),
93 peer_endpoint.data(), &addr_len,
94 o->new_socket_.get(), ec);
95
96 // Restart the accept operation if we got the connection_aborted error
97 // and the enable_connection_aborted socket option is not set.
98 if (ec == boost::asio::error::connection_aborted
99 && !o->enable_connection_aborted_)
100 {
101 o->reset();
102 o->socket_service_.restart_accept_op(o->socket_,
103 o->new_socket_, o->protocol_.family(),
104 o->protocol_.type(), o->protocol_.protocol(),
105 o->output_buffer(), o->address_length(), o);
106 p.v = p.p = 0;
107 return;
108 }
109
110 // If the socket was successfully accepted, transfer ownership of the
111 // socket to the peer object.
112 if (!ec)
113 {
114 o->peer_.assign(o->protocol_,
115 typename Socket::native_handle_type(
116 o->new_socket_.get(), peer_endpoint), ec);
117 if (!ec)
118 o->new_socket_.release();
119 }
120
121 // Pass endpoint back to caller.
122 if (o->peer_endpoint_)
123 *o->peer_endpoint_ = peer_endpoint;
124 }
125
b32b8144 126 BOOST_ASIO_HANDLER_COMPLETION((*o));
7c673cae 127
20effc67
TL
128 // Take ownership of the operation's outstanding work.
129 handler_work<Handler, IoExecutor> w(
130 BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
131 o->work_));
132
7c673cae
FG
133 // Make a copy of the handler so that the memory can be deallocated before
134 // the upcall is made. Even if we're not about to make an upcall, a
135 // sub-object of the handler may be the true owner of the memory associated
136 // with the handler. Consequently, a local copy of the handler is required
137 // to ensure that any owning sub-object remains valid until after we have
138 // deallocated the memory here.
139 detail::binder1<Handler, boost::system::error_code>
140 handler(o->handler_, ec);
141 p.h = boost::asio::detail::addressof(handler.handler_);
142 p.reset();
143
144 // Make the upcall if required.
145 if (owner)
146 {
147 fenced_block b(fenced_block::half);
148 BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
b32b8144 149 w.complete(handler, handler.handler_);
7c673cae
FG
150 BOOST_ASIO_HANDLER_INVOCATION_END;
151 }
152 }
153
154private:
155 win_iocp_socket_service_base& socket_service_;
156 socket_type socket_;
157 socket_holder new_socket_;
158 Socket& peer_;
159 Protocol protocol_;
160 typename Protocol::endpoint* peer_endpoint_;
161 unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
162 bool enable_connection_aborted_;
163 Handler handler_;
20effc67 164 handler_work<Handler, IoExecutor> work_;
7c673cae
FG
165};
166
b32b8144
FG
167#if defined(BOOST_ASIO_HAS_MOVE)
168
92f5a8d4
TL
169template <typename Protocol, typename PeerIoExecutor,
170 typename Handler, typename IoExecutor>
b32b8144
FG
171class win_iocp_socket_move_accept_op : public operation
172{
173public:
174 BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_move_accept_op);
175
176 win_iocp_socket_move_accept_op(
177 win_iocp_socket_service_base& socket_service, socket_type socket,
92f5a8d4 178 const Protocol& protocol, const PeerIoExecutor& peer_io_ex,
b32b8144 179 typename Protocol::endpoint* peer_endpoint,
92f5a8d4 180 bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex)
b32b8144
FG
181 : operation(&win_iocp_socket_move_accept_op::do_complete),
182 socket_service_(socket_service),
183 socket_(socket),
92f5a8d4 184 peer_(peer_io_ex),
b32b8144
FG
185 protocol_(protocol),
186 peer_endpoint_(peer_endpoint),
187 enable_connection_aborted_(enable_connection_aborted),
92f5a8d4 188 handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
20effc67 189 work_(handler_, io_ex)
b32b8144 190 {
b32b8144
FG
191 }
192
193 socket_holder& new_socket()
194 {
195 return new_socket_;
196 }
197
198 void* output_buffer()
199 {
200 return output_buffer_;
201 }
202
203 DWORD address_length()
204 {
205 return sizeof(sockaddr_storage_type) + 16;
206 }
207
208 static void do_complete(void* owner, operation* base,
209 const boost::system::error_code& result_ec,
210 std::size_t /*bytes_transferred*/)
211 {
212 boost::system::error_code ec(result_ec);
213
214 // Take ownership of the operation object.
215 win_iocp_socket_move_accept_op* o(
216 static_cast<win_iocp_socket_move_accept_op*>(base));
217 ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
b32b8144
FG
218
219 if (owner)
220 {
221 typename Protocol::endpoint peer_endpoint;
222 std::size_t addr_len = peer_endpoint.capacity();
223 socket_ops::complete_iocp_accept(o->socket_,
224 o->output_buffer(), o->address_length(),
225 peer_endpoint.data(), &addr_len,
226 o->new_socket_.get(), ec);
227
228 // Restart the accept operation if we got the connection_aborted error
229 // and the enable_connection_aborted socket option is not set.
230 if (ec == boost::asio::error::connection_aborted
231 && !o->enable_connection_aborted_)
232 {
233 o->reset();
234 o->socket_service_.restart_accept_op(o->socket_,
235 o->new_socket_, o->protocol_.family(),
236 o->protocol_.type(), o->protocol_.protocol(),
237 o->output_buffer(), o->address_length(), o);
238 p.v = p.p = 0;
239 return;
240 }
241
242 // If the socket was successfully accepted, transfer ownership of the
243 // socket to the peer object.
244 if (!ec)
245 {
246 o->peer_.assign(o->protocol_,
247 typename Protocol::socket::native_handle_type(
248 o->new_socket_.get(), peer_endpoint), ec);
249 if (!ec)
250 o->new_socket_.release();
251 }
252
253 // Pass endpoint back to caller.
254 if (o->peer_endpoint_)
255 *o->peer_endpoint_ = peer_endpoint;
256 }
257
258 BOOST_ASIO_HANDLER_COMPLETION((*o));
259
20effc67
TL
260 // Take ownership of the operation's outstanding work.
261 handler_work<Handler, IoExecutor> w(
262 BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(
263 o->work_));
264
b32b8144
FG
265 // Make a copy of the handler so that the memory can be deallocated before
266 // the upcall is made. Even if we're not about to make an upcall, a
267 // sub-object of the handler may be the true owner of the memory associated
268 // with the handler. Consequently, a local copy of the handler is required
269 // to ensure that any owning sub-object remains valid until after we have
270 // deallocated the memory here.
271 detail::move_binder2<Handler,
92f5a8d4 272 boost::system::error_code, peer_socket_type>
b32b8144 273 handler(0, BOOST_ASIO_MOVE_CAST(Handler)(o->handler_), ec,
92f5a8d4 274 BOOST_ASIO_MOVE_CAST(peer_socket_type)(o->peer_));
b32b8144
FG
275 p.h = boost::asio::detail::addressof(handler.handler_);
276 p.reset();
277
278 // Make the upcall if required.
279 if (owner)
280 {
281 fenced_block b(fenced_block::half);
282 BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
283 w.complete(handler, handler.handler_);
284 BOOST_ASIO_HANDLER_INVOCATION_END;
285 }
286 }
287
288private:
92f5a8d4
TL
289 typedef typename Protocol::socket::template
290 rebind_executor<PeerIoExecutor>::other peer_socket_type;
291
b32b8144
FG
292 win_iocp_socket_service_base& socket_service_;
293 socket_type socket_;
294 socket_holder new_socket_;
92f5a8d4 295 peer_socket_type peer_;
b32b8144
FG
296 Protocol protocol_;
297 typename Protocol::endpoint* peer_endpoint_;
298 unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
299 bool enable_connection_aborted_;
300 Handler handler_;
20effc67 301 handler_work<Handler, IoExecutor> work_;
b32b8144
FG
302};
303
304#endif // defined(BOOST_ASIO_HAS_MOVE)
305
7c673cae
FG
306} // namespace detail
307} // namespace asio
308} // namespace boost
309
310#include <boost/asio/detail/pop_options.hpp>
311
312#endif // defined(BOOST_ASIO_HAS_IOCP)
313
314#endif // BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP