1 // 2 // detail/reactive_socket_accept_op.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2015 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 ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP 12 #define ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP 13 14 15 #include "asio/detail/config.hpp" 16 #include "asio/detail/addressof.hpp" 17 #include "asio/detail/bind_handler.hpp" 18 #include "asio/detail/buffer_sequence_adapter.hpp" 19 #include "asio/detail/fenced_block.hpp" 20 #include "asio/detail/reactor_op.hpp" 21 #include "asio/detail/socket_holder.hpp" 22 #include "asio/detail/socket_ops.hpp" 23 24 #include "asio/detail/push_options.hpp" 25 26 namespace asio { 27 namespace detail { 28 29 template <typename Socket, typename Protocol> 30 class reactive_socket_accept_op_base : public reactor_op 31 { 32 public: 33 reactive_socket_accept_op_base(socket_type socket, 34 socket_ops::state_type state, Socket& peer, const Protocol& protocol, 35 typename Protocol::endpoint* peer_endpoint, func_type complete_func) 36 : reactor_op(&reactive_socket_accept_op_base::do_perform, complete_func), 37 socket_(socket), 38 state_(state), 39 peer_(peer), 40 protocol_(protocol), 41 peer_endpoint_(peer_endpoint) 42 { 43 } 44 45 static bool do_perform(reactor_op* base) 46 { 47 reactive_socket_accept_op_base* o( 48 static_cast<reactive_socket_accept_op_base*>(base)); 49 50 std::size_t addrlen = o->peer_endpoint_ ? o->peer_endpoint_->capacity() : 0; 51 socket_type new_socket = invalid_socket; 52 bool result = socket_ops::non_blocking_accept(o->socket_, 53 o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0, 54 o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket); 55 56 // On success, assign new connection to peer socket object. 57 if (new_socket != invalid_socket) 58 { 59 socket_holder new_socket_holder(new_socket); 60 if (o->peer_endpoint_) 61 o->peer_endpoint_->resize(addrlen); 62 if (!o->peer_.assign(o->protocol_, new_socket, o->ec_)) 63 new_socket_holder.release(); 64 } 65 66 return result; 67 } 68 69 private: 70 socket_type socket_; 71 socket_ops::state_type state_; 72 Socket& peer_; 73 Protocol protocol_; 74 typename Protocol::endpoint* peer_endpoint_; 75 }; 76 77 template <typename Socket, typename Protocol, typename Handler> 78 class reactive_socket_accept_op : 79 public reactive_socket_accept_op_base<Socket, Protocol> 80 { 81 public: 82 ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op); 83 84 reactive_socket_accept_op(socket_type socket, 85 socket_ops::state_type state, Socket& peer, const Protocol& protocol, 86 typename Protocol::endpoint* peer_endpoint, Handler& handler) 87 : reactive_socket_accept_op_base<Socket, Protocol>(socket, state, peer, 88 protocol, peer_endpoint, &reactive_socket_accept_op::do_complete), 89 handler_(ASIO_MOVE_CAST(Handler)(handler)) 90 { 91 } 92 93 static void do_complete(io_service_impl* owner, operation* base, 94 const asio::error_code& /*ec*/, 95 std::size_t /*bytes_transferred*/) 96 { 97 // Take ownership of the handler object. 98 reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base)); 99 ptr p = { asio::detail::addressof(o->handler_), o, o }; 100 101 ASIO_HANDLER_COMPLETION((o)); 102 103 // Make a copy of the handler so that the memory can be deallocated before 104 // the upcall is made. Even if we're not about to make an upcall, a 105 // sub-object of the handler may be the true owner of the memory associated 106 // with the handler. Consequently, a local copy of the handler is required 107 // to ensure that any owning sub-object remains valid until after we have 108 // deallocated the memory here. 109 detail::binder1<Handler, asio::error_code> 110 handler(o->handler_, o->ec_); 111 p.h = asio::detail::addressof(handler.handler_); 112 p.reset(); 113 114 // Make the upcall if required. 115 if (owner) 116 { 117 fenced_block b(fenced_block::half); 118 ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); 119 asio_handler_invoke_helpers::invoke(handler, handler.handler_); 120 ASIO_HANDLER_INVOCATION_END; 121 } 122 } 123 124 private: 125 Handler handler_; 126 }; 127 128 } // namespace detail 129 } // namespace asio 130 131 #include "asio/detail/pop_options.hpp" 132 133 #endif // ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP 134