connection_impl.hpp 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332
  1. /*
  2. * Copyright (c) 2014, Peter Thorson. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the WebSocket++ Project nor the
  12. * names of its contributors may be used to endorse or promote products
  13. * derived from this software without specific prior written permission.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
  19. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. *
  26. */
  27. #ifndef WEBSOCKETPP_CONNECTION_IMPL_HPP
  28. #define WEBSOCKETPP_CONNECTION_IMPL_HPP
  29. #include <websocketpp/processors/hybi00.hpp>
  30. #include <websocketpp/processors/hybi07.hpp>
  31. #include <websocketpp/processors/hybi08.hpp>
  32. #include <websocketpp/processors/hybi13.hpp>
  33. #include <websocketpp/processors/processor.hpp>
  34. #include <websocketpp/common/platforms.hpp>
  35. #include <websocketpp/common/system_error.hpp>
  36. #include <algorithm>
  37. #include <exception>
  38. #include <sstream>
  39. #include <string>
  40. #include <utility>
  41. #include <vector>
  42. namespace websocketpp {
  43. namespace istate = session::internal_state;
  44. template <typename config>
  45. void connection<config>::set_termination_handler(
  46. termination_handler new_handler)
  47. {
  48. m_alog.write(log::alevel::devel,
  49. "connection set_termination_handler");
  50. //scoped_lock_type lock(m_connection_state_lock);
  51. m_termination_handler = new_handler;
  52. }
  53. template <typename config>
  54. std::string const & connection<config>::get_origin() const {
  55. //scoped_lock_type lock(m_connection_state_lock);
  56. return m_processor->get_origin(m_request);
  57. }
  58. template <typename config>
  59. size_t connection<config>::get_buffered_amount() const {
  60. //scoped_lock_type lock(m_connection_state_lock);
  61. return m_send_buffer_size;
  62. }
  63. template <typename config>
  64. session::state::value connection<config>::get_state() const {
  65. //scoped_lock_type lock(m_connection_state_lock);
  66. return m_state;
  67. }
  68. template <typename config>
  69. lib::error_code connection<config>::send(std::string const & payload,
  70. frame::opcode::value op)
  71. {
  72. message_ptr msg = m_msg_manager->get_message(op,payload.size());
  73. msg->append_payload(payload);
  74. return send(msg);
  75. }
  76. template <typename config>
  77. lib::error_code connection<config>::send(void const * payload, size_t len,
  78. frame::opcode::value op)
  79. {
  80. message_ptr msg = m_msg_manager->get_message(op,len);
  81. msg->append_payload(payload,len);
  82. return send(msg);
  83. }
  84. template <typename config>
  85. lib::error_code connection<config>::send(typename config::message_type::ptr msg)
  86. {
  87. if (m_alog.static_test(log::alevel::devel)) {
  88. m_alog.write(log::alevel::devel,"connection send");
  89. }
  90. {
  91. scoped_lock_type lock(m_connection_state_lock);
  92. if (m_state != session::state::open) {
  93. return error::make_error_code(error::invalid_state);
  94. }
  95. }
  96. message_ptr outgoing_msg;
  97. bool needs_writing = false;
  98. if (msg->get_prepared()) {
  99. outgoing_msg = msg;
  100. scoped_lock_type lock(m_write_lock);
  101. write_push(outgoing_msg);
  102. needs_writing = !m_write_flag && !m_send_queue.empty();
  103. } else {
  104. outgoing_msg = m_msg_manager->get_message();
  105. if (!outgoing_msg) {
  106. return error::make_error_code(error::no_outgoing_buffers);
  107. }
  108. scoped_lock_type lock(m_write_lock);
  109. lib::error_code ec = m_processor->prepare_data_frame(msg,outgoing_msg);
  110. if (ec) {
  111. return ec;
  112. }
  113. write_push(outgoing_msg);
  114. needs_writing = !m_write_flag && !m_send_queue.empty();
  115. }
  116. if (needs_writing) {
  117. transport_con_type::dispatch(lib::bind(
  118. &type::write_frame,
  119. type::get_shared()
  120. ));
  121. }
  122. return lib::error_code();
  123. }
  124. template <typename config>
  125. void connection<config>::ping(std::string const& payload, lib::error_code& ec) {
  126. if (m_alog.static_test(log::alevel::devel)) {
  127. m_alog.write(log::alevel::devel,"connection ping");
  128. }
  129. {
  130. scoped_lock_type lock(m_connection_state_lock);
  131. if (m_state != session::state::open) {
  132. std::stringstream ss;
  133. ss << "connection::ping called from invalid state " << m_state;
  134. m_alog.write(log::alevel::devel,ss.str());
  135. ec = error::make_error_code(error::invalid_state);
  136. return;
  137. }
  138. }
  139. message_ptr msg = m_msg_manager->get_message();
  140. if (!msg) {
  141. ec = error::make_error_code(error::no_outgoing_buffers);
  142. return;
  143. }
  144. ec = m_processor->prepare_ping(payload,msg);
  145. if (ec) {return;}
  146. // set ping timer if we are listening for one
  147. if (m_pong_timeout_handler) {
  148. // Cancel any existing timers
  149. if (m_ping_timer) {
  150. m_ping_timer->cancel();
  151. }
  152. if (m_pong_timeout_dur > 0) {
  153. m_ping_timer = transport_con_type::set_timer(
  154. m_pong_timeout_dur,
  155. lib::bind(
  156. &type::handle_pong_timeout,
  157. type::get_shared(),
  158. payload,
  159. lib::placeholders::_1
  160. )
  161. );
  162. }
  163. if (!m_ping_timer) {
  164. // Our transport doesn't support timers
  165. m_elog.write(log::elevel::warn,"Warning: a pong_timeout_handler is \
  166. set but the transport in use does not support timeouts.");
  167. }
  168. }
  169. bool needs_writing = false;
  170. {
  171. scoped_lock_type lock(m_write_lock);
  172. write_push(msg);
  173. needs_writing = !m_write_flag && !m_send_queue.empty();
  174. }
  175. if (needs_writing) {
  176. transport_con_type::dispatch(lib::bind(
  177. &type::write_frame,
  178. type::get_shared()
  179. ));
  180. }
  181. ec = lib::error_code();
  182. }
  183. template<typename config>
  184. void connection<config>::ping(std::string const & payload) {
  185. lib::error_code ec;
  186. ping(payload,ec);
  187. if (ec) {
  188. throw exception(ec);
  189. }
  190. }
  191. template<typename config>
  192. void connection<config>::handle_pong_timeout(std::string payload,
  193. lib::error_code const & ec)
  194. {
  195. if (ec) {
  196. if (ec == transport::error::operation_aborted) {
  197. // ignore, this is expected
  198. return;
  199. }
  200. m_elog.write(log::elevel::devel,"pong_timeout error: "+ec.message());
  201. return;
  202. }
  203. if (m_pong_timeout_handler) {
  204. m_pong_timeout_handler(m_connection_hdl,payload);
  205. }
  206. }
  207. template <typename config>
  208. void connection<config>::pong(std::string const& payload, lib::error_code& ec) {
  209. if (m_alog.static_test(log::alevel::devel)) {
  210. m_alog.write(log::alevel::devel,"connection pong");
  211. }
  212. {
  213. scoped_lock_type lock(m_connection_state_lock);
  214. if (m_state != session::state::open) {
  215. std::stringstream ss;
  216. ss << "connection::pong called from invalid state " << m_state;
  217. m_alog.write(log::alevel::devel,ss.str());
  218. ec = error::make_error_code(error::invalid_state);
  219. return;
  220. }
  221. }
  222. message_ptr msg = m_msg_manager->get_message();
  223. if (!msg) {
  224. ec = error::make_error_code(error::no_outgoing_buffers);
  225. return;
  226. }
  227. ec = m_processor->prepare_pong(payload,msg);
  228. if (ec) {return;}
  229. bool needs_writing = false;
  230. {
  231. scoped_lock_type lock(m_write_lock);
  232. write_push(msg);
  233. needs_writing = !m_write_flag && !m_send_queue.empty();
  234. }
  235. if (needs_writing) {
  236. transport_con_type::dispatch(lib::bind(
  237. &type::write_frame,
  238. type::get_shared()
  239. ));
  240. }
  241. ec = lib::error_code();
  242. }
  243. template<typename config>
  244. void connection<config>::pong(std::string const & payload) {
  245. lib::error_code ec;
  246. pong(payload,ec);
  247. if (ec) {
  248. throw exception(ec);
  249. }
  250. }
  251. template <typename config>
  252. void connection<config>::close(close::status::value const code,
  253. std::string const & reason, lib::error_code & ec)
  254. {
  255. if (m_alog.static_test(log::alevel::devel)) {
  256. m_alog.write(log::alevel::devel,"connection close");
  257. }
  258. // Truncate reason to maximum size allowable in a close frame.
  259. std::string tr(reason,0,std::min<size_t>(reason.size(),
  260. frame::limits::close_reason_size));
  261. scoped_lock_type lock(m_connection_state_lock);
  262. if (m_state != session::state::open) {
  263. ec = error::make_error_code(error::invalid_state);
  264. return;
  265. }
  266. ec = this->send_close_frame(code,tr,false,close::status::terminal(code));
  267. }
  268. template<typename config>
  269. void connection<config>::close(close::status::value const code,
  270. std::string const & reason)
  271. {
  272. lib::error_code ec;
  273. close(code,reason,ec);
  274. if (ec) {
  275. throw exception(ec);
  276. }
  277. }
  278. /// Trigger the on_interrupt handler
  279. /**
  280. * This is thread safe if the transport is thread safe
  281. */
  282. template <typename config>
  283. lib::error_code connection<config>::interrupt() {
  284. m_alog.write(log::alevel::devel,"connection connection::interrupt");
  285. return transport_con_type::interrupt(
  286. lib::bind(
  287. &type::handle_interrupt,
  288. type::get_shared()
  289. )
  290. );
  291. }
  292. template <typename config>
  293. void connection<config>::handle_interrupt() {
  294. if (m_interrupt_handler) {
  295. m_interrupt_handler(m_connection_hdl);
  296. }
  297. }
  298. template <typename config>
  299. lib::error_code connection<config>::pause_reading() {
  300. m_alog.write(log::alevel::devel,"connection connection::pause_reading");
  301. return transport_con_type::dispatch(
  302. lib::bind(
  303. &type::handle_pause_reading,
  304. type::get_shared()
  305. )
  306. );
  307. }
  308. /// Pause reading handler. Not safe to call directly
  309. template <typename config>
  310. void connection<config>::handle_pause_reading() {
  311. m_alog.write(log::alevel::devel,"connection connection::handle_pause_reading");
  312. m_read_flag = false;
  313. }
  314. template <typename config>
  315. lib::error_code connection<config>::resume_reading() {
  316. m_alog.write(log::alevel::devel,"connection connection::resume_reading");
  317. return transport_con_type::dispatch(
  318. lib::bind(
  319. &type::handle_resume_reading,
  320. type::get_shared()
  321. )
  322. );
  323. }
  324. /// Resume reading helper method. Not safe to call directly
  325. template <typename config>
  326. void connection<config>::handle_resume_reading() {
  327. m_read_flag = true;
  328. read_frame();
  329. }
  330. template <typename config>
  331. bool connection<config>::get_secure() const {
  332. //scoped_lock_type lock(m_connection_state_lock);
  333. return m_uri->get_secure();
  334. }
  335. template <typename config>
  336. std::string const & connection<config>::get_host() const {
  337. //scoped_lock_type lock(m_connection_state_lock);
  338. return m_uri->get_host();
  339. }
  340. template <typename config>
  341. std::string const & connection<config>::get_resource() const {
  342. //scoped_lock_type lock(m_connection_state_lock);
  343. return m_uri->get_resource();
  344. }
  345. template <typename config>
  346. uint16_t connection<config>::get_port() const {
  347. //scoped_lock_type lock(m_connection_state_lock);
  348. return m_uri->get_port();
  349. }
  350. template <typename config>
  351. uri_ptr connection<config>::get_uri() const {
  352. //scoped_lock_type lock(m_connection_state_lock);
  353. return m_uri;
  354. }
  355. template <typename config>
  356. void connection<config>::set_uri(uri_ptr uri) {
  357. //scoped_lock_type lock(m_connection_state_lock);
  358. m_uri = uri;
  359. }
  360. template <typename config>
  361. std::string const & connection<config>::get_subprotocol() const {
  362. return m_subprotocol;
  363. }
  364. template <typename config>
  365. std::vector<std::string> const &
  366. connection<config>::get_requested_subprotocols() const {
  367. return m_requested_subprotocols;
  368. }
  369. template <typename config>
  370. void connection<config>::add_subprotocol(std::string const & value,
  371. lib::error_code & ec)
  372. {
  373. if (m_is_server) {
  374. ec = error::make_error_code(error::client_only);
  375. return;
  376. }
  377. // If the value is empty or has a non-RFC2616 token character it is invalid.
  378. if (value.empty() || std::find_if(value.begin(),value.end(),
  379. http::is_not_token_char) != value.end())
  380. {
  381. ec = error::make_error_code(error::invalid_subprotocol);
  382. return;
  383. }
  384. m_requested_subprotocols.push_back(value);
  385. }
  386. template <typename config>
  387. void connection<config>::add_subprotocol(std::string const & value) {
  388. lib::error_code ec;
  389. this->add_subprotocol(value,ec);
  390. if (ec) {
  391. throw exception(ec);
  392. }
  393. }
  394. template <typename config>
  395. void connection<config>::select_subprotocol(std::string const & value,
  396. lib::error_code & ec)
  397. {
  398. if (!m_is_server) {
  399. ec = error::make_error_code(error::server_only);
  400. return;
  401. }
  402. if (value.empty()) {
  403. ec = lib::error_code();
  404. return;
  405. }
  406. std::vector<std::string>::iterator it;
  407. it = std::find(m_requested_subprotocols.begin(),
  408. m_requested_subprotocols.end(),
  409. value);
  410. if (it == m_requested_subprotocols.end()) {
  411. ec = error::make_error_code(error::unrequested_subprotocol);
  412. return;
  413. }
  414. m_subprotocol = value;
  415. }
  416. template <typename config>
  417. void connection<config>::select_subprotocol(std::string const & value) {
  418. lib::error_code ec;
  419. this->select_subprotocol(value,ec);
  420. if (ec) {
  421. throw exception(ec);
  422. }
  423. }
  424. template <typename config>
  425. std::string const &
  426. connection<config>::get_request_header(std::string const & key) const {
  427. return m_request.get_header(key);
  428. }
  429. template <typename config>
  430. std::string const &
  431. connection<config>::get_request_body() const {
  432. return m_request.get_body();
  433. }
  434. template <typename config>
  435. std::string const &
  436. connection<config>::get_response_header(std::string const & key) const {
  437. return m_response.get_header(key);
  438. }
  439. template <typename config>
  440. void connection<config>::set_status(http::status_code::value code)
  441. {
  442. if (m_internal_state != istate::PROCESS_HTTP_REQUEST) {
  443. throw exception("Call to set_status from invalid state",
  444. error::make_error_code(error::invalid_state));
  445. }
  446. m_response.set_status(code);
  447. }
  448. template <typename config>
  449. void connection<config>::set_status(http::status_code::value code,
  450. std::string const & msg)
  451. {
  452. if (m_internal_state != istate::PROCESS_HTTP_REQUEST) {
  453. throw exception("Call to set_status from invalid state",
  454. error::make_error_code(error::invalid_state));
  455. }
  456. m_response.set_status(code,msg);
  457. }
  458. template <typename config>
  459. void connection<config>::set_body(std::string const & value) {
  460. if (m_internal_state != istate::PROCESS_HTTP_REQUEST) {
  461. throw exception("Call to set_status from invalid state",
  462. error::make_error_code(error::invalid_state));
  463. }
  464. m_response.set_body(value);
  465. }
  466. template <typename config>
  467. void connection<config>::append_header(std::string const & key,
  468. std::string const & val)
  469. {
  470. if (m_is_server) {
  471. if (m_internal_state == istate::PROCESS_HTTP_REQUEST) {
  472. // we are setting response headers for an incoming server connection
  473. m_response.append_header(key,val);
  474. } else {
  475. throw exception("Call to append_header from invalid state",
  476. error::make_error_code(error::invalid_state));
  477. }
  478. } else {
  479. if (m_internal_state == istate::USER_INIT) {
  480. // we are setting initial headers for an outgoing client connection
  481. m_request.append_header(key,val);
  482. } else {
  483. throw exception("Call to append_header from invalid state",
  484. error::make_error_code(error::invalid_state));
  485. }
  486. }
  487. }
  488. template <typename config>
  489. void connection<config>::replace_header(std::string const & key,
  490. std::string const & val)
  491. {
  492. if (m_is_server) {
  493. if (m_internal_state == istate::PROCESS_HTTP_REQUEST) {
  494. // we are setting response headers for an incoming server connection
  495. m_response.replace_header(key,val);
  496. } else {
  497. throw exception("Call to replace_header from invalid state",
  498. error::make_error_code(error::invalid_state));
  499. }
  500. } else {
  501. if (m_internal_state == istate::USER_INIT) {
  502. // we are setting initial headers for an outgoing client connection
  503. m_request.replace_header(key,val);
  504. } else {
  505. throw exception("Call to replace_header from invalid state",
  506. error::make_error_code(error::invalid_state));
  507. }
  508. }
  509. }
  510. template <typename config>
  511. void connection<config>::remove_header(std::string const & key)
  512. {
  513. if (m_is_server) {
  514. if (m_internal_state == istate::PROCESS_HTTP_REQUEST) {
  515. // we are setting response headers for an incoming server connection
  516. m_response.remove_header(key);
  517. } else {
  518. throw exception("Call to remove_header from invalid state",
  519. error::make_error_code(error::invalid_state));
  520. }
  521. } else {
  522. if (m_internal_state == istate::USER_INIT) {
  523. // we are setting initial headers for an outgoing client connection
  524. m_request.remove_header(key);
  525. } else {
  526. throw exception("Call to remove_header from invalid state",
  527. error::make_error_code(error::invalid_state));
  528. }
  529. }
  530. }
  531. /// Defer HTTP Response until later
  532. /**
  533. * Used in the http handler to defer the HTTP response for this connection
  534. * until later. Handshake timers will be canceled and the connection will be
  535. * left open until `send_http_response` or an equivalent is called.
  536. *
  537. * Warning: deferred connections won't time out and as a result can tie up
  538. * resources.
  539. *
  540. * @return A status code, zero on success, non-zero otherwise
  541. */
  542. template <typename config>
  543. lib::error_code connection<config>::defer_http_response() {
  544. // Cancel handshake timer, otherwise the connection will time out and we'll
  545. // close the connection before the app has a chance to send a response.
  546. if (m_handshake_timer) {
  547. m_handshake_timer->cancel();
  548. m_handshake_timer.reset();
  549. }
  550. // Do something to signal deferral
  551. m_http_state = session::http_state::deferred;
  552. return lib::error_code();
  553. }
  554. /// Send deferred HTTP Response (exception free)
  555. /**
  556. * Sends an http response to an HTTP connection that was deferred. This will
  557. * send a complete response including all headers, status line, and body
  558. * text. The connection will be closed afterwards.
  559. *
  560. * @since 0.6.0
  561. *
  562. * @param ec A status code, zero on success, non-zero otherwise
  563. */
  564. template <typename config>
  565. void connection<config>::send_http_response(lib::error_code & ec) {
  566. {
  567. scoped_lock_type lock(m_connection_state_lock);
  568. if (m_http_state != session::http_state::deferred) {
  569. ec = error::make_error_code(error::invalid_state);
  570. return;
  571. }
  572. m_http_state = session::http_state::body_written;
  573. }
  574. this->write_http_response(lib::error_code());
  575. ec = lib::error_code();
  576. }
  577. template <typename config>
  578. void connection<config>::send_http_response() {
  579. lib::error_code ec;
  580. this->send_http_response(ec);
  581. if (ec) {
  582. throw exception(ec);
  583. }
  584. }
  585. /******** logic thread ********/
  586. template <typename config>
  587. void connection<config>::start() {
  588. m_alog.write(log::alevel::devel,"connection start");
  589. if (m_internal_state != istate::USER_INIT) {
  590. m_alog.write(log::alevel::devel,"Start called in invalid state");
  591. this->terminate(error::make_error_code(error::invalid_state));
  592. return;
  593. }
  594. m_internal_state = istate::TRANSPORT_INIT;
  595. // Depending on how the transport implements init this function may return
  596. // immediately and call handle_transport_init later or call
  597. // handle_transport_init from this function.
  598. transport_con_type::init(
  599. lib::bind(
  600. &type::handle_transport_init,
  601. type::get_shared(),
  602. lib::placeholders::_1
  603. )
  604. );
  605. }
  606. template <typename config>
  607. void connection<config>::handle_transport_init(lib::error_code const & ec) {
  608. m_alog.write(log::alevel::devel,"connection handle_transport_init");
  609. lib::error_code ecm = ec;
  610. if (m_internal_state != istate::TRANSPORT_INIT) {
  611. m_alog.write(log::alevel::devel,
  612. "handle_transport_init must be called from transport init state");
  613. ecm = error::make_error_code(error::invalid_state);
  614. }
  615. if (ecm) {
  616. std::stringstream s;
  617. s << "handle_transport_init received error: "<< ecm.message();
  618. m_elog.write(log::elevel::rerror,s.str());
  619. this->terminate(ecm);
  620. return;
  621. }
  622. // At this point the transport is ready to read and write bytes.
  623. if (m_is_server) {
  624. m_internal_state = istate::READ_HTTP_REQUEST;
  625. this->read_handshake(1);
  626. } else {
  627. // We are a client. Set the processor to the version specified in the
  628. // config file and send a handshake request.
  629. m_internal_state = istate::WRITE_HTTP_REQUEST;
  630. m_processor = get_processor(config::client_version);
  631. this->send_http_request();
  632. }
  633. }
  634. template <typename config>
  635. void connection<config>::read_handshake(size_t num_bytes) {
  636. m_alog.write(log::alevel::devel,"connection read");
  637. if (m_open_handshake_timeout_dur > 0) {
  638. m_handshake_timer = transport_con_type::set_timer(
  639. m_open_handshake_timeout_dur,
  640. lib::bind(
  641. &type::handle_open_handshake_timeout,
  642. type::get_shared(),
  643. lib::placeholders::_1
  644. )
  645. );
  646. }
  647. transport_con_type::async_read_at_least(
  648. num_bytes,
  649. m_buf,
  650. config::connection_read_buffer_size,
  651. lib::bind(
  652. &type::handle_read_handshake,
  653. type::get_shared(),
  654. lib::placeholders::_1,
  655. lib::placeholders::_2
  656. )
  657. );
  658. }
  659. // All exit paths for this function need to call write_http_response() or submit
  660. // a new read request with this function as the handler.
  661. template <typename config>
  662. void connection<config>::handle_read_handshake(lib::error_code const & ec,
  663. size_t bytes_transferred)
  664. {
  665. m_alog.write(log::alevel::devel,"connection handle_read_handshake");
  666. lib::error_code ecm = ec;
  667. if (!ecm) {
  668. scoped_lock_type lock(m_connection_state_lock);
  669. if (m_state == session::state::connecting) {
  670. if (m_internal_state != istate::READ_HTTP_REQUEST) {
  671. ecm = error::make_error_code(error::invalid_state);
  672. }
  673. } else if (m_state == session::state::closed) {
  674. // The connection was canceled while the response was being sent,
  675. // usually by the handshake timer. This is basically expected
  676. // (though hopefully rare) and there is nothing we can do so ignore.
  677. m_alog.write(log::alevel::devel,
  678. "handle_read_handshake invoked after connection was closed");
  679. return;
  680. } else {
  681. ecm = error::make_error_code(error::invalid_state);
  682. }
  683. }
  684. if (ecm) {
  685. if (ecm == transport::error::eof && m_state == session::state::closed) {
  686. // we expect to get eof if the connection is closed already
  687. m_alog.write(log::alevel::devel,
  688. "got (expected) eof/state error from closed con");
  689. return;
  690. }
  691. log_err(log::elevel::rerror,"handle_read_handshake",ecm);
  692. this->terminate(ecm);
  693. return;
  694. }
  695. // Boundaries checking. TODO: How much of this should be done?
  696. if (bytes_transferred > config::connection_read_buffer_size) {
  697. m_elog.write(log::elevel::fatal,"Fatal boundaries checking error.");
  698. this->terminate(make_error_code(error::general));
  699. return;
  700. }
  701. size_t bytes_processed = 0;
  702. try {
  703. bytes_processed = m_request.consume(m_buf,bytes_transferred);
  704. } catch (http::exception &e) {
  705. // All HTTP exceptions will result in this request failing and an error
  706. // response being returned. No more bytes will be read in this con.
  707. m_response.set_status(e.m_error_code,e.m_error_msg);
  708. this->write_http_response_error(error::make_error_code(error::http_parse_error));
  709. return;
  710. }
  711. // More paranoid boundaries checking.
  712. // TODO: Is this overkill?
  713. if (bytes_processed > bytes_transferred) {
  714. m_elog.write(log::elevel::fatal,"Fatal boundaries checking error.");
  715. this->terminate(make_error_code(error::general));
  716. return;
  717. }
  718. if (m_alog.static_test(log::alevel::devel)) {
  719. std::stringstream s;
  720. s << "bytes_transferred: " << bytes_transferred
  721. << " bytes, bytes processed: " << bytes_processed << " bytes";
  722. m_alog.write(log::alevel::devel,s.str());
  723. }
  724. if (m_request.ready()) {
  725. lib::error_code processor_ec = this->initialize_processor();
  726. if (processor_ec) {
  727. this->write_http_response_error(processor_ec);
  728. return;
  729. }
  730. if (m_processor && m_processor->get_version() == 0) {
  731. // Version 00 has an extra requirement to read some bytes after the
  732. // handshake
  733. if (bytes_transferred-bytes_processed >= 8) {
  734. m_request.replace_header(
  735. "Sec-WebSocket-Key3",
  736. std::string(m_buf+bytes_processed,m_buf+bytes_processed+8)
  737. );
  738. bytes_processed += 8;
  739. } else {
  740. // TODO: need more bytes
  741. m_alog.write(log::alevel::devel,"short key3 read");
  742. m_response.set_status(http::status_code::internal_server_error);
  743. this->write_http_response_error(processor::error::make_error_code(processor::error::short_key3));
  744. return;
  745. }
  746. }
  747. if (m_alog.static_test(log::alevel::devel)) {
  748. m_alog.write(log::alevel::devel,m_request.raw());
  749. if (m_request.get_header("Sec-WebSocket-Key3") != "") {
  750. m_alog.write(log::alevel::devel,
  751. utility::to_hex(m_request.get_header("Sec-WebSocket-Key3")));
  752. }
  753. }
  754. // The remaining bytes in m_buf are frame data. Copy them to the
  755. // beginning of the buffer and note the length. They will be read after
  756. // the handshake completes and before more bytes are read.
  757. std::copy(m_buf+bytes_processed,m_buf+bytes_transferred,m_buf);
  758. m_buf_cursor = bytes_transferred-bytes_processed;
  759. m_internal_state = istate::PROCESS_HTTP_REQUEST;
  760. // We have the complete request. Process it.
  761. lib::error_code handshake_ec = this->process_handshake_request();
  762. if (!m_is_http || m_http_state != session::http_state::deferred) {
  763. this->write_http_response(handshake_ec);
  764. }
  765. } else {
  766. // read at least 1 more byte
  767. transport_con_type::async_read_at_least(
  768. 1,
  769. m_buf,
  770. config::connection_read_buffer_size,
  771. lib::bind(
  772. &type::handle_read_handshake,
  773. type::get_shared(),
  774. lib::placeholders::_1,
  775. lib::placeholders::_2
  776. )
  777. );
  778. }
  779. }
  780. // write_http_response requires the request to be fully read and the connection
  781. // to be in the PROCESS_HTTP_REQUEST state. In some cases we can detect errors
  782. // before the request is fully read (specifically at a point where we aren't
  783. // sure if the hybi00 key3 bytes need to be read). This method sets the correct
  784. // state and calls write_http_response
  785. template <typename config>
  786. void connection<config>::write_http_response_error(lib::error_code const & ec) {
  787. if (m_internal_state != istate::READ_HTTP_REQUEST) {
  788. m_alog.write(log::alevel::devel,
  789. "write_http_response_error called in invalid state");
  790. this->terminate(error::make_error_code(error::invalid_state));
  791. return;
  792. }
  793. m_internal_state = istate::PROCESS_HTTP_REQUEST;
  794. this->write_http_response(ec);
  795. }
  796. // All exit paths for this function need to call write_http_response() or submit
  797. // a new read request with this function as the handler.
  798. template <typename config>
  799. void connection<config>::handle_read_frame(lib::error_code const & ec,
  800. size_t bytes_transferred)
  801. {
  802. //m_alog.write(log::alevel::devel,"connection handle_read_frame");
  803. lib::error_code ecm = ec;
  804. if (!ecm && m_internal_state != istate::PROCESS_CONNECTION) {
  805. ecm = error::make_error_code(error::invalid_state);
  806. }
  807. if (ecm) {
  808. log::level echannel = log::elevel::rerror;
  809. if (ecm == transport::error::eof) {
  810. if (m_state == session::state::closed) {
  811. // we expect to get eof if the connection is closed already
  812. // just ignore it
  813. m_alog.write(log::alevel::devel,"got eof from closed con");
  814. return;
  815. } else if (m_state == session::state::closing && !m_is_server) {
  816. // If we are a client we expect to get eof in the closing state,
  817. // this is a signal to terminate our end of the connection after
  818. // the closing handshake
  819. terminate(lib::error_code());
  820. return;
  821. }
  822. } else if (ecm == error::invalid_state) {
  823. // In general, invalid state errors in the closed state are the
  824. // result of handlers that were in the system already when the state
  825. // changed and should be ignored as they pose no problems and there
  826. // is nothing useful that we can do about them.
  827. if (m_state == session::state::closed) {
  828. m_alog.write(log::alevel::devel,
  829. "handle_read_frame: got invalid istate in closed state");
  830. return;
  831. }
  832. } else if (ecm == transport::error::tls_short_read) {
  833. if (m_state == session::state::closed) {
  834. // We expect to get a TLS short read if we try to read after the
  835. // connection is closed. If this happens ignore and exit the
  836. // read frame path.
  837. terminate(lib::error_code());
  838. return;
  839. }
  840. echannel = log::elevel::rerror;
  841. } else if (ecm == transport::error::action_after_shutdown) {
  842. echannel = log::elevel::info;
  843. }
  844. log_err(echannel, "handle_read_frame", ecm);
  845. this->terminate(ecm);
  846. return;
  847. }
  848. // Boundaries checking. TODO: How much of this should be done?
  849. /*if (bytes_transferred > config::connection_read_buffer_size) {
  850. m_elog.write(log::elevel::fatal,"Fatal boundaries checking error");
  851. this->terminate(make_error_code(error::general));
  852. return;
  853. }*/
  854. size_t p = 0;
  855. if (m_alog.static_test(log::alevel::devel)) {
  856. std::stringstream s;
  857. s << "p = " << p << " bytes transferred = " << bytes_transferred;
  858. m_alog.write(log::alevel::devel,s.str());
  859. }
  860. while (p < bytes_transferred) {
  861. if (m_alog.static_test(log::alevel::devel)) {
  862. std::stringstream s;
  863. s << "calling consume with " << bytes_transferred-p << " bytes";
  864. m_alog.write(log::alevel::devel,s.str());
  865. }
  866. lib::error_code consume_ec;
  867. p += m_processor->consume(
  868. reinterpret_cast<uint8_t*>(m_buf)+p,
  869. bytes_transferred-p,
  870. consume_ec
  871. );
  872. if (m_alog.static_test(log::alevel::devel)) {
  873. std::stringstream s;
  874. s << "bytes left after consume: " << bytes_transferred-p;
  875. m_alog.write(log::alevel::devel,s.str());
  876. }
  877. if (consume_ec) {
  878. log_err(log::elevel::rerror, "consume", consume_ec);
  879. if (config::drop_on_protocol_error) {
  880. this->terminate(consume_ec);
  881. return;
  882. } else {
  883. lib::error_code close_ec;
  884. this->close(
  885. processor::error::to_ws(consume_ec),
  886. consume_ec.message(),
  887. close_ec
  888. );
  889. if (close_ec) {
  890. log_err(log::elevel::fatal, "Protocol error close frame ", close_ec);
  891. this->terminate(close_ec);
  892. return;
  893. }
  894. }
  895. return;
  896. }
  897. if (m_processor->ready()) {
  898. if (m_alog.static_test(log::alevel::devel)) {
  899. std::stringstream s;
  900. s << "Complete message received. Dispatching";
  901. m_alog.write(log::alevel::devel,s.str());
  902. }
  903. message_ptr msg = m_processor->get_message();
  904. if (!msg) {
  905. m_alog.write(log::alevel::devel, "null message from m_processor");
  906. } else if (!is_control(msg->get_opcode())) {
  907. // data message, dispatch to user
  908. if (m_state != session::state::open) {
  909. m_elog.write(log::elevel::warn, "got non-close frame while closing");
  910. } else if (m_message_handler) {
  911. m_message_handler(m_connection_hdl, msg);
  912. }
  913. } else {
  914. process_control_frame(msg);
  915. }
  916. }
  917. }
  918. read_frame();
  919. }
  920. /// Issue a new transport read unless reading is paused.
  921. template <typename config>
  922. void connection<config>::read_frame() {
  923. if (!m_read_flag) {
  924. return;
  925. }
  926. transport_con_type::async_read_at_least(
  927. // std::min wont work with undefined static const values.
  928. // TODO: is there a more elegant way to do this?
  929. // Need to determine if requesting 1 byte or the exact number of bytes
  930. // is better here. 1 byte lets us be a bit more responsive at a
  931. // potential expense of additional runs through handle_read_frame
  932. /*(m_processor->get_bytes_needed() > config::connection_read_buffer_size ?
  933. config::connection_read_buffer_size : m_processor->get_bytes_needed())*/
  934. 1,
  935. m_buf,
  936. config::connection_read_buffer_size,
  937. m_handle_read_frame
  938. );
  939. }
  940. template <typename config>
  941. lib::error_code connection<config>::initialize_processor() {
  942. m_alog.write(log::alevel::devel,"initialize_processor");
  943. // if it isn't a websocket handshake nothing to do.
  944. if (!processor::is_websocket_handshake(m_request)) {
  945. return lib::error_code();
  946. }
  947. int version = processor::get_websocket_version(m_request);
  948. if (version < 0) {
  949. m_alog.write(log::alevel::devel, "BAD REQUEST: can't determine version");
  950. m_response.set_status(http::status_code::bad_request);
  951. return error::make_error_code(error::invalid_version);
  952. }
  953. m_processor = get_processor(version);
  954. // if the processor is not null we are done
  955. if (m_processor) {
  956. return lib::error_code();
  957. }
  958. // We don't have a processor for this version. Return bad request
  959. // with Sec-WebSocket-Version header filled with values we do accept
  960. m_alog.write(log::alevel::devel, "BAD REQUEST: no processor for version");
  961. m_response.set_status(http::status_code::bad_request);
  962. std::stringstream ss;
  963. std::string sep = "";
  964. std::vector<int>::const_iterator it;
  965. for (it = versions_supported.begin(); it != versions_supported.end(); it++)
  966. {
  967. ss << sep << *it;
  968. sep = ",";
  969. }
  970. m_response.replace_header("Sec-WebSocket-Version",ss.str());
  971. return error::make_error_code(error::unsupported_version);
  972. }
  973. template <typename config>
  974. lib::error_code connection<config>::process_handshake_request() {
  975. m_alog.write(log::alevel::devel,"process handshake request");
  976. if (!processor::is_websocket_handshake(m_request)) {
  977. // this is not a websocket handshake. Process as plain HTTP
  978. m_alog.write(log::alevel::devel,"HTTP REQUEST");
  979. // extract URI from request
  980. m_uri = processor::get_uri_from_host(
  981. m_request,
  982. (transport_con_type::is_secure() ? "https" : "http")
  983. );
  984. if (!m_uri->get_valid()) {
  985. m_alog.write(log::alevel::devel, "Bad request: failed to parse uri");
  986. m_response.set_status(http::status_code::bad_request);
  987. return error::make_error_code(error::invalid_uri);
  988. }
  989. if (m_http_handler) {
  990. m_is_http = true;
  991. m_http_handler(m_connection_hdl);
  992. if (m_state == session::state::closed) {
  993. return error::make_error_code(error::http_connection_ended);
  994. }
  995. } else {
  996. set_status(http::status_code::upgrade_required);
  997. return error::make_error_code(error::upgrade_required);
  998. }
  999. return lib::error_code();
  1000. }
  1001. lib::error_code ec = m_processor->validate_handshake(m_request);
  1002. // Validate: make sure all required elements are present.
  1003. if (ec){
  1004. // Not a valid handshake request
  1005. m_alog.write(log::alevel::devel, "Bad request " + ec.message());
  1006. m_response.set_status(http::status_code::bad_request);
  1007. return ec;
  1008. }
  1009. // Read extension parameters and set up values necessary for the end user
  1010. // to complete extension negotiation.
  1011. std::pair<lib::error_code,std::string> neg_results;
  1012. neg_results = m_processor->negotiate_extensions(m_request);
  1013. if (neg_results.first) {
  1014. // There was a fatal error in extension parsing that should result in
  1015. // a failed connection attempt.
  1016. m_alog.write(log::alevel::devel, "Bad request: " + neg_results.first.message());
  1017. m_response.set_status(http::status_code::bad_request);
  1018. return neg_results.first;
  1019. } else {
  1020. // extension negotiation succeeded, set response header accordingly
  1021. // we don't send an empty extensions header because it breaks many
  1022. // clients.
  1023. if (neg_results.second.size() > 0) {
  1024. m_response.replace_header("Sec-WebSocket-Extensions",
  1025. neg_results.second);
  1026. }
  1027. }
  1028. // extract URI from request
  1029. m_uri = m_processor->get_uri(m_request);
  1030. if (!m_uri->get_valid()) {
  1031. m_alog.write(log::alevel::devel, "Bad request: failed to parse uri");
  1032. m_response.set_status(http::status_code::bad_request);
  1033. return error::make_error_code(error::invalid_uri);
  1034. }
  1035. // extract subprotocols
  1036. lib::error_code subp_ec = m_processor->extract_subprotocols(m_request,
  1037. m_requested_subprotocols);
  1038. if (subp_ec) {
  1039. // should we do anything?
  1040. }
  1041. // Ask application to validate the connection
  1042. if (!m_validate_handler || m_validate_handler(m_connection_hdl)) {
  1043. m_response.set_status(http::status_code::switching_protocols);
  1044. // Write the appropriate response headers based on request and
  1045. // processor version
  1046. ec = m_processor->process_handshake(m_request,m_subprotocol,m_response);
  1047. if (ec) {
  1048. std::stringstream s;
  1049. s << "Processing error: " << ec << "(" << ec.message() << ")";
  1050. m_alog.write(log::alevel::devel, s.str());
  1051. m_response.set_status(http::status_code::internal_server_error);
  1052. return ec;
  1053. }
  1054. } else {
  1055. // User application has rejected the handshake
  1056. m_alog.write(log::alevel::devel, "USER REJECT");
  1057. // Use Bad Request if the user handler did not provide a more
  1058. // specific http response error code.
  1059. // TODO: is there a better default?
  1060. if (m_response.get_status_code() == http::status_code::uninitialized) {
  1061. m_response.set_status(http::status_code::bad_request);
  1062. }
  1063. return error::make_error_code(error::rejected);
  1064. }
  1065. return lib::error_code();
  1066. }
  1067. template <typename config>
  1068. void connection<config>::write_http_response(lib::error_code const & ec) {
  1069. m_alog.write(log::alevel::devel,"connection write_http_response");
  1070. if (ec == error::make_error_code(error::http_connection_ended)) {
  1071. m_alog.write(log::alevel::http,"An HTTP handler took over the connection.");
  1072. return;
  1073. }
  1074. if (m_response.get_status_code() == http::status_code::uninitialized) {
  1075. m_response.set_status(http::status_code::internal_server_error);
  1076. m_ec = error::make_error_code(error::general);
  1077. } else {
  1078. m_ec = ec;
  1079. }
  1080. m_response.set_version("HTTP/1.1");
  1081. // Set server header based on the user agent settings
  1082. if (m_response.get_header("Server") == "") {
  1083. if (!m_user_agent.empty()) {
  1084. m_response.replace_header("Server",m_user_agent);
  1085. } else {
  1086. m_response.remove_header("Server");
  1087. }
  1088. }
  1089. // have the processor generate the raw bytes for the wire (if it exists)
  1090. if (m_processor) {
  1091. m_handshake_buffer = m_processor->get_raw(m_response);
  1092. } else {
  1093. // a processor wont exist for raw HTTP responses.
  1094. m_handshake_buffer = m_response.raw();
  1095. }
  1096. if (m_alog.static_test(log::alevel::devel)) {
  1097. m_alog.write(log::alevel::devel,"Raw Handshake response:\n"+m_handshake_buffer);
  1098. if (m_response.get_header("Sec-WebSocket-Key3") != "") {
  1099. m_alog.write(log::alevel::devel,
  1100. utility::to_hex(m_response.get_header("Sec-WebSocket-Key3")));
  1101. }
  1102. }
  1103. // write raw bytes
  1104. transport_con_type::async_write(
  1105. m_handshake_buffer.data(),
  1106. m_handshake_buffer.size(),
  1107. lib::bind(
  1108. &type::handle_write_http_response,
  1109. type::get_shared(),
  1110. lib::placeholders::_1
  1111. )
  1112. );
  1113. }
  1114. template <typename config>
  1115. void connection<config>::handle_write_http_response(lib::error_code const & ec) {
  1116. m_alog.write(log::alevel::devel,"handle_write_http_response");
  1117. lib::error_code ecm = ec;
  1118. if (!ecm) {
  1119. scoped_lock_type lock(m_connection_state_lock);
  1120. if (m_state == session::state::connecting) {
  1121. if (m_internal_state != istate::PROCESS_HTTP_REQUEST) {
  1122. ecm = error::make_error_code(error::invalid_state);
  1123. }
  1124. } else if (m_state == session::state::closed) {
  1125. // The connection was canceled while the response was being sent,
  1126. // usually by the handshake timer. This is basically expected
  1127. // (though hopefully rare) and there is nothing we can do so ignore.
  1128. m_alog.write(log::alevel::devel,
  1129. "handle_write_http_response invoked after connection was closed");
  1130. return;
  1131. } else {
  1132. ecm = error::make_error_code(error::invalid_state);
  1133. }
  1134. }
  1135. if (ecm) {
  1136. if (ecm == transport::error::eof && m_state == session::state::closed) {
  1137. // we expect to get eof if the connection is closed already
  1138. m_alog.write(log::alevel::devel,
  1139. "got (expected) eof/state error from closed con");
  1140. return;
  1141. }
  1142. log_err(log::elevel::rerror,"handle_write_http_response",ecm);
  1143. this->terminate(ecm);
  1144. return;
  1145. }
  1146. if (m_handshake_timer) {
  1147. m_handshake_timer->cancel();
  1148. m_handshake_timer.reset();
  1149. }
  1150. if (m_response.get_status_code() != http::status_code::switching_protocols)
  1151. {
  1152. /*if (m_processor || m_ec == error::http_parse_error ||
  1153. m_ec == error::invalid_version || m_ec == error::unsupported_version
  1154. || m_ec == error::upgrade_required)
  1155. {*/
  1156. if (!m_is_http) {
  1157. std::stringstream s;
  1158. s << "Handshake ended with HTTP error: "
  1159. << m_response.get_status_code();
  1160. m_elog.write(log::elevel::rerror,s.str());
  1161. } else {
  1162. // if this was not a websocket connection, we have written
  1163. // the expected response and the connection can be closed.
  1164. this->log_http_result();
  1165. if (m_ec) {
  1166. m_alog.write(log::alevel::devel,
  1167. "got to writing HTTP results with m_ec set: "+m_ec.message());
  1168. }
  1169. m_ec = make_error_code(error::http_connection_ended);
  1170. }
  1171. this->terminate(m_ec);
  1172. return;
  1173. }
  1174. this->log_open_result();
  1175. m_internal_state = istate::PROCESS_CONNECTION;
  1176. m_state = session::state::open;
  1177. if (m_open_handler) {
  1178. m_open_handler(m_connection_hdl);
  1179. }
  1180. this->handle_read_frame(lib::error_code(), m_buf_cursor);
  1181. }
  1182. template <typename config>
  1183. void connection<config>::send_http_request() {
  1184. m_alog.write(log::alevel::devel,"connection send_http_request");
  1185. // TODO: origin header?
  1186. // Have the protocol processor fill in the appropriate fields based on the
  1187. // selected client version
  1188. if (m_processor) {
  1189. lib::error_code ec;
  1190. ec = m_processor->client_handshake_request(m_request,m_uri,
  1191. m_requested_subprotocols);
  1192. if (ec) {
  1193. log_err(log::elevel::fatal,"Internal library error: Processor",ec);
  1194. return;
  1195. }
  1196. } else {
  1197. m_elog.write(log::elevel::fatal,"Internal library error: missing processor");
  1198. return;
  1199. }
  1200. // Unless the user has overridden the user agent, send generic WS++ UA.
  1201. if (m_request.get_header("User-Agent") == "") {
  1202. if (!m_user_agent.empty()) {
  1203. m_request.replace_header("User-Agent",m_user_agent);
  1204. } else {
  1205. m_request.remove_header("User-Agent");
  1206. }
  1207. }
  1208. m_handshake_buffer = m_request.raw();
  1209. if (m_alog.static_test(log::alevel::devel)) {
  1210. m_alog.write(log::alevel::devel,"Raw Handshake request:\n"+m_handshake_buffer);
  1211. }
  1212. if (m_open_handshake_timeout_dur > 0) {
  1213. m_handshake_timer = transport_con_type::set_timer(
  1214. m_open_handshake_timeout_dur,
  1215. lib::bind(
  1216. &type::handle_open_handshake_timeout,
  1217. type::get_shared(),
  1218. lib::placeholders::_1
  1219. )
  1220. );
  1221. }
  1222. transport_con_type::async_write(
  1223. m_handshake_buffer.data(),
  1224. m_handshake_buffer.size(),
  1225. lib::bind(
  1226. &type::handle_send_http_request,
  1227. type::get_shared(),
  1228. lib::placeholders::_1
  1229. )
  1230. );
  1231. }
  1232. template <typename config>
  1233. void connection<config>::handle_send_http_request(lib::error_code const & ec) {
  1234. m_alog.write(log::alevel::devel,"handle_send_http_request");
  1235. lib::error_code ecm = ec;
  1236. if (!ecm) {
  1237. scoped_lock_type lock(m_connection_state_lock);
  1238. if (m_state == session::state::connecting) {
  1239. if (m_internal_state != istate::WRITE_HTTP_REQUEST) {
  1240. ecm = error::make_error_code(error::invalid_state);
  1241. } else {
  1242. m_internal_state = istate::READ_HTTP_RESPONSE;
  1243. }
  1244. } else if (m_state == session::state::closed) {
  1245. // The connection was canceled while the response was being sent,
  1246. // usually by the handshake timer. This is basically expected
  1247. // (though hopefully rare) and there is nothing we can do so ignore.
  1248. m_alog.write(log::alevel::devel,
  1249. "handle_send_http_request invoked after connection was closed");
  1250. return;
  1251. } else {
  1252. ecm = error::make_error_code(error::invalid_state);
  1253. }
  1254. }
  1255. if (ecm) {
  1256. if (ecm == transport::error::eof && m_state == session::state::closed) {
  1257. // we expect to get eof if the connection is closed already
  1258. m_alog.write(log::alevel::devel,
  1259. "got (expected) eof/state error from closed con");
  1260. return;
  1261. }
  1262. log_err(log::elevel::rerror,"handle_send_http_request",ecm);
  1263. this->terminate(ecm);
  1264. return;
  1265. }
  1266. transport_con_type::async_read_at_least(
  1267. 1,
  1268. m_buf,
  1269. config::connection_read_buffer_size,
  1270. lib::bind(
  1271. &type::handle_read_http_response,
  1272. type::get_shared(),
  1273. lib::placeholders::_1,
  1274. lib::placeholders::_2
  1275. )
  1276. );
  1277. }
  1278. template <typename config>
  1279. void connection<config>::handle_read_http_response(lib::error_code const & ec,
  1280. size_t bytes_transferred)
  1281. {
  1282. m_alog.write(log::alevel::devel,"handle_read_http_response");
  1283. lib::error_code ecm = ec;
  1284. if (!ecm) {
  1285. scoped_lock_type lock(m_connection_state_lock);
  1286. if (m_state == session::state::connecting) {
  1287. if (m_internal_state != istate::READ_HTTP_RESPONSE) {
  1288. ecm = error::make_error_code(error::invalid_state);
  1289. }
  1290. } else if (m_state == session::state::closed) {
  1291. // The connection was canceled while the response was being sent,
  1292. // usually by the handshake timer. This is basically expected
  1293. // (though hopefully rare) and there is nothing we can do so ignore.
  1294. m_alog.write(log::alevel::devel,
  1295. "handle_read_http_response invoked after connection was closed");
  1296. return;
  1297. } else {
  1298. ecm = error::make_error_code(error::invalid_state);
  1299. }
  1300. }
  1301. if (ecm) {
  1302. if (ecm == transport::error::eof && m_state == session::state::closed) {
  1303. // we expect to get eof if the connection is closed already
  1304. m_alog.write(log::alevel::devel,
  1305. "got (expected) eof/state error from closed con");
  1306. return;
  1307. }
  1308. log_err(log::elevel::rerror,"handle_read_http_response",ecm);
  1309. this->terminate(ecm);
  1310. return;
  1311. }
  1312. size_t bytes_processed = 0;
  1313. // TODO: refactor this to use error codes rather than exceptions
  1314. try {
  1315. bytes_processed = m_response.consume(m_buf,bytes_transferred);
  1316. } catch (http::exception & e) {
  1317. m_elog.write(log::elevel::rerror,
  1318. std::string("error in handle_read_http_response: ")+e.what());
  1319. this->terminate(make_error_code(error::general));
  1320. return;
  1321. }
  1322. m_alog.write(log::alevel::devel,std::string("Raw response: ")+m_response.raw());
  1323. if (m_response.headers_ready()) {
  1324. if (m_handshake_timer) {
  1325. m_handshake_timer->cancel();
  1326. m_handshake_timer.reset();
  1327. }
  1328. lib::error_code validate_ec = m_processor->validate_server_handshake_response(
  1329. m_request,
  1330. m_response
  1331. );
  1332. if (validate_ec) {
  1333. log_err(log::elevel::rerror,"Server handshake response",validate_ec);
  1334. this->terminate(validate_ec);
  1335. return;
  1336. }
  1337. // response is valid, connection can now be assumed to be open
  1338. m_internal_state = istate::PROCESS_CONNECTION;
  1339. m_state = session::state::open;
  1340. this->log_open_result();
  1341. if (m_open_handler) {
  1342. m_open_handler(m_connection_hdl);
  1343. }
  1344. // The remaining bytes in m_buf are frame data. Copy them to the
  1345. // beginning of the buffer and note the length. They will be read after
  1346. // the handshake completes and before more bytes are read.
  1347. std::copy(m_buf+bytes_processed,m_buf+bytes_transferred,m_buf);
  1348. m_buf_cursor = bytes_transferred-bytes_processed;
  1349. this->handle_read_frame(lib::error_code(), m_buf_cursor);
  1350. } else {
  1351. transport_con_type::async_read_at_least(
  1352. 1,
  1353. m_buf,
  1354. config::connection_read_buffer_size,
  1355. lib::bind(
  1356. &type::handle_read_http_response,
  1357. type::get_shared(),
  1358. lib::placeholders::_1,
  1359. lib::placeholders::_2
  1360. )
  1361. );
  1362. }
  1363. }
  1364. template <typename config>
  1365. void connection<config>::handle_open_handshake_timeout(
  1366. lib::error_code const & ec)
  1367. {
  1368. if (ec == transport::error::operation_aborted) {
  1369. m_alog.write(log::alevel::devel,"open handshake timer cancelled");
  1370. } else if (ec) {
  1371. m_alog.write(log::alevel::devel,
  1372. "open handle_open_handshake_timeout error: "+ec.message());
  1373. // TODO: ignore or fail here?
  1374. } else {
  1375. m_alog.write(log::alevel::devel,"open handshake timer expired");
  1376. terminate(make_error_code(error::open_handshake_timeout));
  1377. }
  1378. }
  1379. template <typename config>
  1380. void connection<config>::handle_close_handshake_timeout(
  1381. lib::error_code const & ec)
  1382. {
  1383. if (ec == transport::error::operation_aborted) {
  1384. m_alog.write(log::alevel::devel,"asio close handshake timer cancelled");
  1385. } else if (ec) {
  1386. m_alog.write(log::alevel::devel,
  1387. "asio open handle_close_handshake_timeout error: "+ec.message());
  1388. // TODO: ignore or fail here?
  1389. } else {
  1390. m_alog.write(log::alevel::devel, "asio close handshake timer expired");
  1391. terminate(make_error_code(error::close_handshake_timeout));
  1392. }
  1393. }
  1394. template <typename config>
  1395. void connection<config>::terminate(lib::error_code const & ec) {
  1396. if (m_alog.static_test(log::alevel::devel)) {
  1397. m_alog.write(log::alevel::devel,"connection terminate");
  1398. }
  1399. // Cancel close handshake timer
  1400. if (m_handshake_timer) {
  1401. m_handshake_timer->cancel();
  1402. m_handshake_timer.reset();
  1403. }
  1404. terminate_status tstat = unknown;
  1405. if (ec) {
  1406. m_ec = ec;
  1407. m_local_close_code = close::status::abnormal_close;
  1408. m_local_close_reason = ec.message();
  1409. }
  1410. // TODO: does any of this need a mutex?
  1411. if (m_is_http) {
  1412. m_http_state = session::http_state::closed;
  1413. }
  1414. if (m_state == session::state::connecting) {
  1415. m_state = session::state::closed;
  1416. tstat = failed;
  1417. // Log fail result here before socket is shut down and we can't get
  1418. // the remote address, etc anymore
  1419. if (m_ec != error::http_connection_ended) {
  1420. log_fail_result();
  1421. }
  1422. } else if (m_state != session::state::closed) {
  1423. m_state = session::state::closed;
  1424. tstat = closed;
  1425. } else {
  1426. m_alog.write(log::alevel::devel,
  1427. "terminate called on connection that was already terminated");
  1428. return;
  1429. }
  1430. // TODO: choose between shutdown and close based on error code sent
  1431. transport_con_type::async_shutdown(
  1432. lib::bind(
  1433. &type::handle_terminate,
  1434. type::get_shared(),
  1435. tstat,
  1436. lib::placeholders::_1
  1437. )
  1438. );
  1439. }
  1440. template <typename config>
  1441. void connection<config>::handle_terminate(terminate_status tstat,
  1442. lib::error_code const & ec)
  1443. {
  1444. if (m_alog.static_test(log::alevel::devel)) {
  1445. m_alog.write(log::alevel::devel,"connection handle_terminate");
  1446. }
  1447. if (ec) {
  1448. // there was an error actually shutting down the connection
  1449. log_err(log::elevel::devel,"handle_terminate",ec);
  1450. }
  1451. // clean shutdown
  1452. if (tstat == failed) {
  1453. if (m_ec != error::http_connection_ended) {
  1454. if (m_fail_handler) {
  1455. m_fail_handler(m_connection_hdl);
  1456. }
  1457. }
  1458. } else if (tstat == closed) {
  1459. if (m_close_handler) {
  1460. m_close_handler(m_connection_hdl);
  1461. }
  1462. log_close_result();
  1463. } else {
  1464. m_elog.write(log::elevel::rerror,"Unknown terminate_status");
  1465. }
  1466. // call the termination handler if it exists
  1467. // if it exists it might (but shouldn't) refer to a bad memory location.
  1468. // If it does, we don't care and should catch and ignore it.
  1469. if (m_termination_handler) {
  1470. try {
  1471. m_termination_handler(type::get_shared());
  1472. } catch (std::exception const & e) {
  1473. m_elog.write(log::elevel::warn,
  1474. std::string("termination_handler call failed. Reason was: ")+e.what());
  1475. }
  1476. }
  1477. }
  1478. template <typename config>
  1479. void connection<config>::write_frame() {
  1480. //m_alog.write(log::alevel::devel,"connection write_frame");
  1481. {
  1482. scoped_lock_type lock(m_write_lock);
  1483. // Check the write flag. If true, there is an outstanding transport
  1484. // write already. In this case we just return. The write handler will
  1485. // start a new write if the write queue isn't empty. If false, we set
  1486. // the write flag and proceed to initiate a transport write.
  1487. if (m_write_flag) {
  1488. return;
  1489. }
  1490. // pull off all the messages that are ready to write.
  1491. // stop if we get a message marked terminal
  1492. message_ptr next_message = write_pop();
  1493. while (next_message) {
  1494. m_current_msgs.push_back(next_message);
  1495. if (!next_message->get_terminal()) {
  1496. next_message = write_pop();
  1497. } else {
  1498. next_message = message_ptr();
  1499. }
  1500. }
  1501. if (m_current_msgs.empty()) {
  1502. // there was nothing to send
  1503. return;
  1504. } else {
  1505. // At this point we own the next messages to be sent and are
  1506. // responsible for holding the write flag until they are
  1507. // successfully sent or there is some error
  1508. m_write_flag = true;
  1509. }
  1510. }
  1511. typename std::vector<message_ptr>::iterator it;
  1512. for (it = m_current_msgs.begin(); it != m_current_msgs.end(); ++it) {
  1513. std::string const & header = (*it)->get_header();
  1514. std::string const & payload = (*it)->get_payload();
  1515. m_send_buffer.push_back(transport::buffer(header.c_str(),header.size()));
  1516. m_send_buffer.push_back(transport::buffer(payload.c_str(),payload.size()));
  1517. }
  1518. // Print detailed send stats if those log levels are enabled
  1519. if (m_alog.static_test(log::alevel::frame_header)) {
  1520. if (m_alog.dynamic_test(log::alevel::frame_header)) {
  1521. std::stringstream general,header,payload;
  1522. general << "Dispatching write containing " << m_current_msgs.size()
  1523. <<" message(s) containing ";
  1524. header << "Header Bytes: \n";
  1525. payload << "Payload Bytes: \n";
  1526. size_t hbytes = 0;
  1527. size_t pbytes = 0;
  1528. for (size_t i = 0; i < m_current_msgs.size(); i++) {
  1529. hbytes += m_current_msgs[i]->get_header().size();
  1530. pbytes += m_current_msgs[i]->get_payload().size();
  1531. header << "[" << i << "] ("
  1532. << m_current_msgs[i]->get_header().size() << ") "
  1533. << utility::to_hex(m_current_msgs[i]->get_header()) << "\n";
  1534. if (m_alog.static_test(log::alevel::frame_payload)) {
  1535. if (m_alog.dynamic_test(log::alevel::frame_payload)) {
  1536. payload << "[" << i << "] ("
  1537. << m_current_msgs[i]->get_payload().size() << ") ["<<m_current_msgs[i]->get_opcode()<<"] "
  1538. << (m_current_msgs[i]->get_opcode() == frame::opcode::text ?
  1539. m_current_msgs[i]->get_payload() :
  1540. utility::to_hex(m_current_msgs[i]->get_payload())
  1541. )
  1542. << "\n";
  1543. }
  1544. }
  1545. }
  1546. general << hbytes << " header bytes and " << pbytes << " payload bytes";
  1547. m_alog.write(log::alevel::frame_header,general.str());
  1548. m_alog.write(log::alevel::frame_header,header.str());
  1549. m_alog.write(log::alevel::frame_payload,payload.str());
  1550. }
  1551. }
  1552. transport_con_type::async_write(
  1553. m_send_buffer,
  1554. m_write_frame_handler
  1555. );
  1556. }
  1557. template <typename config>
  1558. void connection<config>::handle_write_frame(lib::error_code const & ec)
  1559. {
  1560. if (m_alog.static_test(log::alevel::devel)) {
  1561. m_alog.write(log::alevel::devel,"connection handle_write_frame");
  1562. }
  1563. bool terminal = m_current_msgs.back()->get_terminal();
  1564. m_send_buffer.clear();
  1565. m_current_msgs.clear();
  1566. // TODO: recycle instead of deleting
  1567. if (ec) {
  1568. log_err(log::elevel::fatal,"handle_write_frame",ec);
  1569. this->terminate(ec);
  1570. return;
  1571. }
  1572. if (terminal) {
  1573. this->terminate(lib::error_code());
  1574. return;
  1575. }
  1576. bool needs_writing = false;
  1577. {
  1578. scoped_lock_type lock(m_write_lock);
  1579. // release write flag
  1580. m_write_flag = false;
  1581. needs_writing = !m_send_queue.empty();
  1582. }
  1583. if (needs_writing) {
  1584. transport_con_type::dispatch(lib::bind(
  1585. &type::write_frame,
  1586. type::get_shared()
  1587. ));
  1588. }
  1589. }
  1590. template <typename config>
  1591. std::vector<int> const & connection<config>::get_supported_versions() const
  1592. {
  1593. return versions_supported;
  1594. }
  1595. template <typename config>
  1596. void connection<config>::process_control_frame(typename config::message_type::ptr msg)
  1597. {
  1598. m_alog.write(log::alevel::devel,"process_control_frame");
  1599. frame::opcode::value op = msg->get_opcode();
  1600. lib::error_code ec;
  1601. std::stringstream s;
  1602. s << "Control frame received with opcode " << op;
  1603. m_alog.write(log::alevel::control,s.str());
  1604. if (m_state == session::state::closed) {
  1605. m_elog.write(log::elevel::warn,"got frame in state closed");
  1606. return;
  1607. }
  1608. if (op != frame::opcode::CLOSE && m_state != session::state::open) {
  1609. m_elog.write(log::elevel::warn,"got non-close frame in state closing");
  1610. return;
  1611. }
  1612. if (op == frame::opcode::PING) {
  1613. bool should_reply = true;
  1614. if (m_ping_handler) {
  1615. should_reply = m_ping_handler(m_connection_hdl, msg->get_payload());
  1616. }
  1617. if (should_reply) {
  1618. this->pong(msg->get_payload(),ec);
  1619. if (ec) {
  1620. log_err(log::elevel::devel,"Failed to send response pong",ec);
  1621. }
  1622. }
  1623. } else if (op == frame::opcode::PONG) {
  1624. if (m_pong_handler) {
  1625. m_pong_handler(m_connection_hdl, msg->get_payload());
  1626. }
  1627. if (m_ping_timer) {
  1628. m_ping_timer->cancel();
  1629. }
  1630. } else if (op == frame::opcode::CLOSE) {
  1631. m_alog.write(log::alevel::devel,"got close frame");
  1632. // record close code and reason somewhere
  1633. m_remote_close_code = close::extract_code(msg->get_payload(),ec);
  1634. if (ec) {
  1635. s.str("");
  1636. if (config::drop_on_protocol_error) {
  1637. s << "Received invalid close code " << m_remote_close_code
  1638. << " dropping connection per config.";
  1639. m_elog.write(log::elevel::devel,s.str());
  1640. this->terminate(ec);
  1641. } else {
  1642. s << "Received invalid close code " << m_remote_close_code
  1643. << " sending acknowledgement and closing";
  1644. m_elog.write(log::elevel::devel,s.str());
  1645. ec = send_close_ack(close::status::protocol_error,
  1646. "Invalid close code");
  1647. if (ec) {
  1648. log_err(log::elevel::devel,"send_close_ack",ec);
  1649. }
  1650. }
  1651. return;
  1652. }
  1653. m_remote_close_reason = close::extract_reason(msg->get_payload(),ec);
  1654. if (ec) {
  1655. if (config::drop_on_protocol_error) {
  1656. m_elog.write(log::elevel::devel,
  1657. "Received invalid close reason. Dropping connection per config");
  1658. this->terminate(ec);
  1659. } else {
  1660. m_elog.write(log::elevel::devel,
  1661. "Received invalid close reason. Sending acknowledgement and closing");
  1662. ec = send_close_ack(close::status::protocol_error,
  1663. "Invalid close reason");
  1664. if (ec) {
  1665. log_err(log::elevel::devel,"send_close_ack",ec);
  1666. }
  1667. }
  1668. return;
  1669. }
  1670. if (m_state == session::state::open) {
  1671. s.str("");
  1672. s << "Received close frame with code " << m_remote_close_code
  1673. << " and reason " << m_remote_close_reason;
  1674. m_alog.write(log::alevel::devel,s.str());
  1675. ec = send_close_ack();
  1676. if (ec) {
  1677. log_err(log::elevel::devel,"send_close_ack",ec);
  1678. }
  1679. } else if (m_state == session::state::closing && !m_was_clean) {
  1680. // ack of our close
  1681. m_alog.write(log::alevel::devel, "Got acknowledgement of close");
  1682. m_was_clean = true;
  1683. // If we are a server terminate the connection now. Clients should
  1684. // leave the connection open to give the server an opportunity to
  1685. // initiate the TCP close. The client's timer will handle closing
  1686. // its side of the connection if the server misbehaves.
  1687. //
  1688. // TODO: different behavior if the underlying transport doesn't
  1689. // support timers?
  1690. if (m_is_server) {
  1691. terminate(lib::error_code());
  1692. }
  1693. } else {
  1694. // spurious, ignore
  1695. m_elog.write(log::elevel::devel, "Got close frame in wrong state");
  1696. }
  1697. } else {
  1698. // got an invalid control opcode
  1699. m_elog.write(log::elevel::devel, "Got control frame with invalid opcode");
  1700. // initiate protocol error shutdown
  1701. }
  1702. }
  1703. template <typename config>
  1704. lib::error_code connection<config>::send_close_ack(close::status::value code,
  1705. std::string const & reason)
  1706. {
  1707. return send_close_frame(code,reason,true,m_is_server);
  1708. }
  1709. template <typename config>
  1710. lib::error_code connection<config>::send_close_frame(close::status::value code,
  1711. std::string const & reason, bool ack, bool terminal)
  1712. {
  1713. m_alog.write(log::alevel::devel,"send_close_frame");
  1714. // check for special codes
  1715. // If silent close is set, respect it and blank out close information
  1716. // Otherwise use whatever has been specified in the parameters. If
  1717. // parameters specifies close::status::blank then determine what to do
  1718. // based on whether or not this is an ack. If it is not an ack just
  1719. // send blank info. If it is an ack then echo the close information from
  1720. // the remote endpoint.
  1721. if (config::silent_close) {
  1722. m_alog.write(log::alevel::devel,"closing silently");
  1723. m_local_close_code = close::status::no_status;
  1724. m_local_close_reason = "";
  1725. } else if (code != close::status::blank) {
  1726. m_alog.write(log::alevel::devel,"closing with specified codes");
  1727. m_local_close_code = code;
  1728. m_local_close_reason = reason;
  1729. } else if (!ack) {
  1730. m_alog.write(log::alevel::devel,"closing with no status code");
  1731. m_local_close_code = close::status::no_status;
  1732. m_local_close_reason = "";
  1733. } else if (m_remote_close_code == close::status::no_status) {
  1734. m_alog.write(log::alevel::devel,
  1735. "acknowledging a no-status close with normal code");
  1736. m_local_close_code = close::status::normal;
  1737. m_local_close_reason = "";
  1738. } else {
  1739. m_alog.write(log::alevel::devel,"acknowledging with remote codes");
  1740. m_local_close_code = m_remote_close_code;
  1741. m_local_close_reason = m_remote_close_reason;
  1742. }
  1743. std::stringstream s;
  1744. s << "Closing with code: " << m_local_close_code << ", and reason: "
  1745. << m_local_close_reason;
  1746. m_alog.write(log::alevel::devel,s.str());
  1747. message_ptr msg = m_msg_manager->get_message();
  1748. if (!msg) {
  1749. return error::make_error_code(error::no_outgoing_buffers);
  1750. }
  1751. lib::error_code ec = m_processor->prepare_close(m_local_close_code,
  1752. m_local_close_reason,msg);
  1753. if (ec) {
  1754. return ec;
  1755. }
  1756. // Messages flagged terminal will result in the TCP connection being dropped
  1757. // after the message has been written. This is typically used when servers
  1758. // send an ack and when any endpoint encounters a protocol error
  1759. if (terminal) {
  1760. msg->set_terminal(true);
  1761. }
  1762. m_state = session::state::closing;
  1763. if (ack) {
  1764. m_was_clean = true;
  1765. }
  1766. // Start a timer so we don't wait forever for the acknowledgement close
  1767. // frame
  1768. if (m_close_handshake_timeout_dur > 0) {
  1769. m_handshake_timer = transport_con_type::set_timer(
  1770. m_close_handshake_timeout_dur,
  1771. lib::bind(
  1772. &type::handle_close_handshake_timeout,
  1773. type::get_shared(),
  1774. lib::placeholders::_1
  1775. )
  1776. );
  1777. }
  1778. bool needs_writing = false;
  1779. {
  1780. scoped_lock_type lock(m_write_lock);
  1781. write_push(msg);
  1782. needs_writing = !m_write_flag && !m_send_queue.empty();
  1783. }
  1784. if (needs_writing) {
  1785. transport_con_type::dispatch(lib::bind(
  1786. &type::write_frame,
  1787. type::get_shared()
  1788. ));
  1789. }
  1790. return lib::error_code();
  1791. }
  1792. template <typename config>
  1793. typename connection<config>::processor_ptr
  1794. connection<config>::get_processor(int version) const {
  1795. // TODO: allow disabling certain versions
  1796. processor_ptr p;
  1797. switch (version) {
  1798. case 0:
  1799. p = lib::make_shared<processor::hybi00<config> >(
  1800. transport_con_type::is_secure(),
  1801. m_is_server,
  1802. m_msg_manager
  1803. );
  1804. break;
  1805. case 7:
  1806. p = lib::make_shared<processor::hybi07<config> >(
  1807. transport_con_type::is_secure(),
  1808. m_is_server,
  1809. m_msg_manager,
  1810. lib::ref(m_rng)
  1811. );
  1812. break;
  1813. case 8:
  1814. p = lib::make_shared<processor::hybi08<config> >(
  1815. transport_con_type::is_secure(),
  1816. m_is_server,
  1817. m_msg_manager,
  1818. lib::ref(m_rng)
  1819. );
  1820. break;
  1821. case 13:
  1822. p = lib::make_shared<processor::hybi13<config> >(
  1823. transport_con_type::is_secure(),
  1824. m_is_server,
  1825. m_msg_manager,
  1826. lib::ref(m_rng)
  1827. );
  1828. break;
  1829. default:
  1830. return p;
  1831. }
  1832. // Settings not configured by the constructor
  1833. p->set_max_message_size(m_max_message_size);
  1834. return p;
  1835. }
  1836. template <typename config>
  1837. void connection<config>::write_push(typename config::message_type::ptr msg)
  1838. {
  1839. if (!msg) {
  1840. return;
  1841. }
  1842. m_send_buffer_size += msg->get_payload().size();
  1843. m_send_queue.push(msg);
  1844. if (m_alog.static_test(log::alevel::devel)) {
  1845. std::stringstream s;
  1846. s << "write_push: message count: " << m_send_queue.size()
  1847. << " buffer size: " << m_send_buffer_size;
  1848. m_alog.write(log::alevel::devel,s.str());
  1849. }
  1850. }
  1851. template <typename config>
  1852. typename config::message_type::ptr connection<config>::write_pop()
  1853. {
  1854. message_ptr msg;
  1855. if (m_send_queue.empty()) {
  1856. return msg;
  1857. }
  1858. msg = m_send_queue.front();
  1859. m_send_buffer_size -= msg->get_payload().size();
  1860. m_send_queue.pop();
  1861. if (m_alog.static_test(log::alevel::devel)) {
  1862. std::stringstream s;
  1863. s << "write_pop: message count: " << m_send_queue.size()
  1864. << " buffer size: " << m_send_buffer_size;
  1865. m_alog.write(log::alevel::devel,s.str());
  1866. }
  1867. return msg;
  1868. }
  1869. template <typename config>
  1870. void connection<config>::log_open_result()
  1871. {
  1872. std::stringstream s;
  1873. int version;
  1874. if (!processor::is_websocket_handshake(m_request)) {
  1875. version = -1;
  1876. } else {
  1877. version = processor::get_websocket_version(m_request);
  1878. }
  1879. // Connection Type
  1880. s << (version == -1 ? "HTTP" : "WebSocket") << " Connection ";
  1881. // Remote endpoint address
  1882. s << transport_con_type::get_remote_endpoint() << " ";
  1883. // Version string if WebSocket
  1884. if (version != -1) {
  1885. s << "v" << version << " ";
  1886. }
  1887. // User Agent
  1888. std::string ua = m_request.get_header("User-Agent");
  1889. if (ua == "") {
  1890. s << "\"\" ";
  1891. } else {
  1892. // check if there are any quotes in the user agent
  1893. s << "\"" << utility::string_replace_all(ua,"\"","\\\"") << "\" ";
  1894. }
  1895. // URI
  1896. s << (m_uri ? m_uri->get_resource() : "NULL") << " ";
  1897. // Status code
  1898. s << m_response.get_status_code();
  1899. m_alog.write(log::alevel::connect,s.str());
  1900. }
  1901. template <typename config>
  1902. void connection<config>::log_close_result()
  1903. {
  1904. std::stringstream s;
  1905. s << "Disconnect "
  1906. << "close local:[" << m_local_close_code
  1907. << (m_local_close_reason == "" ? "" : ","+m_local_close_reason)
  1908. << "] remote:[" << m_remote_close_code
  1909. << (m_remote_close_reason == "" ? "" : ","+m_remote_close_reason) << "]";
  1910. m_alog.write(log::alevel::disconnect,s.str());
  1911. }
  1912. template <typename config>
  1913. void connection<config>::log_fail_result()
  1914. {
  1915. std::stringstream s;
  1916. int version = processor::get_websocket_version(m_request);
  1917. // Connection Type
  1918. s << "WebSocket Connection ";
  1919. // Remote endpoint address & WebSocket version
  1920. s << transport_con_type::get_remote_endpoint();
  1921. if (version < 0) {
  1922. s << " -";
  1923. } else {
  1924. s << " v" << version;
  1925. }
  1926. // User Agent
  1927. std::string ua = m_request.get_header("User-Agent");
  1928. if (ua == "") {
  1929. s << " \"\" ";
  1930. } else {
  1931. // check if there are any quotes in the user agent
  1932. s << " \"" << utility::string_replace_all(ua,"\"","\\\"") << "\" ";
  1933. }
  1934. // URI
  1935. s << (m_uri ? m_uri->get_resource() : "-");
  1936. // HTTP Status code
  1937. s << " " << m_response.get_status_code();
  1938. // WebSocket++ error code & reason
  1939. s << " " << m_ec << " " << m_ec.message();
  1940. m_alog.write(log::alevel::fail,s.str());
  1941. }
  1942. template <typename config>
  1943. void connection<config>::log_http_result() {
  1944. std::stringstream s;
  1945. if (processor::is_websocket_handshake(m_request)) {
  1946. m_alog.write(log::alevel::devel,"Call to log_http_result for WebSocket");
  1947. return;
  1948. }
  1949. // Connection Type
  1950. s << (m_request.get_header("host") == "" ? "-" : m_request.get_header("host"))
  1951. << " " << transport_con_type::get_remote_endpoint()
  1952. << " \"" << m_request.get_method()
  1953. << " " << (m_uri ? m_uri->get_resource() : "-")
  1954. << " " << m_request.get_version() << "\" " << m_response.get_status_code()
  1955. << " " << m_response.get_body().size();
  1956. // User Agent
  1957. std::string ua = m_request.get_header("User-Agent");
  1958. if (ua == "") {
  1959. s << " \"\" ";
  1960. } else {
  1961. // check if there are any quotes in the user agent
  1962. s << " \"" << utility::string_replace_all(ua,"\"","\\\"") << "\" ";
  1963. }
  1964. m_alog.write(log::alevel::http,s.str());
  1965. }
  1966. } // namespace websocketpp
  1967. #endif // WEBSOCKETPP_CONNECTION_IMPL_HPP