stream.ipp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  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. #ifndef BOOST_BEAST_WEBSOCKET_IMPL_STREAM_IPP
  10. #define BOOST_BEAST_WEBSOCKET_IMPL_STREAM_IPP
  11. #include <boost/beast/websocket/rfc6455.hpp>
  12. #include <boost/beast/websocket/teardown.hpp>
  13. #include <boost/beast/websocket/detail/hybi13.hpp>
  14. #include <boost/beast/websocket/detail/pmd_extension.hpp>
  15. #include <boost/beast/version.hpp>
  16. #include <boost/beast/http/read.hpp>
  17. #include <boost/beast/http/write.hpp>
  18. #include <boost/beast/http/rfc7230.hpp>
  19. #include <boost/beast/core/buffers_cat.hpp>
  20. #include <boost/beast/core/buffers_prefix.hpp>
  21. #include <boost/beast/core/buffers_suffix.hpp>
  22. #include <boost/beast/core/flat_static_buffer.hpp>
  23. #include <boost/beast/core/type_traits.hpp>
  24. #include <boost/beast/core/detail/clamp.hpp>
  25. #include <boost/beast/core/detail/type_traits.hpp>
  26. #include <boost/assert.hpp>
  27. #include <boost/endian/buffers.hpp>
  28. #include <boost/make_unique.hpp>
  29. #include <boost/throw_exception.hpp>
  30. #include <algorithm>
  31. #include <memory>
  32. #include <stdexcept>
  33. #include <utility>
  34. #include <iostream>
  35. namespace boost {
  36. namespace beast {
  37. namespace websocket {
  38. template<class NextLayer, bool deflateSupported>
  39. template<class... Args>
  40. stream<NextLayer, deflateSupported>::
  41. stream(Args&&... args)
  42. : stream_(std::forward<Args>(args)...)
  43. {
  44. BOOST_ASSERT(rd_buf_.max_size() >=
  45. max_control_frame_size);
  46. }
  47. template<class NextLayer, bool deflateSupported>
  48. template<class DynamicBuffer, class>
  49. std::size_t
  50. stream<NextLayer, deflateSupported>::
  51. read_size_hint(DynamicBuffer& buffer) const
  52. {
  53. static_assert(
  54. boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
  55. "DynamicBuffer requirements not met");
  56. auto const initial_size = (std::min)(
  57. +tcp_frame_size,
  58. buffer.max_size() - buffer.size());
  59. if(initial_size == 0)
  60. return 1; // buffer is full
  61. return read_size_hint(initial_size);
  62. }
  63. //------------------------------------------------------------------------------
  64. template<class NextLayer, bool deflateSupported>
  65. void
  66. stream<NextLayer, deflateSupported>::
  67. set_option(permessage_deflate const& o, std::true_type)
  68. {
  69. if( o.server_max_window_bits > 15 ||
  70. o.server_max_window_bits < 9)
  71. BOOST_THROW_EXCEPTION(std::invalid_argument{
  72. "invalid server_max_window_bits"});
  73. if( o.client_max_window_bits > 15 ||
  74. o.client_max_window_bits < 9)
  75. BOOST_THROW_EXCEPTION(std::invalid_argument{
  76. "invalid client_max_window_bits"});
  77. if( o.compLevel < 0 ||
  78. o.compLevel > 9)
  79. BOOST_THROW_EXCEPTION(std::invalid_argument{
  80. "invalid compLevel"});
  81. if( o.memLevel < 1 ||
  82. o.memLevel > 9)
  83. BOOST_THROW_EXCEPTION(std::invalid_argument{
  84. "invalid memLevel"});
  85. this->pmd_opts_ = o;
  86. }
  87. template<class NextLayer, bool deflateSupported>
  88. void
  89. stream<NextLayer, deflateSupported>::
  90. set_option(permessage_deflate const& o, std::false_type)
  91. {
  92. if(o.client_enable || o.server_enable)
  93. {
  94. // Can't enable permessage-deflate
  95. // when deflateSupported == false.
  96. //
  97. BOOST_THROW_EXCEPTION(std::invalid_argument{
  98. "deflateSupported == false"});
  99. }
  100. }
  101. template<class NextLayer, bool deflateSupported>
  102. void
  103. stream<NextLayer, deflateSupported>::
  104. open(role_type role)
  105. {
  106. // VFALCO TODO analyze and remove dupe code in reset()
  107. role_ = role;
  108. status_ = status::open;
  109. rd_remain_ = 0;
  110. rd_cont_ = false;
  111. rd_done_ = true;
  112. // Can't clear this because accept uses it
  113. //rd_buf_.reset();
  114. rd_fh_.fin = false;
  115. rd_close_ = false;
  116. wr_close_ = false;
  117. // These should not be necessary, because all completion
  118. // handlers must be allowed to execute otherwise the
  119. // stream exhibits undefined behavior.
  120. wr_block_.reset();
  121. rd_block_.reset();
  122. cr_.code = close_code::none;
  123. wr_cont_ = false;
  124. wr_buf_size_ = 0;
  125. open_pmd(is_deflate_supported{});
  126. }
  127. template<class NextLayer, bool deflateSupported>
  128. inline
  129. void
  130. stream<NextLayer, deflateSupported>::
  131. open_pmd(std::true_type)
  132. {
  133. if(((role_ == role_type::client &&
  134. this->pmd_opts_.client_enable) ||
  135. (role_ == role_type::server &&
  136. this->pmd_opts_.server_enable)) &&
  137. this->pmd_config_.accept)
  138. {
  139. pmd_normalize(this->pmd_config_);
  140. this->pmd_.reset(new typename
  141. detail::stream_base<deflateSupported>::pmd_type);
  142. if(role_ == role_type::client)
  143. {
  144. this->pmd_->zi.reset(
  145. this->pmd_config_.server_max_window_bits);
  146. this->pmd_->zo.reset(
  147. this->pmd_opts_.compLevel,
  148. this->pmd_config_.client_max_window_bits,
  149. this->pmd_opts_.memLevel,
  150. zlib::Strategy::normal);
  151. }
  152. else
  153. {
  154. this->pmd_->zi.reset(
  155. this->pmd_config_.client_max_window_bits);
  156. this->pmd_->zo.reset(
  157. this->pmd_opts_.compLevel,
  158. this->pmd_config_.server_max_window_bits,
  159. this->pmd_opts_.memLevel,
  160. zlib::Strategy::normal);
  161. }
  162. }
  163. }
  164. template<class NextLayer, bool deflateSupported>
  165. void
  166. stream<NextLayer, deflateSupported>::
  167. close()
  168. {
  169. wr_buf_.reset();
  170. close_pmd(is_deflate_supported{});
  171. }
  172. template<class NextLayer, bool deflateSupported>
  173. void
  174. stream<NextLayer, deflateSupported>::
  175. reset()
  176. {
  177. BOOST_ASSERT(status_ != status::open);
  178. rd_remain_ = 0;
  179. rd_cont_ = false;
  180. rd_done_ = true;
  181. rd_buf_.consume(rd_buf_.size());
  182. rd_fh_.fin = false;
  183. rd_close_ = false;
  184. wr_close_ = false;
  185. wr_cont_ = false;
  186. // These should not be necessary, because all completion
  187. // handlers must be allowed to execute otherwise the
  188. // stream exhibits undefined behavior.
  189. wr_block_.reset();
  190. rd_block_.reset();
  191. cr_.code = close_code::none;
  192. }
  193. // Called before each write frame
  194. template<class NextLayer, bool deflateSupported>
  195. inline
  196. void
  197. stream<NextLayer, deflateSupported>::
  198. begin_msg(std::true_type)
  199. {
  200. wr_frag_ = wr_frag_opt_;
  201. wr_compress_ = static_cast<bool>(this->pmd_);
  202. // Maintain the write buffer
  203. if( wr_compress_ ||
  204. role_ == role_type::client)
  205. {
  206. if(! wr_buf_ || wr_buf_size_ != wr_buf_opt_)
  207. {
  208. wr_buf_size_ = wr_buf_opt_;
  209. wr_buf_ = boost::make_unique_noinit<
  210. std::uint8_t[]>(wr_buf_size_);
  211. }
  212. }
  213. else
  214. {
  215. wr_buf_size_ = wr_buf_opt_;
  216. wr_buf_.reset();
  217. }
  218. }
  219. // Called before each write frame
  220. template<class NextLayer, bool deflateSupported>
  221. inline
  222. void
  223. stream<NextLayer, deflateSupported>::
  224. begin_msg(std::false_type)
  225. {
  226. wr_frag_ = wr_frag_opt_;
  227. // Maintain the write buffer
  228. if(role_ == role_type::client)
  229. {
  230. if(! wr_buf_ || wr_buf_size_ != wr_buf_opt_)
  231. {
  232. wr_buf_size_ = wr_buf_opt_;
  233. wr_buf_ = boost::make_unique_noinit<
  234. std::uint8_t[]>(wr_buf_size_);
  235. }
  236. }
  237. else
  238. {
  239. wr_buf_size_ = wr_buf_opt_;
  240. wr_buf_.reset();
  241. }
  242. }
  243. template<class NextLayer, bool deflateSupported>
  244. std::size_t
  245. stream<NextLayer, deflateSupported>::
  246. read_size_hint(
  247. std::size_t initial_size,
  248. std::true_type) const
  249. {
  250. using beast::detail::clamp;
  251. std::size_t result;
  252. BOOST_ASSERT(initial_size > 0);
  253. if(! this->pmd_ || (! rd_done_ && ! this->pmd_->rd_set))
  254. {
  255. // current message is uncompressed
  256. if(rd_done_)
  257. {
  258. // first message frame
  259. result = initial_size;
  260. goto done;
  261. }
  262. else if(rd_fh_.fin)
  263. {
  264. // last message frame
  265. BOOST_ASSERT(rd_remain_ > 0);
  266. result = clamp(rd_remain_);
  267. goto done;
  268. }
  269. }
  270. result = (std::max)(
  271. initial_size, clamp(rd_remain_));
  272. done:
  273. BOOST_ASSERT(result != 0);
  274. return result;
  275. }
  276. template<class NextLayer, bool deflateSupported>
  277. std::size_t
  278. stream<NextLayer, deflateSupported>::
  279. read_size_hint(
  280. std::size_t initial_size,
  281. std::false_type) const
  282. {
  283. using beast::detail::clamp;
  284. std::size_t result;
  285. BOOST_ASSERT(initial_size > 0);
  286. // compression is not supported
  287. if(rd_done_)
  288. {
  289. // first message frame
  290. result = initial_size;
  291. }
  292. else if(rd_fh_.fin)
  293. {
  294. // last message frame
  295. BOOST_ASSERT(rd_remain_ > 0);
  296. result = clamp(rd_remain_);
  297. }
  298. else
  299. {
  300. result = (std::max)(
  301. initial_size, clamp(rd_remain_));
  302. }
  303. BOOST_ASSERT(result != 0);
  304. return result;
  305. }
  306. //------------------------------------------------------------------------------
  307. // Attempt to read a complete frame header.
  308. // Returns `false` if more bytes are needed
  309. template<class NextLayer, bool deflateSupported>
  310. template<class DynamicBuffer>
  311. bool
  312. stream<NextLayer, deflateSupported>::
  313. parse_fh(
  314. detail::frame_header& fh,
  315. DynamicBuffer& b,
  316. error_code& ec)
  317. {
  318. using boost::asio::buffer;
  319. using boost::asio::buffer_copy;
  320. using boost::asio::buffer_size;
  321. if(buffer_size(b.data()) < 2)
  322. {
  323. // need more bytes
  324. ec.assign(0, ec.category());
  325. return false;
  326. }
  327. buffers_suffix<typename
  328. DynamicBuffer::const_buffers_type> cb{
  329. b.data()};
  330. std::size_t need;
  331. {
  332. std::uint8_t tmp[2];
  333. cb.consume(buffer_copy(buffer(tmp), cb));
  334. fh.len = tmp[1] & 0x7f;
  335. switch(fh.len)
  336. {
  337. case 126: need = 2; break;
  338. case 127: need = 8; break;
  339. default:
  340. need = 0;
  341. }
  342. fh.mask = (tmp[1] & 0x80) != 0;
  343. if(fh.mask)
  344. need += 4;
  345. if(buffer_size(cb) < need)
  346. {
  347. // need more bytes
  348. ec.assign(0, ec.category());
  349. return false;
  350. }
  351. fh.op = static_cast<
  352. detail::opcode>(tmp[0] & 0x0f);
  353. fh.fin = (tmp[0] & 0x80) != 0;
  354. fh.rsv1 = (tmp[0] & 0x40) != 0;
  355. fh.rsv2 = (tmp[0] & 0x20) != 0;
  356. fh.rsv3 = (tmp[0] & 0x10) != 0;
  357. }
  358. switch(fh.op)
  359. {
  360. case detail::opcode::binary:
  361. case detail::opcode::text:
  362. if(rd_cont_)
  363. {
  364. // new data frame when continuation expected
  365. ec = error::bad_data_frame;
  366. return false;
  367. }
  368. if(fh.rsv2 || fh.rsv3 ||
  369. ! this->rd_deflated(fh.rsv1))
  370. {
  371. // reserved bits not cleared
  372. ec = error::bad_reserved_bits;
  373. return false;
  374. }
  375. break;
  376. case detail::opcode::cont:
  377. if(! rd_cont_)
  378. {
  379. // continuation without an active message
  380. ec = error::bad_continuation;
  381. return false;
  382. }
  383. if(fh.rsv1 || fh.rsv2 || fh.rsv3)
  384. {
  385. // reserved bits not cleared
  386. ec = error::bad_reserved_bits;
  387. return false;
  388. }
  389. break;
  390. default:
  391. if(detail::is_reserved(fh.op))
  392. {
  393. // reserved opcode
  394. ec = error::bad_opcode;
  395. return false;
  396. }
  397. if(! fh.fin)
  398. {
  399. // fragmented control message
  400. ec = error::bad_control_fragment;
  401. return false;
  402. }
  403. if(fh.len > 125)
  404. {
  405. // invalid length for control message
  406. ec = error::bad_control_size;
  407. return false;
  408. }
  409. if(fh.rsv1 || fh.rsv2 || fh.rsv3)
  410. {
  411. // reserved bits not cleared
  412. ec = error::bad_reserved_bits;
  413. return false;
  414. }
  415. break;
  416. }
  417. if(role_ == role_type::server && ! fh.mask)
  418. {
  419. // unmasked frame from client
  420. ec = error::bad_unmasked_frame;
  421. return false;
  422. }
  423. if(role_ == role_type::client && fh.mask)
  424. {
  425. // masked frame from server
  426. ec = error::bad_masked_frame;
  427. return false;
  428. }
  429. if(detail::is_control(fh.op) &&
  430. buffer_size(cb) < need + fh.len)
  431. {
  432. // Make the entire control frame payload
  433. // get read in before we return `true`
  434. return false;
  435. }
  436. switch(fh.len)
  437. {
  438. case 126:
  439. {
  440. std::uint8_t tmp[2];
  441. BOOST_ASSERT(buffer_size(cb) >= sizeof(tmp));
  442. cb.consume(buffer_copy(buffer(tmp), cb));
  443. fh.len = detail::big_uint16_to_native(&tmp[0]);
  444. if(fh.len < 126)
  445. {
  446. // length not canonical
  447. ec = error::bad_size;
  448. return false;
  449. }
  450. break;
  451. }
  452. case 127:
  453. {
  454. std::uint8_t tmp[8];
  455. BOOST_ASSERT(buffer_size(cb) >= sizeof(tmp));
  456. cb.consume(buffer_copy(buffer(tmp), cb));
  457. fh.len = detail::big_uint64_to_native(&tmp[0]);
  458. if(fh.len < 65536)
  459. {
  460. // length not canonical
  461. ec = error::bad_size;
  462. return false;
  463. }
  464. break;
  465. }
  466. }
  467. if(fh.mask)
  468. {
  469. std::uint8_t tmp[4];
  470. BOOST_ASSERT(buffer_size(cb) >= sizeof(tmp));
  471. cb.consume(buffer_copy(buffer(tmp), cb));
  472. fh.key = detail::little_uint32_to_native(&tmp[0]);
  473. detail::prepare_key(rd_key_, fh.key);
  474. }
  475. else
  476. {
  477. // initialize this otherwise operator== breaks
  478. fh.key = 0;
  479. }
  480. if(! detail::is_control(fh.op))
  481. {
  482. if(fh.op != detail::opcode::cont)
  483. {
  484. rd_size_ = 0;
  485. rd_op_ = fh.op;
  486. }
  487. else
  488. {
  489. if(rd_size_ > (std::numeric_limits<
  490. std::uint64_t>::max)() - fh.len)
  491. {
  492. // message size exceeds configured limit
  493. ec = error::message_too_big;
  494. return false;
  495. }
  496. }
  497. if(! this->rd_deflated())
  498. {
  499. if(rd_msg_max_ && beast::detail::sum_exceeds(
  500. rd_size_, fh.len, rd_msg_max_))
  501. {
  502. // message size exceeds configured limit
  503. ec = error::message_too_big;
  504. return false;
  505. }
  506. }
  507. rd_cont_ = ! fh.fin;
  508. rd_remain_ = fh.len;
  509. }
  510. b.consume(b.size() - buffer_size(cb));
  511. ec.assign(0, ec.category());
  512. return true;
  513. }
  514. template<class NextLayer, bool deflateSupported>
  515. template<class DynamicBuffer>
  516. void
  517. stream<NextLayer, deflateSupported>::
  518. write_close(DynamicBuffer& db, close_reason const& cr)
  519. {
  520. using namespace boost::endian;
  521. detail::frame_header fh;
  522. fh.op = detail::opcode::close;
  523. fh.fin = true;
  524. fh.rsv1 = false;
  525. fh.rsv2 = false;
  526. fh.rsv3 = false;
  527. fh.len = cr.code == close_code::none ?
  528. 0 : 2 + cr.reason.size();
  529. if(role_ == role_type::client)
  530. {
  531. fh.mask = true;
  532. fh.key = this->create_mask();
  533. }
  534. else
  535. {
  536. fh.mask = false;
  537. }
  538. detail::write(db, fh);
  539. if(cr.code != close_code::none)
  540. {
  541. detail::prepared_key key;
  542. if(fh.mask)
  543. detail::prepare_key(key, fh.key);
  544. {
  545. std::uint8_t tmp[2];
  546. ::new(&tmp[0]) big_uint16_buf_t{
  547. (std::uint16_t)cr.code};
  548. auto mb = db.prepare(2);
  549. boost::asio::buffer_copy(mb,
  550. boost::asio::buffer(tmp));
  551. if(fh.mask)
  552. detail::mask_inplace(mb, key);
  553. db.commit(2);
  554. }
  555. if(! cr.reason.empty())
  556. {
  557. auto mb = db.prepare(cr.reason.size());
  558. boost::asio::buffer_copy(mb,
  559. boost::asio::const_buffer(
  560. cr.reason.data(), cr.reason.size()));
  561. if(fh.mask)
  562. detail::mask_inplace(mb, key);
  563. db.commit(cr.reason.size());
  564. }
  565. }
  566. }
  567. template<class NextLayer, bool deflateSupported>
  568. template<class DynamicBuffer>
  569. void
  570. stream<NextLayer, deflateSupported>::
  571. write_ping(DynamicBuffer& db,
  572. detail::opcode code, ping_data const& data)
  573. {
  574. detail::frame_header fh;
  575. fh.op = code;
  576. fh.fin = true;
  577. fh.rsv1 = false;
  578. fh.rsv2 = false;
  579. fh.rsv3 = false;
  580. fh.len = data.size();
  581. fh.mask = role_ == role_type::client;
  582. if(fh.mask)
  583. fh.key = this->create_mask();
  584. detail::write(db, fh);
  585. if(data.empty())
  586. return;
  587. detail::prepared_key key;
  588. if(fh.mask)
  589. detail::prepare_key(key, fh.key);
  590. auto mb = db.prepare(data.size());
  591. boost::asio::buffer_copy(mb,
  592. boost::asio::const_buffer(
  593. data.data(), data.size()));
  594. if(fh.mask)
  595. detail::mask_inplace(mb, key);
  596. db.commit(data.size());
  597. }
  598. //------------------------------------------------------------------------------
  599. template<class NextLayer, bool deflateSupported>
  600. template<class Decorator>
  601. request_type
  602. stream<NextLayer, deflateSupported>::
  603. build_request(detail::sec_ws_key_type& key,
  604. string_view host, string_view target,
  605. Decorator const& decorator)
  606. {
  607. request_type req;
  608. req.target(target);
  609. req.version(11);
  610. req.method(http::verb::get);
  611. req.set(http::field::host, host);
  612. req.set(http::field::upgrade, "websocket");
  613. req.set(http::field::connection, "upgrade");
  614. detail::make_sec_ws_key(key);
  615. req.set(http::field::sec_websocket_key, key);
  616. req.set(http::field::sec_websocket_version, "13");
  617. build_request_pmd(req, is_deflate_supported{});
  618. decorator(req);
  619. if(! req.count(http::field::user_agent))
  620. req.set(http::field::user_agent,
  621. BOOST_BEAST_VERSION_STRING);
  622. return req;
  623. }
  624. template<class NextLayer, bool deflateSupported>
  625. inline
  626. void
  627. stream<NextLayer, deflateSupported>::
  628. build_request_pmd(request_type& req, std::true_type)
  629. {
  630. if(this->pmd_opts_.client_enable)
  631. {
  632. detail::pmd_offer config;
  633. config.accept = true;
  634. config.server_max_window_bits =
  635. this->pmd_opts_.server_max_window_bits;
  636. config.client_max_window_bits =
  637. this->pmd_opts_.client_max_window_bits;
  638. config.server_no_context_takeover =
  639. this->pmd_opts_.server_no_context_takeover;
  640. config.client_no_context_takeover =
  641. this->pmd_opts_.client_no_context_takeover;
  642. detail::pmd_write(req, config);
  643. }
  644. }
  645. template<class NextLayer, bool deflateSupported>
  646. template<class Body, class Allocator, class Decorator>
  647. response_type
  648. stream<NextLayer, deflateSupported>::
  649. build_response(
  650. http::request<Body,
  651. http::basic_fields<Allocator>> const& req,
  652. Decorator const& decorator,
  653. error_code& result)
  654. {
  655. auto const decorate =
  656. [&decorator](response_type& res)
  657. {
  658. decorator(res);
  659. if(! res.count(http::field::server))
  660. {
  661. BOOST_STATIC_ASSERT(sizeof(BOOST_BEAST_VERSION_STRING) < 20);
  662. static_string<20> s(BOOST_BEAST_VERSION_STRING);
  663. res.set(http::field::server, s);
  664. }
  665. };
  666. auto err =
  667. [&](error e)
  668. {
  669. result = e;
  670. response_type res;
  671. res.version(req.version());
  672. res.result(http::status::bad_request);
  673. res.body() = result.message();
  674. res.prepare_payload();
  675. decorate(res);
  676. return res;
  677. };
  678. if(req.version() != 11)
  679. return err(error::bad_http_version);
  680. if(req.method() != http::verb::get)
  681. return err(error::bad_method);
  682. if(! req.count(http::field::host))
  683. return err(error::no_host);
  684. {
  685. auto const it = req.find(http::field::connection);
  686. if(it == req.end())
  687. return err(error::no_connection);
  688. if(! http::token_list{it->value()}.exists("upgrade"))
  689. return err(error::no_connection_upgrade);
  690. }
  691. {
  692. auto const it = req.find(http::field::upgrade);
  693. if(it == req.end())
  694. return err(error::no_upgrade);
  695. if(! http::token_list{it->value()}.exists("websocket"))
  696. return err(error::no_upgrade_websocket);
  697. }
  698. string_view key;
  699. {
  700. auto const it = req.find(http::field::sec_websocket_key);
  701. if(it == req.end())
  702. return err(error::no_sec_key);
  703. key = it->value();
  704. if(key.size() > detail::sec_ws_key_type::max_size_n)
  705. return err(error::bad_sec_key);
  706. }
  707. {
  708. auto const it = req.find(http::field::sec_websocket_version);
  709. if(it == req.end())
  710. return err(error::no_sec_version);
  711. if(it->value() != "13")
  712. {
  713. response_type res;
  714. res.result(http::status::upgrade_required);
  715. res.version(req.version());
  716. res.set(http::field::sec_websocket_version, "13");
  717. result = error::bad_sec_version;
  718. res.body() = result.message();
  719. res.prepare_payload();
  720. decorate(res);
  721. return res;
  722. }
  723. }
  724. response_type res;
  725. res.result(http::status::switching_protocols);
  726. res.version(req.version());
  727. res.set(http::field::upgrade, "websocket");
  728. res.set(http::field::connection, "upgrade");
  729. {
  730. detail::sec_ws_accept_type acc;
  731. detail::make_sec_ws_accept(acc, key);
  732. res.set(http::field::sec_websocket_accept, acc);
  733. }
  734. build_response_pmd(res, req, is_deflate_supported{});
  735. decorate(res);
  736. result = {};
  737. return res;
  738. }
  739. template<class NextLayer, bool deflateSupported>
  740. template<class Body, class Allocator>
  741. inline
  742. void
  743. stream<NextLayer, deflateSupported>::
  744. build_response_pmd(
  745. response_type& res,
  746. http::request<Body,
  747. http::basic_fields<Allocator>> const& req,
  748. std::true_type)
  749. {
  750. detail::pmd_offer offer;
  751. detail::pmd_offer unused;
  752. pmd_read(offer, req);
  753. pmd_negotiate(res, unused, offer, this->pmd_opts_);
  754. }
  755. // Called when the WebSocket Upgrade response is received
  756. template<class NextLayer, bool deflateSupported>
  757. void
  758. stream<NextLayer, deflateSupported>::
  759. on_response(
  760. response_type const& res,
  761. detail::sec_ws_key_type const& key,
  762. error_code& ec)
  763. {
  764. auto const err =
  765. [&](error e)
  766. {
  767. ec = e;
  768. };
  769. if(res.result() != http::status::switching_protocols)
  770. return err(error::upgrade_declined);
  771. if(res.version() != 11)
  772. return err(error::bad_http_version);
  773. {
  774. auto const it = res.find(http::field::connection);
  775. if(it == res.end())
  776. return err(error::no_connection);
  777. if(! http::token_list{it->value()}.exists("upgrade"))
  778. return err(error::no_connection_upgrade);
  779. }
  780. {
  781. auto const it = res.find(http::field::upgrade);
  782. if(it == res.end())
  783. return err(error::no_upgrade);
  784. if(! http::token_list{it->value()}.exists("websocket"))
  785. return err(error::no_upgrade_websocket);
  786. }
  787. {
  788. auto const it = res.find(http::field::sec_websocket_accept);
  789. if(it == res.end())
  790. return err(error::no_sec_accept);
  791. detail::sec_ws_accept_type acc;
  792. detail::make_sec_ws_accept(acc, key);
  793. if(acc.compare(it->value()) != 0)
  794. return err(error::bad_sec_accept);
  795. }
  796. ec.assign(0, ec.category());
  797. on_response_pmd(res, is_deflate_supported{});
  798. open(role_type::client);
  799. }
  800. template<class NextLayer, bool deflateSupported>
  801. inline
  802. void
  803. stream<NextLayer, deflateSupported>::
  804. on_response_pmd(
  805. response_type const& res,
  806. std::true_type)
  807. {
  808. detail::pmd_offer offer;
  809. pmd_read(offer, res);
  810. // VFALCO see if offer satisfies pmd_config_,
  811. // return an error if not.
  812. this->pmd_config_ = offer; // overwrite for now
  813. }
  814. // _Fail the WebSocket Connection_
  815. template<class NextLayer, bool deflateSupported>
  816. void
  817. stream<NextLayer, deflateSupported>::
  818. do_fail(
  819. std::uint16_t code, // if set, send a close frame first
  820. error_code ev, // error code to use upon success
  821. error_code& ec) // set to the error, else set to ev
  822. {
  823. BOOST_ASSERT(ev);
  824. status_ = status::closing;
  825. if(code != close_code::none && ! wr_close_)
  826. {
  827. wr_close_ = true;
  828. detail::frame_buffer fb;
  829. write_close<
  830. flat_static_buffer_base>(fb, code);
  831. boost::asio::write(stream_, fb.data(), ec);
  832. if(! check_ok(ec))
  833. return;
  834. }
  835. using beast::websocket::teardown;
  836. teardown(role_, stream_, ec);
  837. if(ec == boost::asio::error::eof)
  838. {
  839. // Rationale:
  840. // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
  841. ec.assign(0, ec.category());
  842. }
  843. if(! ec)
  844. ec = ev;
  845. if(ec && ec != error::closed)
  846. status_ = status::failed;
  847. else
  848. status_ = status::closed;
  849. close();
  850. }
  851. } // websocket
  852. } // beast
  853. } // boost
  854. #endif