• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
reactive_socket_accept_op_base(socket_type socket,socket_ops::state_type state,Socket & peer,const Protocol & protocol,typename Protocol::endpoint * peer_endpoint,func_type complete_func)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 
do_perform(reactor_op * base)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 
reactive_socket_accept_op(socket_type socket,socket_ops::state_type state,Socket & peer,const Protocol & protocol,typename Protocol::endpoint * peer_endpoint,Handler & handler)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 
do_complete(io_service_impl * owner,operation * base,const asio::error_code &,std::size_t)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