Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:46

0001 //
0002 // detail/win_iocp_socket_accept_op.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP
0012 #define BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if defined(BOOST_ASIO_HAS_IOCP)
0021 
0022 #include <boost/asio/detail/bind_handler.hpp>
0023 #include <boost/asio/detail/fenced_block.hpp>
0024 #include <boost/asio/detail/handler_alloc_helpers.hpp>
0025 #include <boost/asio/detail/handler_work.hpp>
0026 #include <boost/asio/detail/memory.hpp>
0027 #include <boost/asio/detail/operation.hpp>
0028 #include <boost/asio/detail/socket_ops.hpp>
0029 #include <boost/asio/detail/win_iocp_socket_service_base.hpp>
0030 #include <boost/asio/error.hpp>
0031 
0032 #include <boost/asio/detail/push_options.hpp>
0033 
0034 namespace boost {
0035 namespace asio {
0036 namespace detail {
0037 
0038 template <typename Socket, typename Protocol,
0039     typename Handler, typename IoExecutor>
0040 class win_iocp_socket_accept_op : public operation
0041 {
0042 public:
0043   BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_accept_op);
0044 
0045   win_iocp_socket_accept_op(win_iocp_socket_service_base& socket_service,
0046       socket_type socket, Socket& peer, const Protocol& protocol,
0047       typename Protocol::endpoint* peer_endpoint,
0048       bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex)
0049     : operation(&win_iocp_socket_accept_op::do_complete),
0050       socket_service_(socket_service),
0051       socket_(socket),
0052       peer_(peer),
0053       protocol_(protocol),
0054       peer_endpoint_(peer_endpoint),
0055       enable_connection_aborted_(enable_connection_aborted),
0056       proxy_op_(0),
0057       cancel_requested_(0),
0058       handler_(static_cast<Handler&&>(handler)),
0059       work_(handler_, io_ex)
0060   {
0061   }
0062 
0063   socket_holder& new_socket()
0064   {
0065     return new_socket_;
0066   }
0067 
0068   void* output_buffer()
0069   {
0070     return output_buffer_;
0071   }
0072 
0073   DWORD address_length()
0074   {
0075     return sizeof(sockaddr_storage_type) + 16;
0076   }
0077 
0078   void enable_cancellation(long* cancel_requested, operation* proxy_op)
0079   {
0080     cancel_requested_ = cancel_requested;
0081     proxy_op_ = proxy_op;
0082   }
0083 
0084   static void do_complete(void* owner, operation* base,
0085       const boost::system::error_code& result_ec,
0086       std::size_t /*bytes_transferred*/)
0087   {
0088     boost::system::error_code ec(result_ec);
0089 
0090     // Take ownership of the operation object.
0091     BOOST_ASIO_ASSUME(base != 0);
0092     win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base));
0093     ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
0094 
0095     if (owner)
0096     {
0097       typename Protocol::endpoint peer_endpoint;
0098       std::size_t addr_len = peer_endpoint.capacity();
0099       socket_ops::complete_iocp_accept(o->socket_,
0100           o->output_buffer(), o->address_length(),
0101           peer_endpoint.data(), &addr_len,
0102           o->new_socket_.get(), ec);
0103 
0104       // Restart the accept operation if we got the connection_aborted error
0105       // and the enable_connection_aborted socket option is not set.
0106       if (ec == boost::asio::error::connection_aborted
0107           && !o->enable_connection_aborted_)
0108       {
0109         o->reset();
0110         if (o->proxy_op_)
0111           o->proxy_op_->reset();
0112         o->socket_service_.restart_accept_op(o->socket_,
0113             o->new_socket_, o->protocol_.family(),
0114             o->protocol_.type(), o->protocol_.protocol(),
0115             o->output_buffer(), o->address_length(),
0116             o->cancel_requested_, o->proxy_op_ ? o->proxy_op_ : o);
0117         p.v = p.p = 0;
0118         return;
0119       }
0120 
0121       // If the socket was successfully accepted, transfer ownership of the
0122       // socket to the peer object.
0123       if (!ec)
0124       {
0125         o->peer_.assign(o->protocol_,
0126             typename Socket::native_handle_type(
0127               o->new_socket_.get(), peer_endpoint), ec);
0128         if (!ec)
0129           o->new_socket_.release();
0130       }
0131 
0132       // Pass endpoint back to caller.
0133       if (o->peer_endpoint_)
0134         *o->peer_endpoint_ = peer_endpoint;
0135     }
0136 
0137     BOOST_ASIO_HANDLER_COMPLETION((*o));
0138 
0139     // Take ownership of the operation's outstanding work.
0140     handler_work<Handler, IoExecutor> w(
0141         static_cast<handler_work<Handler, IoExecutor>&&>(
0142           o->work_));
0143 
0144     BOOST_ASIO_ERROR_LOCATION(ec);
0145 
0146     // Make a copy of the handler so that the memory can be deallocated before
0147     // the upcall is made. Even if we're not about to make an upcall, a
0148     // sub-object of the handler may be the true owner of the memory associated
0149     // with the handler. Consequently, a local copy of the handler is required
0150     // to ensure that any owning sub-object remains valid until after we have
0151     // deallocated the memory here.
0152     detail::binder1<Handler, boost::system::error_code>
0153       handler(o->handler_, ec);
0154     p.h = boost::asio::detail::addressof(handler.handler_);
0155     p.reset();
0156 
0157     // Make the upcall if required.
0158     if (owner)
0159     {
0160       fenced_block b(fenced_block::half);
0161       BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
0162       w.complete(handler, handler.handler_);
0163       BOOST_ASIO_HANDLER_INVOCATION_END;
0164     }
0165   }
0166 
0167 private:
0168   win_iocp_socket_service_base& socket_service_;
0169   socket_type socket_;
0170   socket_holder new_socket_;
0171   Socket& peer_;
0172   Protocol protocol_;
0173   typename Protocol::endpoint* peer_endpoint_;
0174   unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
0175   bool enable_connection_aborted_;
0176   operation* proxy_op_;
0177   long* cancel_requested_;
0178   Handler handler_;
0179   handler_work<Handler, IoExecutor> work_;
0180 };
0181 
0182 template <typename Protocol, typename PeerIoExecutor,
0183     typename Handler, typename IoExecutor>
0184 class win_iocp_socket_move_accept_op : public operation
0185 {
0186 public:
0187   BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_move_accept_op);
0188 
0189   win_iocp_socket_move_accept_op(
0190       win_iocp_socket_service_base& socket_service, socket_type socket,
0191       const Protocol& protocol, const PeerIoExecutor& peer_io_ex,
0192       typename Protocol::endpoint* peer_endpoint,
0193       bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex)
0194     : operation(&win_iocp_socket_move_accept_op::do_complete),
0195       socket_service_(socket_service),
0196       socket_(socket),
0197       peer_(peer_io_ex),
0198       protocol_(protocol),
0199       peer_endpoint_(peer_endpoint),
0200       enable_connection_aborted_(enable_connection_aborted),
0201       cancel_requested_(0),
0202       proxy_op_(0),
0203       handler_(static_cast<Handler&&>(handler)),
0204       work_(handler_, io_ex)
0205   {
0206   }
0207 
0208   socket_holder& new_socket()
0209   {
0210     return new_socket_;
0211   }
0212 
0213   void* output_buffer()
0214   {
0215     return output_buffer_;
0216   }
0217 
0218   DWORD address_length()
0219   {
0220     return sizeof(sockaddr_storage_type) + 16;
0221   }
0222 
0223   void enable_cancellation(long* cancel_requested, operation* proxy_op)
0224   {
0225     cancel_requested_ = cancel_requested;
0226     proxy_op_ = proxy_op;
0227   }
0228 
0229   static void do_complete(void* owner, operation* base,
0230       const boost::system::error_code& result_ec,
0231       std::size_t /*bytes_transferred*/)
0232   {
0233     boost::system::error_code ec(result_ec);
0234 
0235     // Take ownership of the operation object.
0236     BOOST_ASIO_ASSUME(base != 0);
0237     win_iocp_socket_move_accept_op* o(
0238         static_cast<win_iocp_socket_move_accept_op*>(base));
0239     ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
0240 
0241     if (owner)
0242     {
0243       typename Protocol::endpoint peer_endpoint;
0244       std::size_t addr_len = peer_endpoint.capacity();
0245       socket_ops::complete_iocp_accept(o->socket_,
0246           o->output_buffer(), o->address_length(),
0247           peer_endpoint.data(), &addr_len,
0248           o->new_socket_.get(), ec);
0249 
0250       // Restart the accept operation if we got the connection_aborted error
0251       // and the enable_connection_aborted socket option is not set.
0252       if (ec == boost::asio::error::connection_aborted
0253           && !o->enable_connection_aborted_)
0254       {
0255         o->reset();
0256         if (o->proxy_op_)
0257           o->proxy_op_->reset();
0258         o->socket_service_.restart_accept_op(o->socket_,
0259             o->new_socket_, o->protocol_.family(),
0260             o->protocol_.type(), o->protocol_.protocol(),
0261             o->output_buffer(), o->address_length(),
0262             o->cancel_requested_, o->proxy_op_ ? o->proxy_op_ : o);
0263         p.v = p.p = 0;
0264         return;
0265       }
0266 
0267       // If the socket was successfully accepted, transfer ownership of the
0268       // socket to the peer object.
0269       if (!ec)
0270       {
0271         o->peer_.assign(o->protocol_,
0272             typename Protocol::socket::native_handle_type(
0273               o->new_socket_.get(), peer_endpoint), ec);
0274         if (!ec)
0275           o->new_socket_.release();
0276       }
0277 
0278       // Pass endpoint back to caller.
0279       if (o->peer_endpoint_)
0280         *o->peer_endpoint_ = peer_endpoint;
0281     }
0282 
0283     BOOST_ASIO_HANDLER_COMPLETION((*o));
0284 
0285     // Take ownership of the operation's outstanding work.
0286     handler_work<Handler, IoExecutor> w(
0287         static_cast<handler_work<Handler, IoExecutor>&&>(
0288           o->work_));
0289 
0290     BOOST_ASIO_ERROR_LOCATION(ec);
0291 
0292     // Make a copy of the handler so that the memory can be deallocated before
0293     // the upcall is made. Even if we're not about to make an upcall, a
0294     // sub-object of the handler may be the true owner of the memory associated
0295     // with the handler. Consequently, a local copy of the handler is required
0296     // to ensure that any owning sub-object remains valid until after we have
0297     // deallocated the memory here.
0298     detail::move_binder2<Handler,
0299       boost::system::error_code, peer_socket_type>
0300         handler(0, static_cast<Handler&&>(o->handler_), ec,
0301           static_cast<peer_socket_type&&>(o->peer_));
0302     p.h = boost::asio::detail::addressof(handler.handler_);
0303     p.reset();
0304 
0305     // Make the upcall if required.
0306     if (owner)
0307     {
0308       fenced_block b(fenced_block::half);
0309       BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
0310       w.complete(handler, handler.handler_);
0311       BOOST_ASIO_HANDLER_INVOCATION_END;
0312     }
0313   }
0314 
0315 private:
0316   typedef typename Protocol::socket::template
0317     rebind_executor<PeerIoExecutor>::other peer_socket_type;
0318 
0319   win_iocp_socket_service_base& socket_service_;
0320   socket_type socket_;
0321   socket_holder new_socket_;
0322   peer_socket_type peer_;
0323   Protocol protocol_;
0324   typename Protocol::endpoint* peer_endpoint_;
0325   unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
0326   bool enable_connection_aborted_;
0327   long* cancel_requested_;
0328   operation* proxy_op_;
0329   Handler handler_;
0330   handler_work<Handler, IoExecutor> work_;
0331 };
0332 
0333 } // namespace detail
0334 } // namespace asio
0335 } // namespace boost
0336 
0337 #include <boost/asio/detail/pop_options.hpp>
0338 
0339 #endif // defined(BOOST_ASIO_HAS_IOCP)
0340 
0341 #endif // BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP