]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/websocket/impl/stream.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / websocket / impl / stream.hpp
1 //
2 // Copyright (c) 2016-2019 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_STREAM_HPP
11 #define BOOST_BEAST_WEBSOCKET_IMPL_STREAM_HPP
12
13 #include <boost/beast/core/buffer_traits.hpp>
14 #include <boost/beast/websocket/rfc6455.hpp>
15 #include <boost/beast/websocket/teardown.hpp>
16 #include <boost/beast/websocket/detail/hybi13.hpp>
17 #include <boost/beast/websocket/detail/mask.hpp>
18 #include <boost/beast/websocket/impl/stream_impl.hpp>
19 #include <boost/beast/version.hpp>
20 #include <boost/beast/http/read.hpp>
21 #include <boost/beast/http/write.hpp>
22 #include <boost/beast/http/rfc7230.hpp>
23 #include <boost/beast/core/buffers_cat.hpp>
24 #include <boost/beast/core/buffers_prefix.hpp>
25 #include <boost/beast/core/buffers_suffix.hpp>
26 #include <boost/beast/core/flat_static_buffer.hpp>
27 #include <boost/beast/core/detail/clamp.hpp>
28 #include <boost/asio/steady_timer.hpp>
29 #include <boost/assert.hpp>
30 #include <boost/make_shared.hpp>
31 #include <boost/throw_exception.hpp>
32 #include <algorithm>
33 #include <chrono>
34 #include <memory>
35 #include <stdexcept>
36 #include <utility>
37
38 namespace boost {
39 namespace beast {
40 namespace websocket {
41
42 template<class NextLayer, bool deflateSupported>
43 stream<NextLayer, deflateSupported>::
44 ~stream()
45 {
46 if(impl_)
47 impl_->remove();
48 }
49
50 template<class NextLayer, bool deflateSupported>
51 template<class... Args>
52 stream<NextLayer, deflateSupported>::
53 stream(Args&&... args)
54 : impl_(boost::make_shared<impl_type>(
55 std::forward<Args>(args)...))
56 {
57 BOOST_ASSERT(impl_->rd_buf.max_size() >=
58 max_control_frame_size);
59 }
60
61 template<class NextLayer, bool deflateSupported>
62 auto
63 stream<NextLayer, deflateSupported>::
64 get_executor() noexcept ->
65 executor_type
66 {
67 return impl_->stream().get_executor();
68 }
69
70 template<class NextLayer, bool deflateSupported>
71 auto
72 stream<NextLayer, deflateSupported>::
73 next_layer() noexcept ->
74 next_layer_type&
75 {
76 return impl_->stream();
77 }
78
79 template<class NextLayer, bool deflateSupported>
80 auto
81 stream<NextLayer, deflateSupported>::
82 next_layer() const noexcept ->
83 next_layer_type const&
84 {
85 return impl_->stream();
86 }
87
88 template<class NextLayer, bool deflateSupported>
89 bool
90 stream<NextLayer, deflateSupported>::
91 is_open() const noexcept
92 {
93 return impl_->status_ == status::open;
94 }
95
96 template<class NextLayer, bool deflateSupported>
97 bool
98 stream<NextLayer, deflateSupported>::
99 got_binary() const noexcept
100 {
101 return impl_->rd_op == detail::opcode::binary;
102 }
103
104 template<class NextLayer, bool deflateSupported>
105 bool
106 stream<NextLayer, deflateSupported>::
107 is_message_done() const noexcept
108 {
109 return impl_->rd_done;
110 }
111
112 template<class NextLayer, bool deflateSupported>
113 close_reason const&
114 stream<NextLayer, deflateSupported>::
115 reason() const noexcept
116 {
117 return impl_->cr;
118 }
119
120 template<class NextLayer, bool deflateSupported>
121 std::size_t
122 stream<NextLayer, deflateSupported>::
123 read_size_hint(
124 std::size_t initial_size) const
125 {
126 return impl_->read_size_hint_pmd(
127 initial_size, impl_->rd_done,
128 impl_->rd_remain, impl_->rd_fh);
129 }
130
131 template<class NextLayer, bool deflateSupported>
132 template<class DynamicBuffer, class>
133 std::size_t
134 stream<NextLayer, deflateSupported>::
135 read_size_hint(DynamicBuffer& buffer) const
136 {
137 static_assert(
138 net::is_dynamic_buffer<DynamicBuffer>::value,
139 "DynamicBuffer type requirements not met");
140 return impl_->read_size_hint_db(buffer);
141 }
142
143 //------------------------------------------------------------------------------
144 //
145 // Settings
146 //
147 //------------------------------------------------------------------------------
148
149 // decorator
150
151 template<class NextLayer, bool deflateSupported>
152 void
153 stream<NextLayer, deflateSupported>::
154 set_option(decorator opt)
155 {
156 impl_->decorator_opt = std::move(opt.d_);
157 }
158
159 // timeout
160
161 template<class NextLayer, bool deflateSupported>
162 void
163 stream<NextLayer, deflateSupported>::
164 get_option(timeout& opt)
165 {
166 opt = impl_->timeout_opt;
167 }
168
169 template<class NextLayer, bool deflateSupported>
170 void
171 stream<NextLayer, deflateSupported>::
172 set_option(timeout const& opt)
173 {
174 impl_->set_option(opt);
175 }
176
177 //
178
179 template<class NextLayer, bool deflateSupported>
180 void
181 stream<NextLayer, deflateSupported>::
182 set_option(permessage_deflate const& o)
183 {
184 impl_->set_option_pmd(o);
185 }
186
187 template<class NextLayer, bool deflateSupported>
188 void
189 stream<NextLayer, deflateSupported>::
190 get_option(permessage_deflate& o)
191 {
192 impl_->get_option_pmd(o);
193 }
194
195 template<class NextLayer, bool deflateSupported>
196 void
197 stream<NextLayer, deflateSupported>::
198 auto_fragment(bool value)
199 {
200 impl_->wr_frag_opt = value;
201 }
202
203 template<class NextLayer, bool deflateSupported>
204 bool
205 stream<NextLayer, deflateSupported>::
206 auto_fragment() const
207 {
208 return impl_->wr_frag_opt;
209 }
210
211 template<class NextLayer, bool deflateSupported>
212 void
213 stream<NextLayer, deflateSupported>::
214 binary(bool value)
215 {
216 impl_->wr_opcode = value ?
217 detail::opcode::binary :
218 detail::opcode::text;
219 }
220
221 template<class NextLayer, bool deflateSupported>
222 bool
223 stream<NextLayer, deflateSupported>::
224 binary() const
225 {
226 return impl_->wr_opcode == detail::opcode::binary;
227 }
228
229 template<class NextLayer, bool deflateSupported>
230 void
231 stream<NextLayer, deflateSupported>::
232 control_callback(std::function<
233 void(frame_type, string_view)> cb)
234 {
235 impl_->ctrl_cb = std::move(cb);
236 }
237
238 template<class NextLayer, bool deflateSupported>
239 void
240 stream<NextLayer, deflateSupported>::
241 control_callback()
242 {
243 impl_->ctrl_cb = {};
244 }
245
246 template<class NextLayer, bool deflateSupported>
247 void
248 stream<NextLayer, deflateSupported>::
249 read_message_max(std::size_t amount)
250 {
251 impl_->rd_msg_max = amount;
252 }
253
254 template<class NextLayer, bool deflateSupported>
255 std::size_t
256 stream<NextLayer, deflateSupported>::
257 read_message_max() const
258 {
259 return impl_->rd_msg_max;
260 }
261
262 template<class NextLayer, bool deflateSupported>
263 void
264 stream<NextLayer, deflateSupported>::
265 secure_prng(bool value)
266 {
267 this->impl_->secure_prng_ = value;
268 }
269
270 template<class NextLayer, bool deflateSupported>
271 void
272 stream<NextLayer, deflateSupported>::
273 write_buffer_bytes(std::size_t amount)
274 {
275 if(amount < 8)
276 BOOST_THROW_EXCEPTION(std::invalid_argument{
277 "write buffer size underflow"});
278 impl_->wr_buf_opt = amount;
279 }
280
281 template<class NextLayer, bool deflateSupported>
282 std::size_t
283 stream<NextLayer, deflateSupported>::
284 write_buffer_bytes() const
285 {
286 return impl_->wr_buf_opt;
287 }
288
289 template<class NextLayer, bool deflateSupported>
290 void
291 stream<NextLayer, deflateSupported>::
292 text(bool value)
293 {
294 impl_->wr_opcode = value ?
295 detail::opcode::text :
296 detail::opcode::binary;
297 }
298
299 template<class NextLayer, bool deflateSupported>
300 bool
301 stream<NextLayer, deflateSupported>::
302 text() const
303 {
304 return impl_->wr_opcode == detail::opcode::text;
305 }
306
307 //------------------------------------------------------------------------------
308
309 // _Fail the WebSocket Connection_
310 template<class NextLayer, bool deflateSupported>
311 void
312 stream<NextLayer, deflateSupported>::
313 do_fail(
314 std::uint16_t code, // if set, send a close frame first
315 error_code ev, // error code to use upon success
316 error_code& ec) // set to the error, else set to ev
317 {
318 BOOST_ASSERT(ev);
319 impl_->change_status(status::closing);
320 if(code != close_code::none && ! impl_->wr_close)
321 {
322 impl_->wr_close = true;
323 detail::frame_buffer fb;
324 impl_->template write_close<
325 flat_static_buffer_base>(fb, code);
326 net::write(impl_->stream(), fb.data(), ec);
327 if(impl_->check_stop_now(ec))
328 return;
329 }
330 using beast::websocket::teardown;
331 teardown(impl_->role, impl_->stream(), ec);
332 if(ec == net::error::eof)
333 {
334 // Rationale:
335 // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
336 ec = {};
337 }
338 if(! ec)
339 ec = ev;
340 if(ec && ec != error::closed)
341 impl_->change_status(status::failed);
342 else
343 impl_->change_status(status::closed);
344 impl_->close();
345 }
346
347 } // websocket
348 } // beast
349 } // boost
350
351 #endif