diff options
Diffstat (limited to 'boost/asio/detail/reactive_socket_service.hpp')
-rw-r--r-- | boost/asio/detail/reactive_socket_service.hpp | 128 |
1 files changed, 98 insertions, 30 deletions
diff --git a/boost/asio/detail/reactive_socket_service.hpp b/boost/asio/detail/reactive_socket_service.hpp index d5a6e08eab..186cf35336 100644 --- a/boost/asio/detail/reactive_socket_service.hpp +++ b/boost/asio/detail/reactive_socket_service.hpp @@ -21,10 +21,10 @@ #include <boost/asio/buffer.hpp> #include <boost/asio/error.hpp> -#include <boost/asio/io_service.hpp> +#include <boost/asio/io_context.hpp> #include <boost/asio/socket_base.hpp> -#include <boost/asio/detail/addressof.hpp> #include <boost/asio/detail/buffer_sequence_adapter.hpp> +#include <boost/asio/detail/memory.hpp> #include <boost/asio/detail/noncopyable.hpp> #include <boost/asio/detail/reactive_null_buffers_op.hpp> #include <boost/asio/detail/reactive_socket_accept_op.hpp> @@ -46,6 +46,7 @@ namespace detail { template <typename Protocol> class reactive_socket_service : + public service_base<reactive_socket_service<Protocol> >, public reactive_socket_service_base { public: @@ -73,11 +74,18 @@ public: }; // Constructor. - reactive_socket_service(boost::asio::io_service& io_service) - : reactive_socket_service_base(io_service) + reactive_socket_service(boost::asio::io_context& io_context) + : service_base<reactive_socket_service<Protocol> >(io_context), + reactive_socket_service_base(io_context) { } + // Destroy all user-defined handler objects owned by the service. + void shutdown() + { + this->base_shutdown(); + } + // Move-construct a new socket implementation. void move_construct(implementation_type& impl, implementation_type& other_impl) @@ -196,6 +204,14 @@ public: return endpoint; } + // Disable sends or receives on the socket. + boost::system::error_code shutdown(base_implementation_type& impl, + socket_base::shutdown_type what, boost::system::error_code& ec) + { + socket_ops::shutdown(impl.socket_, what, ec); + return ec; + } + // Send a datagram to the specified endpoint. Returns the number of bytes // sent. template <typename ConstBufferSequence> @@ -217,7 +233,7 @@ public: boost::system::error_code& ec) { // Wait for socket to become ready. - socket_ops::poll_write(impl.socket_, impl.state_, ec); + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); return 0; } @@ -237,11 +253,11 @@ public: typedef reactive_socket_sendto_op<ConstBufferSequence, endpoint_type, Handler> op; typename op::ptr p = { boost::asio::detail::addressof(handler), - boost_asio_handler_alloc_helpers::allocate( - sizeof(op), handler), 0 }; + op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler); - BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to")); + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send_to")); start_op(impl, reactor::write_op, p.p, is_continuation, true, false); p.v = p.p = 0; @@ -258,12 +274,11 @@ public: // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler> op; typename op::ptr p = { boost::asio::detail::addressof(handler), - boost_asio_handler_alloc_helpers::allocate( - sizeof(op), handler), 0 }; + op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(handler); - BOOST_ASIO_HANDLER_CREATION((p.p, "socket", - &impl, "async_send_to(null_buffers)")); + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send_to(null_buffers)")); start_op(impl, reactor::write_op, p.p, is_continuation, false, false); p.v = p.p = 0; @@ -297,7 +312,7 @@ public: boost::system::error_code& ec) { // Wait for socket to become ready. - socket_ops::poll_read(impl.socket_, impl.state_, ec); + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); // Reset endpoint since it can be given no sensible value at this time. sender_endpoint = endpoint_type(); @@ -320,14 +335,13 @@ public: typedef reactive_socket_recvfrom_op<MutableBufferSequence, endpoint_type, Handler> op; typename op::ptr p = { boost::asio::detail::addressof(handler), - boost_asio_handler_alloc_helpers::allocate( - sizeof(op), handler), 0 }; + op::ptr::allocate(handler), 0 }; int protocol = impl.protocol_.type(); p.p = new (p.v) op(impl.socket_, protocol, buffers, sender_endpoint, flags, handler); - BOOST_ASIO_HANDLER_CREATION((p.p, "socket", - &impl, "async_receive_from")); + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_from")); start_op(impl, (flags & socket_base::message_out_of_band) @@ -348,12 +362,11 @@ public: // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler> op; typename op::ptr p = { boost::asio::detail::addressof(handler), - boost_asio_handler_alloc_helpers::allocate( - sizeof(op), handler), 0 }; + op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(handler); - BOOST_ASIO_HANDLER_CREATION((p.p, "socket", - &impl, "async_receive_from(null_buffers)")); + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_from(null_buffers)")); // Reset endpoint since it can be given no sensible value at this time. sender_endpoint = endpoint_type(); @@ -387,15 +400,44 @@ public: { if (peer_endpoint) peer_endpoint->resize(addr_len); - if (!peer.assign(impl.protocol_, new_socket.get(), ec)) + peer.assign(impl.protocol_, new_socket.get(), ec); + if (!ec) new_socket.release(); } return ec; } - // Start an asynchronous accept. The peer and peer_endpoint objects - // must be valid until the accept's handler is invoked. +#if defined(BOOST_ASIO_HAS_MOVE) + // Accept a new connection. + typename Protocol::socket accept(implementation_type& impl, + io_context* peer_io_context, endpoint_type* peer_endpoint, + boost::system::error_code& ec) + { + typename Protocol::socket peer( + peer_io_context ? *peer_io_context : io_context_); + + std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; + socket_holder new_socket(socket_ops::sync_accept(impl.socket_, + impl.state_, peer_endpoint ? peer_endpoint->data() : 0, + peer_endpoint ? &addr_len : 0, ec)); + + // On success, assign new connection to peer socket object. + if (new_socket.get() != invalid_socket) + { + if (peer_endpoint) + peer_endpoint->resize(addr_len); + peer.assign(impl.protocol_, new_socket.get(), ec); + if (!ec) + new_socket.release(); + } + + return peer; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + + // Start an asynchronous accept. The peer and peer_endpoint objects must be + // valid until the accept's handler is invoked. template <typename Socket, typename Handler> void async_accept(implementation_type& impl, Socket& peer, endpoint_type* peer_endpoint, Handler& handler) @@ -406,17 +448,43 @@ public: // Allocate and construct an operation to wrap the handler. typedef reactive_socket_accept_op<Socket, Protocol, Handler> op; typename op::ptr p = { boost::asio::detail::addressof(handler), - boost_asio_handler_alloc_helpers::allocate( - sizeof(op), handler), 0 }; + op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(impl.socket_, impl.state_, peer, impl.protocol_, peer_endpoint, handler); - BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept")); + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_accept")); start_accept_op(impl, p.p, is_continuation, peer.is_open()); p.v = p.p = 0; } +#if defined(BOOST_ASIO_HAS_MOVE) + // Start an asynchronous accept. The peer_endpoint object must be valid until + // the accept's handler is invoked. + template <typename Handler> + void async_accept(implementation_type& impl, + boost::asio::io_context* peer_io_context, + endpoint_type* peer_endpoint, Handler& handler) + { + bool is_continuation = + boost_asio_handler_cont_helpers::is_continuation(handler); + + // Allocate and construct an operation to wrap the handler. + typedef reactive_socket_move_accept_op<Protocol, Handler> op; + typename op::ptr p = { boost::asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(peer_io_context ? *peer_io_context : io_context_, + impl.socket_, impl.state_, impl.protocol_, peer_endpoint, handler); + + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_accept")); + + start_accept_op(impl, p.p, is_continuation, false); + p.v = p.p = 0; + } +#endif // defined(BOOST_ASIO_HAS_MOVE) + // Connect the socket to the specified endpoint. boost::system::error_code connect(implementation_type& impl, const endpoint_type& peer_endpoint, boost::system::error_code& ec) @@ -437,11 +505,11 @@ public: // Allocate and construct an operation to wrap the handler. typedef reactive_socket_connect_op<Handler> op; typename op::ptr p = { boost::asio::detail::addressof(handler), - boost_asio_handler_alloc_helpers::allocate( - sizeof(op), handler), 0 }; + op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(impl.socket_, handler); - BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect")); + BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", + &impl, impl.socket_, "async_connect")); start_connect_op(impl, p.p, is_continuation, peer_endpoint.data(), peer_endpoint.size()); |