stream_impl.hpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  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. #ifndef BOOST_BEAST_WEBSOCKET_IMPL_STREAM_IMPL_HPP
  10. #define BOOST_BEAST_WEBSOCKET_IMPL_STREAM_IMPL_HPP
  11. #include <boost/beast/websocket/rfc6455.hpp>
  12. #include <boost/beast/websocket/detail/frame.hpp>
  13. #include <boost/beast/websocket/detail/hybi13.hpp>
  14. #include <boost/beast/websocket/detail/mask.hpp>
  15. #include <boost/beast/websocket/detail/pmd_extension.hpp>
  16. #include <boost/beast/websocket/detail/prng.hpp>
  17. #include <boost/beast/websocket/detail/service.hpp>
  18. #include <boost/beast/websocket/detail/soft_mutex.hpp>
  19. #include <boost/beast/websocket/detail/utf8_checker.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/saved_handler.hpp>
  28. #include <boost/beast/core/static_buffer.hpp>
  29. #include <boost/beast/core/stream_traits.hpp>
  30. #include <boost/beast/core/detail/clamp.hpp>
  31. #include <boost/beast/core/detail/type_traits.hpp>
  32. #include <boost/beast/version.hpp>
  33. #include <boost/asio/bind_executor.hpp>
  34. #include <boost/asio/steady_timer.hpp>
  35. #include <boost/core/empty_value.hpp>
  36. #include <boost/enable_shared_from_this.hpp>
  37. #include <boost/shared_ptr.hpp>
  38. #include <boost/optional.hpp>
  39. namespace boost {
  40. namespace beast {
  41. namespace websocket {
  42. template<
  43. class NextLayer, bool deflateSupported>
  44. struct stream<NextLayer, deflateSupported>::impl_type
  45. : boost::empty_value<NextLayer>
  46. , detail::service::impl_type
  47. , detail::impl_base<deflateSupported>
  48. {
  49. NextLayer& stream() noexcept
  50. {
  51. return this->boost::empty_value<
  52. NextLayer>::get();
  53. }
  54. boost::weak_ptr<impl_type>
  55. weak_from_this()
  56. {
  57. return boost::static_pointer_cast<
  58. impl_type>(this->detail::service::
  59. impl_type::shared_from_this());
  60. }
  61. boost::shared_ptr<impl_type>
  62. shared_this()
  63. {
  64. return boost::static_pointer_cast<
  65. impl_type>(this->detail::service::
  66. impl_type::shared_from_this());
  67. }
  68. net::steady_timer timer; // used for timeouts
  69. close_reason cr; // set from received close frame
  70. control_cb_type ctrl_cb; // control callback
  71. std::size_t rd_msg_max /* max message size */ = 16 * 1024 * 1024;
  72. std::uint64_t rd_size /* total size of current message so far */ = 0;
  73. std::uint64_t rd_remain /* message frame bytes left in current frame */ = 0;
  74. detail::frame_header rd_fh; // current frame header
  75. detail::prepared_key rd_key; // current stateful mask key
  76. detail::frame_buffer rd_fb; // to write control frames (during reads)
  77. detail::utf8_checker rd_utf8; // to validate utf8
  78. static_buffer<
  79. +tcp_frame_size> rd_buf; // buffer for reads
  80. detail::opcode rd_op /* current message binary or text */ = detail::opcode::text;
  81. bool rd_cont /* `true` if the next frame is a continuation */ = false;
  82. bool rd_done /* set when a message is done */ = true;
  83. bool rd_close /* did we read a close frame? */ = false;
  84. detail::soft_mutex rd_block; // op currently reading
  85. role_type role /* server or client */ = role_type::client;
  86. status status_ /* state of the object */ = status::closed;
  87. detail::soft_mutex wr_block; // op currently writing
  88. bool wr_close /* did we write a close frame? */ = false;
  89. bool wr_cont /* next write is a continuation */ = false;
  90. bool wr_frag /* autofrag the current message */ = false;
  91. bool wr_frag_opt /* autofrag option setting */ = true;
  92. bool wr_compress /* compress current message */ = false;
  93. detail::opcode wr_opcode /* message type */ = detail::opcode::text;
  94. std::unique_ptr<
  95. std::uint8_t[]> wr_buf; // write buffer
  96. std::size_t wr_buf_size /* write buffer size (current message) */ = 0;
  97. std::size_t wr_buf_opt /* write buffer size option setting */ = 4096;
  98. detail::fh_buffer wr_fb; // header buffer used for writes
  99. saved_handler op_rd; // paused read op
  100. saved_handler op_wr; // paused write op
  101. saved_handler op_ping; // paused ping op
  102. saved_handler op_idle_ping; // paused idle ping op
  103. saved_handler op_close; // paused close op
  104. saved_handler op_r_rd; // paused read op (async read)
  105. saved_handler op_r_close; // paused close op (async read)
  106. bool idle_pinging = false;
  107. bool secure_prng_ = true;
  108. bool ec_delivered = false;
  109. bool timed_out = false;
  110. int idle_counter = 0;
  111. detail::decorator decorator_opt; // Decorator for HTTP messages
  112. timeout timeout_opt; // Timeout/idle settings
  113. template<class... Args>
  114. impl_type(Args&&... args)
  115. : boost::empty_value<NextLayer>(
  116. boost::empty_init_t{},
  117. std::forward<Args>(args)...)
  118. , detail::service::impl_type(
  119. this->boost::empty_value<NextLayer>::get().get_executor().context())
  120. , timer(this->boost::empty_value<NextLayer>::get().get_executor())
  121. {
  122. timeout_opt.handshake_timeout = none();
  123. timeout_opt.idle_timeout = none();
  124. timeout_opt.keep_alive_pings = false;
  125. }
  126. void
  127. shutdown() override
  128. {
  129. op_rd.reset();
  130. op_wr.reset();
  131. op_ping.reset();
  132. op_idle_ping.reset();
  133. op_close.reset();
  134. op_r_rd.reset();
  135. op_r_close.reset();
  136. }
  137. void
  138. open(role_type role_)
  139. {
  140. // VFALCO TODO analyze and remove dupe code in reset()
  141. timer.expires_at(never());
  142. timed_out = false;
  143. cr.code = close_code::none;
  144. role = role_;
  145. status_ = status::open;
  146. rd_remain = 0;
  147. rd_cont = false;
  148. rd_done = true;
  149. // Can't clear this because accept uses it
  150. //rd_buf.reset();
  151. rd_fh.fin = false;
  152. rd_close = false;
  153. wr_close = false;
  154. // These should not be necessary, because all completion
  155. // handlers must be allowed to execute otherwise the
  156. // stream exhibits undefined behavior.
  157. wr_block.reset();
  158. rd_block.reset();
  159. wr_cont = false;
  160. wr_buf_size = 0;
  161. this->open_pmd(role);
  162. }
  163. void
  164. close()
  165. {
  166. timer.cancel();
  167. wr_buf.reset();
  168. this->close_pmd();
  169. }
  170. void
  171. reset()
  172. {
  173. BOOST_ASSERT(status_ != status::open);
  174. timer.expires_at(never());
  175. cr.code = close_code::none;
  176. rd_remain = 0;
  177. rd_cont = false;
  178. rd_done = true;
  179. rd_buf.consume(rd_buf.size());
  180. rd_fh.fin = false;
  181. rd_close = false;
  182. wr_close = false;
  183. wr_cont = false;
  184. // These should not be necessary, because all completion
  185. // handlers must be allowed to execute otherwise the
  186. // stream exhibits undefined behavior.
  187. wr_block.reset();
  188. rd_block.reset();
  189. // VFALCO Is this needed?
  190. timer.cancel();
  191. }
  192. // Called before each write frame
  193. void
  194. begin_msg()
  195. {
  196. wr_frag = wr_frag_opt;
  197. // Maintain the write buffer
  198. if( this->pmd_enabled() ||
  199. role == role_type::client)
  200. {
  201. if(! wr_buf ||
  202. wr_buf_size != wr_buf_opt)
  203. {
  204. wr_buf_size = wr_buf_opt;
  205. wr_buf = boost::make_unique_noinit<
  206. std::uint8_t[]>(wr_buf_size);
  207. }
  208. }
  209. else
  210. {
  211. wr_buf_size = wr_buf_opt;
  212. wr_buf.reset();
  213. }
  214. }
  215. //--------------------------------------------------------------------------
  216. template<class Decorator>
  217. request_type
  218. build_request(
  219. detail::sec_ws_key_type& key,
  220. string_view host, string_view target,
  221. Decorator const& decorator);
  222. void
  223. on_response(
  224. response_type const& res,
  225. detail::sec_ws_key_type const& key,
  226. error_code& ec);
  227. template<class Body, class Allocator, class Decorator>
  228. response_type
  229. build_response(
  230. http::request<Body,
  231. http::basic_fields<Allocator>> const& req,
  232. Decorator const& decorator,
  233. error_code& result);
  234. // Attempt to read a complete frame header.
  235. // Returns `false` if more bytes are needed
  236. template<class DynamicBuffer>
  237. bool
  238. parse_fh(detail::frame_header& fh,
  239. DynamicBuffer& b, error_code& ec);
  240. std::uint32_t
  241. create_mask()
  242. {
  243. auto g = detail::make_prng(secure_prng_);
  244. for(;;)
  245. if(auto key = g())
  246. return key;
  247. }
  248. std::size_t
  249. read_size_hint(std::size_t initial_size) const
  250. {
  251. return this->read_size_hint_pmd(
  252. initial_size, rd_done, rd_remain, rd_fh);
  253. }
  254. template<class DynamicBuffer>
  255. std::size_t
  256. read_size_hint_db(DynamicBuffer& buffer) const
  257. {
  258. auto const initial_size = (std::min)(
  259. +tcp_frame_size,
  260. buffer.max_size() - buffer.size());
  261. if(initial_size == 0)
  262. return 1; // buffer is full
  263. return this->read_size_hint(initial_size);
  264. }
  265. template<class DynamicBuffer>
  266. void
  267. write_ping(DynamicBuffer& db,
  268. detail::opcode code, ping_data const& data);
  269. template<class DynamicBuffer>
  270. void
  271. write_close(DynamicBuffer& db, close_reason const& cr);
  272. //--------------------------------------------------------------------------
  273. void
  274. set_option(timeout const& opt)
  275. {
  276. if( opt.handshake_timeout == none() &&
  277. opt.idle_timeout == none())
  278. {
  279. // turn timer off
  280. timer.cancel();
  281. timer.expires_at(never());
  282. }
  283. timeout_opt = opt;
  284. }
  285. // Determine if an operation should stop and
  286. // deliver an error code to the completion handler.
  287. //
  288. // This function must be called at the beginning
  289. // of every composed operation, and every time a
  290. // composed operation receives an intermediate
  291. // completion.
  292. //
  293. bool
  294. check_stop_now(error_code& ec)
  295. {
  296. // Deliver the timeout to the first caller
  297. if(timed_out)
  298. {
  299. timed_out = false;
  300. ec = beast::error::timeout;
  301. return true;
  302. }
  303. // If the stream is closed then abort
  304. if( status_ == status::closed ||
  305. status_ == status::failed)
  306. {
  307. //BOOST_ASSERT(ec_delivered);
  308. ec = net::error::operation_aborted;
  309. return true;
  310. }
  311. // If no error then keep going
  312. if(! ec)
  313. return false;
  314. // Is this the first error seen?
  315. if(ec_delivered)
  316. {
  317. // No, so abort
  318. ec = net::error::operation_aborted;
  319. return true;
  320. }
  321. // Deliver the error to the completion handler
  322. ec_delivered = true;
  323. if(status_ != status::closed)
  324. status_ = status::failed;
  325. return true;
  326. }
  327. // Change the status of the stream
  328. void
  329. change_status(status new_status)
  330. {
  331. switch(new_status)
  332. {
  333. case status::handshake:
  334. break;
  335. case status::open:
  336. break;
  337. case status::closing:
  338. //BOOST_ASSERT(status_ == status::open);
  339. break;
  340. case status::failed:
  341. case status::closed:
  342. // this->close(); // Is this right?
  343. break;
  344. default:
  345. break;
  346. }
  347. status_ = new_status;
  348. }
  349. // Called to disarm the idle timeout counter
  350. void
  351. reset_idle()
  352. {
  353. idle_counter = 0;
  354. }
  355. // Maintain the expiration timer
  356. template<class Executor>
  357. void
  358. update_timer(Executor const& ex)
  359. {
  360. switch(status_)
  361. {
  362. case status::handshake:
  363. BOOST_ASSERT(idle_counter == 0);
  364. if(! is_timer_set() &&
  365. timeout_opt.handshake_timeout != none())
  366. {
  367. timer.expires_after(
  368. timeout_opt.handshake_timeout);
  369. timer.async_wait(
  370. timeout_handler<Executor>(
  371. ex, this->weak_from_this()));
  372. }
  373. break;
  374. case status::open:
  375. if(timeout_opt.idle_timeout != none())
  376. {
  377. idle_counter = 0;
  378. if(timeout_opt.keep_alive_pings)
  379. timer.expires_after(
  380. timeout_opt.idle_timeout / 2);
  381. else
  382. timer.expires_after(
  383. timeout_opt.idle_timeout);
  384. timer.async_wait(
  385. timeout_handler<Executor>(
  386. ex, this->weak_from_this()));
  387. }
  388. else
  389. {
  390. timer.cancel();
  391. timer.expires_at(never());
  392. }
  393. break;
  394. case status::closing:
  395. if(timeout_opt.handshake_timeout != none())
  396. {
  397. idle_counter = 0;
  398. timer.expires_after(
  399. timeout_opt.handshake_timeout);
  400. timer.async_wait(
  401. timeout_handler<Executor>(
  402. ex, this->weak_from_this()));
  403. }
  404. else
  405. {
  406. BOOST_ASSERT(! is_timer_set());
  407. }
  408. break;
  409. case status::failed:
  410. case status::closed:
  411. // this->close(); // Is this right?
  412. timer.cancel();
  413. timer.expires_at(never());
  414. break;
  415. }
  416. }
  417. private:
  418. bool
  419. is_timer_set() const
  420. {
  421. return timer.expiry() != never();
  422. }
  423. template<class Executor>
  424. class timeout_handler
  425. : boost::empty_value<Executor>
  426. {
  427. boost::weak_ptr<impl_type> wp_;
  428. public:
  429. timeout_handler(
  430. Executor const& ex,
  431. boost::weak_ptr<impl_type>&& wp)
  432. : boost::empty_value<Executor>(
  433. boost::empty_init_t{}, ex)
  434. , wp_(std::move(wp))
  435. {
  436. }
  437. using executor_type = Executor;
  438. executor_type
  439. get_executor() const noexcept
  440. {
  441. return this->get();
  442. }
  443. void
  444. operator()(error_code ec)
  445. {
  446. // timer canceled?
  447. if(ec == net::error::operation_aborted)
  448. return;
  449. BOOST_ASSERT(! ec);
  450. // stream destroyed?
  451. auto sp = wp_.lock();
  452. if(! sp)
  453. return;
  454. auto& impl = *sp;
  455. switch(impl.status_)
  456. {
  457. case status::handshake:
  458. impl.timed_out = true;
  459. close_socket(get_lowest_layer(impl.stream()));
  460. return;
  461. case status::open:
  462. // timeout was disabled
  463. if(impl.timeout_opt.idle_timeout == none())
  464. return;
  465. if( impl.timeout_opt.keep_alive_pings &&
  466. impl.idle_counter < 1)
  467. {
  468. idle_ping_op<Executor>(sp, get_executor());
  469. ++impl.idle_counter;
  470. impl.timer.expires_after(
  471. impl.timeout_opt.idle_timeout / 2);
  472. impl.timer.async_wait(std::move(*this));
  473. return;
  474. }
  475. // timeout
  476. impl.timed_out = true;
  477. close_socket(get_lowest_layer(impl.stream()));
  478. return;
  479. case status::closing:
  480. impl.timed_out = true;
  481. close_socket(get_lowest_layer(impl.stream()));
  482. return;
  483. case status::closed:
  484. case status::failed:
  485. // nothing to do?
  486. return;
  487. }
  488. }
  489. };
  490. };
  491. //--------------------------------------------------------------------------
  492. //
  493. // client
  494. //
  495. //--------------------------------------------------------------------------
  496. template<class NextLayer, bool deflateSupported>
  497. template<class Decorator>
  498. request_type
  499. stream<NextLayer, deflateSupported>::impl_type::
  500. build_request(
  501. detail::sec_ws_key_type& key,
  502. string_view host, string_view target,
  503. Decorator const& decorator)
  504. {
  505. request_type req;
  506. req.target(target);
  507. req.version(11);
  508. req.method(http::verb::get);
  509. req.set(http::field::host, host);
  510. req.set(http::field::upgrade, "websocket");
  511. req.set(http::field::connection, "upgrade");
  512. detail::make_sec_ws_key(key);
  513. req.set(http::field::sec_websocket_key, key);
  514. req.set(http::field::sec_websocket_version, "13");
  515. this->build_request_pmd(req);
  516. decorator_opt(req);
  517. decorator(req);
  518. if(! req.count(http::field::user_agent))
  519. req.set(http::field::user_agent,
  520. BOOST_BEAST_VERSION_STRING);
  521. return req;
  522. }
  523. // Called when the WebSocket Upgrade response is received
  524. template<class NextLayer, bool deflateSupported>
  525. void
  526. stream<NextLayer, deflateSupported>::impl_type::
  527. on_response(
  528. response_type const& res,
  529. detail::sec_ws_key_type const& key,
  530. error_code& ec)
  531. {
  532. auto const err =
  533. [&](error e)
  534. {
  535. ec = e;
  536. };
  537. if(res.result() != http::status::switching_protocols)
  538. return err(error::upgrade_declined);
  539. if(res.version() != 11)
  540. return err(error::bad_http_version);
  541. {
  542. auto const it = res.find(http::field::connection);
  543. if(it == res.end())
  544. return err(error::no_connection);
  545. if(! http::token_list{it->value()}.exists("upgrade"))
  546. return err(error::no_connection_upgrade);
  547. }
  548. {
  549. auto const it = res.find(http::field::upgrade);
  550. if(it == res.end())
  551. return err(error::no_upgrade);
  552. if(! http::token_list{it->value()}.exists("websocket"))
  553. return err(error::no_upgrade_websocket);
  554. }
  555. {
  556. auto const it = res.find(
  557. http::field::sec_websocket_accept);
  558. if(it == res.end())
  559. return err(error::no_sec_accept);
  560. detail::sec_ws_accept_type acc;
  561. detail::make_sec_ws_accept(acc, key);
  562. if(acc.compare(it->value()) != 0)
  563. return err(error::bad_sec_accept);
  564. }
  565. ec = {};
  566. this->on_response_pmd(res);
  567. this->open(role_type::client);
  568. }
  569. //------------------------------------------------------------------------------
  570. // Attempt to read a complete frame header.
  571. // Returns `false` if more bytes are needed
  572. template<class NextLayer, bool deflateSupported>
  573. template<class DynamicBuffer>
  574. bool
  575. stream<NextLayer, deflateSupported>::impl_type::
  576. parse_fh(
  577. detail::frame_header& fh,
  578. DynamicBuffer& b,
  579. error_code& ec)
  580. {
  581. if(buffer_bytes(b.data()) < 2)
  582. {
  583. // need more bytes
  584. ec = {};
  585. return false;
  586. }
  587. buffers_suffix<typename
  588. DynamicBuffer::const_buffers_type> cb{
  589. b.data()};
  590. std::size_t need;
  591. {
  592. std::uint8_t tmp[2];
  593. cb.consume(net::buffer_copy(
  594. net::buffer(tmp), cb));
  595. fh.len = tmp[1] & 0x7f;
  596. switch(fh.len)
  597. {
  598. case 126: need = 2; break;
  599. case 127: need = 8; break;
  600. default:
  601. need = 0;
  602. }
  603. fh.mask = (tmp[1] & 0x80) != 0;
  604. if(fh.mask)
  605. need += 4;
  606. if(buffer_bytes(cb) < need)
  607. {
  608. // need more bytes
  609. ec = {};
  610. return false;
  611. }
  612. fh.op = static_cast<
  613. detail::opcode>(tmp[0] & 0x0f);
  614. fh.fin = (tmp[0] & 0x80) != 0;
  615. fh.rsv1 = (tmp[0] & 0x40) != 0;
  616. fh.rsv2 = (tmp[0] & 0x20) != 0;
  617. fh.rsv3 = (tmp[0] & 0x10) != 0;
  618. }
  619. switch(fh.op)
  620. {
  621. case detail::opcode::binary:
  622. case detail::opcode::text:
  623. if(rd_cont)
  624. {
  625. // new data frame when continuation expected
  626. ec = error::bad_data_frame;
  627. return false;
  628. }
  629. if(fh.rsv2 || fh.rsv3 ||
  630. ! this->rd_deflated(fh.rsv1))
  631. {
  632. // reserved bits not cleared
  633. ec = error::bad_reserved_bits;
  634. return false;
  635. }
  636. break;
  637. case detail::opcode::cont:
  638. if(! rd_cont)
  639. {
  640. // continuation without an active message
  641. ec = error::bad_continuation;
  642. return false;
  643. }
  644. if(fh.rsv1 || fh.rsv2 || fh.rsv3)
  645. {
  646. // reserved bits not cleared
  647. ec = error::bad_reserved_bits;
  648. return false;
  649. }
  650. break;
  651. default:
  652. if(detail::is_reserved(fh.op))
  653. {
  654. // reserved opcode
  655. ec = error::bad_opcode;
  656. return false;
  657. }
  658. if(! fh.fin)
  659. {
  660. // fragmented control message
  661. ec = error::bad_control_fragment;
  662. return false;
  663. }
  664. if(fh.len > 125)
  665. {
  666. // invalid length for control message
  667. ec = error::bad_control_size;
  668. return false;
  669. }
  670. if(fh.rsv1 || fh.rsv2 || fh.rsv3)
  671. {
  672. // reserved bits not cleared
  673. ec = error::bad_reserved_bits;
  674. return false;
  675. }
  676. break;
  677. }
  678. if(role == role_type::server && ! fh.mask)
  679. {
  680. // unmasked frame from client
  681. ec = error::bad_unmasked_frame;
  682. return false;
  683. }
  684. if(role == role_type::client && fh.mask)
  685. {
  686. // masked frame from server
  687. ec = error::bad_masked_frame;
  688. return false;
  689. }
  690. if(detail::is_control(fh.op) &&
  691. buffer_bytes(cb) < need + fh.len)
  692. {
  693. // Make the entire control frame payload
  694. // get read in before we return `true`
  695. return false;
  696. }
  697. switch(fh.len)
  698. {
  699. case 126:
  700. {
  701. std::uint8_t tmp[2];
  702. BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp));
  703. cb.consume(net::buffer_copy(net::buffer(tmp), cb));
  704. fh.len = detail::big_uint16_to_native(&tmp[0]);
  705. if(fh.len < 126)
  706. {
  707. // length not canonical
  708. ec = error::bad_size;
  709. return false;
  710. }
  711. break;
  712. }
  713. case 127:
  714. {
  715. std::uint8_t tmp[8];
  716. BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp));
  717. cb.consume(net::buffer_copy(net::buffer(tmp), cb));
  718. fh.len = detail::big_uint64_to_native(&tmp[0]);
  719. if(fh.len < 65536)
  720. {
  721. // length not canonical
  722. ec = error::bad_size;
  723. return false;
  724. }
  725. break;
  726. }
  727. }
  728. if(fh.mask)
  729. {
  730. std::uint8_t tmp[4];
  731. BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp));
  732. cb.consume(net::buffer_copy(net::buffer(tmp), cb));
  733. fh.key = detail::little_uint32_to_native(&tmp[0]);
  734. detail::prepare_key(rd_key, fh.key);
  735. }
  736. else
  737. {
  738. // initialize this otherwise operator== breaks
  739. fh.key = 0;
  740. }
  741. if(! detail::is_control(fh.op))
  742. {
  743. if(fh.op != detail::opcode::cont)
  744. {
  745. rd_size = 0;
  746. rd_op = fh.op;
  747. }
  748. else
  749. {
  750. if(rd_size > (std::numeric_limits<
  751. std::uint64_t>::max)() - fh.len)
  752. {
  753. // message size exceeds configured limit
  754. ec = error::message_too_big;
  755. return false;
  756. }
  757. }
  758. if(! this->rd_deflated())
  759. {
  760. if(rd_msg_max && beast::detail::sum_exceeds(
  761. rd_size, fh.len, rd_msg_max))
  762. {
  763. // message size exceeds configured limit
  764. ec = error::message_too_big;
  765. return false;
  766. }
  767. }
  768. rd_cont = ! fh.fin;
  769. rd_remain = fh.len;
  770. }
  771. b.consume(b.size() - buffer_bytes(cb));
  772. ec = {};
  773. return true;
  774. }
  775. template<class NextLayer, bool deflateSupported>
  776. template<class DynamicBuffer>
  777. void
  778. stream<NextLayer, deflateSupported>::impl_type::
  779. write_ping(DynamicBuffer& db,
  780. detail::opcode code, ping_data const& data)
  781. {
  782. detail::frame_header fh;
  783. fh.op = code;
  784. fh.fin = true;
  785. fh.rsv1 = false;
  786. fh.rsv2 = false;
  787. fh.rsv3 = false;
  788. fh.len = data.size();
  789. fh.mask = role == role_type::client;
  790. if(fh.mask)
  791. fh.key = create_mask();
  792. detail::write(db, fh);
  793. if(data.empty())
  794. return;
  795. detail::prepared_key key;
  796. if(fh.mask)
  797. detail::prepare_key(key, fh.key);
  798. auto mb = db.prepare(data.size());
  799. net::buffer_copy(mb,
  800. net::const_buffer(
  801. data.data(), data.size()));
  802. if(fh.mask)
  803. detail::mask_inplace(mb, key);
  804. db.commit(data.size());
  805. }
  806. template<class NextLayer, bool deflateSupported>
  807. template<class DynamicBuffer>
  808. void
  809. stream<NextLayer, deflateSupported>::impl_type::
  810. write_close(DynamicBuffer& db, close_reason const& cr)
  811. {
  812. using namespace boost::endian;
  813. detail::frame_header fh;
  814. fh.op = detail::opcode::close;
  815. fh.fin = true;
  816. fh.rsv1 = false;
  817. fh.rsv2 = false;
  818. fh.rsv3 = false;
  819. fh.len = cr.code == close_code::none ?
  820. 0 : 2 + cr.reason.size();
  821. if(role == role_type::client)
  822. {
  823. fh.mask = true;
  824. fh.key = create_mask();
  825. }
  826. else
  827. {
  828. fh.mask = false;
  829. }
  830. detail::write(db, fh);
  831. if(cr.code != close_code::none)
  832. {
  833. detail::prepared_key key;
  834. if(fh.mask)
  835. detail::prepare_key(key, fh.key);
  836. {
  837. std::uint8_t tmp[2];
  838. ::new(&tmp[0]) big_uint16_buf_t{
  839. (std::uint16_t)cr.code};
  840. auto mb = db.prepare(2);
  841. net::buffer_copy(mb,
  842. net::buffer(tmp));
  843. if(fh.mask)
  844. detail::mask_inplace(mb, key);
  845. db.commit(2);
  846. }
  847. if(! cr.reason.empty())
  848. {
  849. auto mb = db.prepare(cr.reason.size());
  850. net::buffer_copy(mb,
  851. net::const_buffer(
  852. cr.reason.data(), cr.reason.size()));
  853. if(fh.mask)
  854. detail::mask_inplace(mb, key);
  855. db.commit(cr.reason.size());
  856. }
  857. }
  858. }
  859. } // websocket
  860. } // beast
  861. } // boost
  862. #endif