]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // detail/reactive_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_REACTIVE_SOCKET_ACCEPT_OP_HPP | |
12 | #define BOOST_ASIO_DETAIL_REACTIVE_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> | |
7c673cae | 19 | #include <boost/asio/detail/bind_handler.hpp> |
7c673cae | 20 | #include <boost/asio/detail/fenced_block.hpp> |
20effc67 TL |
21 | #include <boost/asio/detail/handler_alloc_helpers.hpp> |
22 | #include <boost/asio/detail/handler_invoke_helpers.hpp> | |
23 | #include <boost/asio/detail/handler_work.hpp> | |
b32b8144 | 24 | #include <boost/asio/detail/memory.hpp> |
7c673cae FG |
25 | #include <boost/asio/detail/reactor_op.hpp> |
26 | #include <boost/asio/detail/socket_holder.hpp> | |
27 | #include <boost/asio/detail/socket_ops.hpp> | |
28 | ||
29 | #include <boost/asio/detail/push_options.hpp> | |
30 | ||
31 | namespace boost { | |
32 | namespace asio { | |
33 | namespace detail { | |
34 | ||
35 | template <typename Socket, typename Protocol> | |
36 | class reactive_socket_accept_op_base : public reactor_op | |
37 | { | |
38 | public: | |
20effc67 TL |
39 | reactive_socket_accept_op_base(const boost::system::error_code& success_ec, |
40 | socket_type socket, socket_ops::state_type state, Socket& peer, | |
41 | const Protocol& protocol, typename Protocol::endpoint* peer_endpoint, | |
42 | func_type complete_func) | |
43 | : reactor_op(success_ec, | |
44 | &reactive_socket_accept_op_base::do_perform, complete_func), | |
7c673cae FG |
45 | socket_(socket), |
46 | state_(state), | |
47 | peer_(peer), | |
48 | protocol_(protocol), | |
b32b8144 FG |
49 | peer_endpoint_(peer_endpoint), |
50 | addrlen_(peer_endpoint ? peer_endpoint->capacity() : 0) | |
7c673cae FG |
51 | { |
52 | } | |
53 | ||
b32b8144 | 54 | static status do_perform(reactor_op* base) |
7c673cae FG |
55 | { |
56 | reactive_socket_accept_op_base* o( | |
57 | static_cast<reactive_socket_accept_op_base*>(base)); | |
58 | ||
7c673cae | 59 | socket_type new_socket = invalid_socket; |
b32b8144 FG |
60 | status result = socket_ops::non_blocking_accept(o->socket_, |
61 | o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0, | |
62 | o->peer_endpoint_ ? &o->addrlen_ : 0, o->ec_, new_socket) | |
63 | ? done : not_done; | |
64 | o->new_socket_.reset(new_socket); | |
7c673cae | 65 | |
b32b8144 | 66 | BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_accept", o->ec_)); |
7c673cae FG |
67 | |
68 | return result; | |
69 | } | |
70 | ||
b32b8144 FG |
71 | void do_assign() |
72 | { | |
73 | if (new_socket_.get() != invalid_socket) | |
74 | { | |
75 | if (peer_endpoint_) | |
76 | peer_endpoint_->resize(addrlen_); | |
77 | peer_.assign(protocol_, new_socket_.get(), ec_); | |
78 | if (!ec_) | |
79 | new_socket_.release(); | |
80 | } | |
81 | } | |
82 | ||
7c673cae FG |
83 | private: |
84 | socket_type socket_; | |
85 | socket_ops::state_type state_; | |
b32b8144 | 86 | socket_holder new_socket_; |
7c673cae FG |
87 | Socket& peer_; |
88 | Protocol protocol_; | |
89 | typename Protocol::endpoint* peer_endpoint_; | |
b32b8144 | 90 | std::size_t addrlen_; |
7c673cae FG |
91 | }; |
92 | ||
92f5a8d4 TL |
93 | template <typename Socket, typename Protocol, |
94 | typename Handler, typename IoExecutor> | |
7c673cae FG |
95 | class reactive_socket_accept_op : |
96 | public reactive_socket_accept_op_base<Socket, Protocol> | |
97 | { | |
98 | public: | |
99 | BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op); | |
100 | ||
20effc67 TL |
101 | reactive_socket_accept_op(const boost::system::error_code& success_ec, |
102 | socket_type socket, socket_ops::state_type state, Socket& peer, | |
103 | const Protocol& protocol, typename Protocol::endpoint* peer_endpoint, | |
104 | Handler& handler, const IoExecutor& io_ex) | |
105 | : reactive_socket_accept_op_base<Socket, Protocol>( | |
106 | success_ec, socket, state, peer, protocol, peer_endpoint, | |
107 | &reactive_socket_accept_op::do_complete), | |
92f5a8d4 | 108 | handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), |
20effc67 | 109 | work_(handler_, io_ex) |
7c673cae FG |
110 | { |
111 | } | |
112 | ||
b32b8144 | 113 | static void do_complete(void* owner, operation* base, |
7c673cae FG |
114 | const boost::system::error_code& /*ec*/, |
115 | std::size_t /*bytes_transferred*/) | |
116 | { | |
117 | // Take ownership of the handler object. | |
118 | reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base)); | |
119 | ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; | |
b32b8144 FG |
120 | |
121 | // On success, assign new connection to peer socket object. | |
122 | if (owner) | |
123 | o->do_assign(); | |
7c673cae | 124 | |
b32b8144 | 125 | BOOST_ASIO_HANDLER_COMPLETION((*o)); |
7c673cae | 126 | |
20effc67 TL |
127 | // Take ownership of the operation's outstanding work. |
128 | handler_work<Handler, IoExecutor> w( | |
129 | BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( | |
130 | o->work_)); | |
131 | ||
7c673cae FG |
132 | // Make a copy of the handler so that the memory can be deallocated before |
133 | // the upcall is made. Even if we're not about to make an upcall, a | |
134 | // sub-object of the handler may be the true owner of the memory associated | |
135 | // with the handler. Consequently, a local copy of the handler is required | |
136 | // to ensure that any owning sub-object remains valid until after we have | |
137 | // deallocated the memory here. | |
138 | detail::binder1<Handler, boost::system::error_code> | |
139 | handler(o->handler_, o->ec_); | |
140 | p.h = boost::asio::detail::addressof(handler.handler_); | |
141 | p.reset(); | |
142 | ||
143 | // Make the upcall if required. | |
144 | if (owner) | |
145 | { | |
146 | fenced_block b(fenced_block::half); | |
147 | BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); | |
b32b8144 FG |
148 | w.complete(handler, handler.handler_); |
149 | BOOST_ASIO_HANDLER_INVOCATION_END; | |
150 | } | |
151 | } | |
152 | ||
153 | private: | |
154 | Handler handler_; | |
20effc67 | 155 | handler_work<Handler, IoExecutor> work_; |
b32b8144 FG |
156 | }; |
157 | ||
158 | #if defined(BOOST_ASIO_HAS_MOVE) | |
159 | ||
92f5a8d4 TL |
160 | template <typename Protocol, typename PeerIoExecutor, |
161 | typename Handler, typename IoExecutor> | |
b32b8144 | 162 | class reactive_socket_move_accept_op : |
92f5a8d4 TL |
163 | private Protocol::socket::template rebind_executor<PeerIoExecutor>::other, |
164 | public reactive_socket_accept_op_base< | |
165 | typename Protocol::socket::template rebind_executor<PeerIoExecutor>::other, | |
166 | Protocol> | |
b32b8144 FG |
167 | { |
168 | public: | |
169 | BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op); | |
170 | ||
20effc67 TL |
171 | reactive_socket_move_accept_op(const boost::system::error_code& success_ec, |
172 | const PeerIoExecutor& peer_io_ex, socket_type socket, | |
173 | socket_ops::state_type state, const Protocol& protocol, | |
174 | typename Protocol::endpoint* peer_endpoint, Handler& handler, | |
175 | const IoExecutor& io_ex) | |
92f5a8d4 TL |
176 | : peer_socket_type(peer_io_ex), |
177 | reactive_socket_accept_op_base<peer_socket_type, Protocol>( | |
20effc67 | 178 | success_ec, socket, state, *this, protocol, peer_endpoint, |
b32b8144 | 179 | &reactive_socket_move_accept_op::do_complete), |
92f5a8d4 | 180 | handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)), |
20effc67 | 181 | work_(handler_, io_ex) |
b32b8144 | 182 | { |
b32b8144 FG |
183 | } |
184 | ||
185 | static void do_complete(void* owner, operation* base, | |
186 | const boost::system::error_code& /*ec*/, | |
187 | std::size_t /*bytes_transferred*/) | |
188 | { | |
189 | // Take ownership of the handler object. | |
190 | reactive_socket_move_accept_op* o( | |
191 | static_cast<reactive_socket_move_accept_op*>(base)); | |
192 | ptr p = { boost::asio::detail::addressof(o->handler_), o, o }; | |
b32b8144 FG |
193 | |
194 | // On success, assign new connection to peer socket object. | |
195 | if (owner) | |
196 | o->do_assign(); | |
197 | ||
198 | BOOST_ASIO_HANDLER_COMPLETION((*o)); | |
199 | ||
20effc67 TL |
200 | // Take ownership of the operation's outstanding work. |
201 | handler_work<Handler, IoExecutor> w( | |
202 | BOOST_ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( | |
203 | o->work_)); | |
204 | ||
b32b8144 FG |
205 | // Make a copy of the handler so that the memory can be deallocated before |
206 | // the upcall is made. Even if we're not about to make an upcall, a | |
207 | // sub-object of the handler may be the true owner of the memory associated | |
208 | // with the handler. Consequently, a local copy of the handler is required | |
209 | // to ensure that any owning sub-object remains valid until after we have | |
210 | // deallocated the memory here. | |
211 | detail::move_binder2<Handler, | |
92f5a8d4 | 212 | boost::system::error_code, peer_socket_type> |
b32b8144 | 213 | handler(0, BOOST_ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_, |
92f5a8d4 | 214 | BOOST_ASIO_MOVE_CAST(peer_socket_type)(*o)); |
b32b8144 FG |
215 | p.h = boost::asio::detail::addressof(handler.handler_); |
216 | p.reset(); | |
217 | ||
218 | // Make the upcall if required. | |
219 | if (owner) | |
220 | { | |
221 | fenced_block b(fenced_block::half); | |
222 | BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "...")); | |
223 | w.complete(handler, handler.handler_); | |
7c673cae FG |
224 | BOOST_ASIO_HANDLER_INVOCATION_END; |
225 | } | |
226 | } | |
227 | ||
228 | private: | |
92f5a8d4 TL |
229 | typedef typename Protocol::socket::template |
230 | rebind_executor<PeerIoExecutor>::other peer_socket_type; | |
231 | ||
7c673cae | 232 | Handler handler_; |
20effc67 | 233 | handler_work<Handler, IoExecutor> work_; |
7c673cae FG |
234 | }; |
235 | ||
b32b8144 FG |
236 | #endif // defined(BOOST_ASIO_HAS_MOVE) |
237 | ||
7c673cae FG |
238 | } // namespace detail |
239 | } // namespace asio | |
240 | } // namespace boost | |
241 | ||
242 | #include <boost/asio/detail/pop_options.hpp> | |
243 | ||
244 | #endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP |