]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/websocket/impl/teardown.ipp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / websocket / impl / teardown.ipp
1 //
2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
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)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
11 #define BOOST_BEAST_WEBSOCKET_IMPL_TEARDOWN_IPP
12
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>
19 #include <memory>
20
21 namespace boost {
22 namespace beast {
23 namespace websocket {
24
25 namespace detail {
26
27 template<class Handler>
28 class teardown_tcp_op
29 {
30 using socket_type =
31 boost::asio::ip::tcp::socket;
32
33 Handler h_;
34 socket_type& s_;
35 role_type role_;
36 int step_ = 0;
37
38 public:
39 teardown_tcp_op(teardown_tcp_op&& other) = default;
40 teardown_tcp_op(teardown_tcp_op const& other) = default;
41
42 template<class DeducedHandler>
43 teardown_tcp_op(
44 DeducedHandler&& h,
45 socket_type& s,
46 role_type role)
47 : h_(std::forward<DeducedHandler>(h))
48 , s_(s)
49 , role_(role)
50 {
51 }
52
53 using allocator_type =
54 boost::asio::associated_allocator_t<Handler>;
55
56 allocator_type
57 get_allocator() const noexcept
58 {
59 return boost::asio::get_associated_allocator(h_);
60 }
61
62 using executor_type = boost::asio::associated_executor_t<
63 Handler, decltype(std::declval<socket_type&>().get_executor())>;
64
65 executor_type
66 get_executor() const noexcept
67 {
68 return boost::asio::get_associated_executor(
69 h_, s_.get_executor());
70 }
71
72 void
73 operator()(
74 error_code ec = {},
75 std::size_t bytes_transferred = 0);
76
77 friend
78 bool asio_handler_is_continuation(teardown_tcp_op* op)
79 {
80 using boost::asio::asio_handler_is_continuation;
81 return op->step_ >= 3 ||
82 asio_handler_is_continuation(std::addressof(op->h_));
83 }
84 };
85
86 template<class Handler>
87 void
88 teardown_tcp_op<Handler>::
89 operator()(error_code ec, std::size_t)
90 {
91 using boost::asio::buffer;
92 using tcp = boost::asio::ip::tcp;
93 switch(step_)
94 {
95 case 0:
96 s_.non_blocking(true, ec);
97 if(ec)
98 {
99 step_ = 1;
100 return boost::asio::post(
101 s_.get_executor(),
102 bind_handler(std::move(*this), ec, 0));
103 }
104 step_ = 2;
105 if(role_ == role_type::server)
106 s_.shutdown(tcp::socket::shutdown_send, ec);
107 goto do_read;
108
109 case 1:
110 break;
111
112 case 2:
113 step_ = 3;
114
115 case 3:
116 if(ec != boost::asio::error::would_block)
117 break;
118 {
119 char buf[2048];
120 s_.read_some(
121 boost::asio::buffer(buf), ec);
122 if(ec)
123 break;
124 }
125
126 do_read:
127 return s_.async_read_some(
128 boost::asio::null_buffers{},
129 std::move(*this));
130 }
131 if(role_ == role_type::client)
132 s_.shutdown(tcp::socket::shutdown_send, ec);
133 s_.close(ec);
134 h_(ec);
135 }
136
137 } // detail
138
139 //------------------------------------------------------------------------------
140
141 inline
142 void
143 teardown(
144 role_type role,
145 boost::asio::ip::tcp::socket& socket,
146 error_code& ec)
147 {
148 using boost::asio::buffer;
149 if(role == role_type::server)
150 socket.shutdown(
151 boost::asio::ip::tcp::socket::shutdown_send, ec);
152 while(! ec)
153 {
154 char buf[8192];
155 auto const n = socket.read_some(
156 buffer(buf), ec);
157 if(! n)
158 break;
159 }
160 if(role == role_type::client)
161 socket.shutdown(
162 boost::asio::ip::tcp::socket::shutdown_send, ec);
163 socket.close(ec);
164 }
165
166 template<class TeardownHandler>
167 inline
168 void
169 async_teardown(
170 role_type role,
171 boost::asio::ip::tcp::socket& socket,
172 TeardownHandler&& handler)
173 {
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,
180 role}();
181 }
182
183 } // websocket
184 } // beast
185 } // boost
186
187 #endif