Home | History | Annotate | Download | only in detail
      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