2 // Copyright (c) 2016-2019 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_STREAM_HPP
11 #define BOOST_BEAST_WEBSOCKET_IMPL_STREAM_HPP
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>
42 template<class NextLayer, bool deflateSupported>
43 stream<NextLayer, deflateSupported>::
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)...))
57 BOOST_ASSERT(impl_->rd_buf.max_size() >=
58 max_control_frame_size);
61 template<class NextLayer, bool deflateSupported>
63 stream<NextLayer, deflateSupported>::
64 get_executor() noexcept ->
67 return impl_->stream().get_executor();
70 template<class NextLayer, bool deflateSupported>
72 stream<NextLayer, deflateSupported>::
73 next_layer() noexcept ->
76 return impl_->stream();
79 template<class NextLayer, bool deflateSupported>
81 stream<NextLayer, deflateSupported>::
82 next_layer() const noexcept ->
83 next_layer_type const&
85 return impl_->stream();
88 template<class NextLayer, bool deflateSupported>
90 stream<NextLayer, deflateSupported>::
91 is_open() const noexcept
93 return impl_->status_ == status::open;
96 template<class NextLayer, bool deflateSupported>
98 stream<NextLayer, deflateSupported>::
99 got_binary() const noexcept
101 return impl_->rd_op == detail::opcode::binary;
104 template<class NextLayer, bool deflateSupported>
106 stream<NextLayer, deflateSupported>::
107 is_message_done() const noexcept
109 return impl_->rd_done;
112 template<class NextLayer, bool deflateSupported>
114 stream<NextLayer, deflateSupported>::
115 reason() const noexcept
120 template<class NextLayer, bool deflateSupported>
122 stream<NextLayer, deflateSupported>::
124 std::size_t initial_size) const
126 return impl_->read_size_hint_pmd(
127 initial_size, impl_->rd_done,
128 impl_->rd_remain, impl_->rd_fh);
131 template<class NextLayer, bool deflateSupported>
132 template<class DynamicBuffer, class>
134 stream<NextLayer, deflateSupported>::
135 read_size_hint(DynamicBuffer& buffer) const
138 net::is_dynamic_buffer<DynamicBuffer>::value,
139 "DynamicBuffer type requirements not met");
140 return impl_->read_size_hint_db(buffer);
143 //------------------------------------------------------------------------------
147 //------------------------------------------------------------------------------
151 template<class NextLayer, bool deflateSupported>
153 stream<NextLayer, deflateSupported>::
154 set_option(decorator opt)
156 impl_->decorator_opt = std::move(opt.d_);
161 template<class NextLayer, bool deflateSupported>
163 stream<NextLayer, deflateSupported>::
164 get_option(timeout& opt)
166 opt = impl_->timeout_opt;
169 template<class NextLayer, bool deflateSupported>
171 stream<NextLayer, deflateSupported>::
172 set_option(timeout const& opt)
174 impl_->set_option(opt);
179 template<class NextLayer, bool deflateSupported>
181 stream<NextLayer, deflateSupported>::
182 set_option(permessage_deflate const& o)
184 impl_->set_option_pmd(o);
187 template<class NextLayer, bool deflateSupported>
189 stream<NextLayer, deflateSupported>::
190 get_option(permessage_deflate& o)
192 impl_->get_option_pmd(o);
195 template<class NextLayer, bool deflateSupported>
197 stream<NextLayer, deflateSupported>::
198 auto_fragment(bool value)
200 impl_->wr_frag_opt = value;
203 template<class NextLayer, bool deflateSupported>
205 stream<NextLayer, deflateSupported>::
206 auto_fragment() const
208 return impl_->wr_frag_opt;
211 template<class NextLayer, bool deflateSupported>
213 stream<NextLayer, deflateSupported>::
216 impl_->wr_opcode = value ?
217 detail::opcode::binary :
218 detail::opcode::text;
221 template<class NextLayer, bool deflateSupported>
223 stream<NextLayer, deflateSupported>::
226 return impl_->wr_opcode == detail::opcode::binary;
229 template<class NextLayer, bool deflateSupported>
231 stream<NextLayer, deflateSupported>::
232 control_callback(std::function<
233 void(frame_type, string_view)> cb)
235 impl_->ctrl_cb = std::move(cb);
238 template<class NextLayer, bool deflateSupported>
240 stream<NextLayer, deflateSupported>::
246 template<class NextLayer, bool deflateSupported>
248 stream<NextLayer, deflateSupported>::
249 read_message_max(std::size_t amount)
251 impl_->rd_msg_max = amount;
254 template<class NextLayer, bool deflateSupported>
256 stream<NextLayer, deflateSupported>::
257 read_message_max() const
259 return impl_->rd_msg_max;
262 template<class NextLayer, bool deflateSupported>
264 stream<NextLayer, deflateSupported>::
265 secure_prng(bool value)
267 this->impl_->secure_prng_ = value;
270 template<class NextLayer, bool deflateSupported>
272 stream<NextLayer, deflateSupported>::
273 write_buffer_bytes(std::size_t amount)
276 BOOST_THROW_EXCEPTION(std::invalid_argument{
277 "write buffer size underflow"});
278 impl_->wr_buf_opt = amount;
281 template<class NextLayer, bool deflateSupported>
283 stream<NextLayer, deflateSupported>::
284 write_buffer_bytes() const
286 return impl_->wr_buf_opt;
289 template<class NextLayer, bool deflateSupported>
291 stream<NextLayer, deflateSupported>::
294 impl_->wr_opcode = value ?
295 detail::opcode::text :
296 detail::opcode::binary;
299 template<class NextLayer, bool deflateSupported>
301 stream<NextLayer, deflateSupported>::
304 return impl_->wr_opcode == detail::opcode::text;
307 //------------------------------------------------------------------------------
309 // _Fail the WebSocket Connection_
310 template<class NextLayer, bool deflateSupported>
312 stream<NextLayer, deflateSupported>::
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
319 impl_->change_status(status::closing);
320 if(code != close_code::none && ! impl_->wr_close)
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))
330 using beast::websocket::teardown;
331 teardown(impl_->role, impl_->stream(), ec);
332 if(ec == net::error::eof)
335 // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
340 if(ec && ec != error::closed)
341 impl_->change_status(status::failed);
343 impl_->change_status(status::closed);