10ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
20ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// detail/reactive_socket_accept_op.hpp
30ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
40ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
50ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
60ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
70ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// Distributed under the Boost Software License, Version 1.0. (See accompanying
80ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
90ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie//
100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#ifndef ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#define ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/config.hpp"
160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/addressof.hpp"
170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/bind_handler.hpp"
180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/buffer_sequence_adapter.hpp"
190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/fenced_block.hpp"
200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/reactor_op.hpp"
210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/socket_holder.hpp"
220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/socket_ops.hpp"
230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/push_options.hpp"
250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace asio {
270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffienamespace detail {
280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename Socket, typename Protocol>
300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieclass reactive_socket_accept_op_base : public reactor_op
310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiepublic:
330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  reactive_socket_accept_op_base(socket_type socket,
340ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      socket_ops::state_type state, Socket& peer, const Protocol& protocol,
350ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename Protocol::endpoint* peer_endpoint, func_type complete_func)
360ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : reactor_op(&reactive_socket_accept_op_base::do_perform, complete_func),
370ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      socket_(socket),
380ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      state_(state),
390ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      peer_(peer),
400ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      protocol_(protocol),
410ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      peer_endpoint_(peer_endpoint)
420ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
430ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
440ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
450ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static bool do_perform(reactor_op* base)
460ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
470ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    reactive_socket_accept_op_base* o(
480ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        static_cast<reactive_socket_accept_op_base*>(base));
490ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
500ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    std::size_t addrlen = o->peer_endpoint_ ? o->peer_endpoint_->capacity() : 0;
510ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    socket_type new_socket = invalid_socket;
520ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    bool result = socket_ops::non_blocking_accept(o->socket_,
530ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,
540ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie          o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket);
550ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
560ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // On success, assign new connection to peer socket object.
570ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    if (new_socket != invalid_socket)
580ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
590ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      socket_holder new_socket_holder(new_socket);
600ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      if (o->peer_endpoint_)
610ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        o->peer_endpoint_->resize(addrlen);
620ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      if (!o->peer_.assign(o->protocol_, new_socket, o->ec_))
630ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        new_socket_holder.release();
640ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
650ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
660ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    return result;
670ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
680ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
690ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieprivate:
700ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  socket_type socket_;
710ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  socket_ops::state_type state_;
720ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  Socket& peer_;
730ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  Protocol protocol_;
740ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  typename Protocol::endpoint* peer_endpoint_;
750ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie};
760ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
770ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffietemplate <typename Socket, typename Protocol, typename Handler>
780ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieclass reactive_socket_accept_op :
790ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  public reactive_socket_accept_op_base<Socket, Protocol>
800ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie{
810ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffiepublic:
820ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op);
830ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
840ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  reactive_socket_accept_op(socket_type socket,
850ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      socket_ops::state_type state, Socket& peer, const Protocol& protocol,
860ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      typename Protocol::endpoint* peer_endpoint, Handler& handler)
870ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    : reactive_socket_accept_op_base<Socket, Protocol>(socket, state, peer,
880ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie        protocol, peer_endpoint, &reactive_socket_accept_op::do_complete),
890ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      handler_(ASIO_MOVE_CAST(Handler)(handler))
900ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
910ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
920ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
930ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  static void do_complete(io_service_impl* owner, operation* base,
940ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      const asio::error_code& /*ec*/,
950ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      std::size_t /*bytes_transferred*/)
960ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  {
970ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // Take ownership of the handler object.
980ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));
990ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ptr p = { asio::detail::addressof(o->handler_), o, o };
1000ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1010ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    ASIO_HANDLER_COMPLETION((o));
1020ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1030ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // Make a copy of the handler so that the memory can be deallocated before
1040ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // the upcall is made. Even if we're not about to make an upcall, a
1050ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // sub-object of the handler may be the true owner of the memory associated
1060ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // with the handler. Consequently, a local copy of the handler is required
1070ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // to ensure that any owning sub-object remains valid until after we have
1080ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // deallocated the memory here.
1090ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    detail::binder1<Handler, asio::error_code>
1100ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      handler(o->handler_, o->ec_);
1110ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    p.h = asio::detail::addressof(handler.handler_);
1120ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    p.reset();
1130ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1140ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    // Make the upcall if required.
1150ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    if (owner)
1160ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    {
1170ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      fenced_block b(fenced_block::half);
1180ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
1190ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
1200ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie      ASIO_HANDLER_INVOCATION_END;
1210ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie    }
1220ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  }
1230ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1240ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffieprivate:
1250ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie  Handler handler_;
1260ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie};
1270ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1280ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace detail
1290ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie} // namespace asio
1300ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1310ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#include "asio/detail/pop_options.hpp"
1320ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie
1330ee85db398be8ea33d67cc42f99a1468cd6c8180François Gaffie#endif // ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
134