2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
11 #define BOOST_BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
13 #include <boost/beast/core/bind_handler.hpp>
14 #include <boost/beast/core/type_traits.hpp>
15 #include <boost/asio/associated_allocator.hpp>
16 #include <boost/asio/associated_executor.hpp>
17 #include <boost/asio/handler_continuation_hook.hpp>
18 #include <boost/asio/post.hpp>
27 template<class Handler>
31 boost::asio::ip::tcp::socket;
39 teardown_tcp_op(teardown_tcp_op&& other) = default;
40 teardown_tcp_op(teardown_tcp_op const& other) = default;
42 template<class DeducedHandler>
47 : h_(std::forward<DeducedHandler>(h))
53 using allocator_type =
54 boost::asio::associated_allocator_t<Handler>;
57 get_allocator() const noexcept
59 return boost::asio::get_associated_allocator(h_);
62 using executor_type = boost::asio::associated_executor_t<
63 Handler, decltype(std::declval<socket_type&>().get_executor())>;
66 get_executor() const noexcept
68 return boost::asio::get_associated_executor(
69 h_, s_.get_executor());
75 std::size_t bytes_transferred = 0);
78 bool asio_handler_is_continuation(teardown_tcp_op* op)
80 using boost::asio::asio_handler_is_continuation;
81 return op->step_ >= 3 ||
82 asio_handler_is_continuation(std::addressof(op->h_));
86 template<class Handler>
88 teardown_tcp_op<Handler>::
89 operator()(error_code ec, std::size_t)
91 using boost::asio::buffer;
92 using tcp = boost::asio::ip::tcp;
96 s_.non_blocking(true, ec);
100 return boost::asio::post(
102 bind_handler(std::move(*this), ec, 0));
105 if(role_ == role_type::server)
106 s_.shutdown(tcp::socket::shutdown_send, ec);
116 if(ec != boost::asio::error::would_block)
121 boost::asio::buffer(buf), ec);
127 return s_.async_read_some(
128 boost::asio::null_buffers{},
131 if(role_ == role_type::client)
132 s_.shutdown(tcp::socket::shutdown_send, ec);
139 //------------------------------------------------------------------------------
145 boost::asio::ip::tcp::socket& socket,
148 using boost::asio::buffer;
149 if(role == role_type::server)
151 boost::asio::ip::tcp::socket::shutdown_send, ec);
155 auto const n = socket.read_some(
160 if(role == role_type::client)
162 boost::asio::ip::tcp::socket::shutdown_send, ec);
166 template<class TeardownHandler>
171 boost::asio::ip::tcp::socket& socket,
172 TeardownHandler&& handler)
174 static_assert(beast::is_completion_handler<
175 TeardownHandler, void(error_code)>::value,
176 "TeardownHandler requirements not met");
177 detail::teardown_tcp_op<typename std::decay<
178 TeardownHandler>::type>{std::forward<
179 TeardownHandler>(handler), socket,