connection.hpp 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642
  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_HPP
  28. #define WEBSOCKETPP_CONNECTION_HPP
  29. #include <websocketpp/close.hpp>
  30. #include <websocketpp/error.hpp>
  31. #include <websocketpp/frame.hpp>
  32. #include <websocketpp/logger/levels.hpp>
  33. #include <websocketpp/processors/processor.hpp>
  34. #include <websocketpp/transport/base/connection.hpp>
  35. #include <websocketpp/http/constants.hpp>
  36. #include <websocketpp/common/connection_hdl.hpp>
  37. #include <websocketpp/common/cpp11.hpp>
  38. #include <websocketpp/common/functional.hpp>
  39. #include <queue>
  40. #include <sstream>
  41. #include <string>
  42. #include <vector>
  43. namespace websocketpp {
  44. /// The type and function signature of an open handler
  45. /**
  46. * The open handler is called once for every successful WebSocket connection
  47. * attempt. Either the fail handler or the open handler will be called for each
  48. * WebSocket connection attempt. HTTP Connections that did not attempt to
  49. * upgrade the connection to the WebSocket protocol will trigger the http
  50. * handler instead of fail/open.
  51. */
  52. typedef lib::function<void(connection_hdl)> open_handler;
  53. /// The type and function signature of a close handler
  54. /**
  55. * The close handler is called once for every successfully established
  56. * connection after it is no longer capable of sending or receiving new messages
  57. *
  58. * The close handler will be called exactly once for every connection for which
  59. * the open handler was called.
  60. */
  61. typedef lib::function<void(connection_hdl)> close_handler;
  62. /// The type and function signature of a fail handler
  63. /**
  64. * The fail handler is called once for every unsuccessful WebSocket connection
  65. * attempt. Either the fail handler or the open handler will be called for each
  66. * WebSocket connection attempt. HTTP Connections that did not attempt to
  67. * upgrade the connection to the WebSocket protocol will trigger the http
  68. * handler instead of fail/open.
  69. */
  70. typedef lib::function<void(connection_hdl)> fail_handler;
  71. /// The type and function signature of an interrupt handler
  72. /**
  73. * The interrupt handler is called when a connection receives an interrupt
  74. * request from the application. Interrupts allow the application to trigger a
  75. * handler to be run in the absense of a WebSocket level handler trigger (like
  76. * a new message).
  77. *
  78. * This is typically used by another application thread to schedule some tasks
  79. * that can only be run from within the handler chain for thread safety reasons.
  80. */
  81. typedef lib::function<void(connection_hdl)> interrupt_handler;
  82. /// The type and function signature of a ping handler
  83. /**
  84. * The ping handler is called when the connection receives a WebSocket ping
  85. * control frame. The string argument contains the ping payload. The payload is
  86. * a binary string up to 126 bytes in length. The ping handler returns a bool,
  87. * true if a pong response should be sent, false if the pong response should be
  88. * suppressed.
  89. */
  90. typedef lib::function<bool(connection_hdl,std::string)> ping_handler;
  91. /// The type and function signature of a pong handler
  92. /**
  93. * The pong handler is called when the connection receives a WebSocket pong
  94. * control frame. The string argument contains the pong payload. The payload is
  95. * a binary string up to 126 bytes in length.
  96. */
  97. typedef lib::function<void(connection_hdl,std::string)> pong_handler;
  98. /// The type and function signature of a pong timeout handler
  99. /**
  100. * The pong timeout handler is called when a ping goes unanswered by a pong for
  101. * longer than the locally specified timeout period.
  102. */
  103. typedef lib::function<void(connection_hdl,std::string)> pong_timeout_handler;
  104. /// The type and function signature of a validate handler
  105. /**
  106. * The validate handler is called after a WebSocket handshake has been received
  107. * and processed but before it has been accepted. This gives the application a
  108. * chance to implement connection details specific policies for accepting
  109. * connections and the ability to negotiate extensions and subprotocols.
  110. *
  111. * The validate handler return value indicates whether or not the connection
  112. * should be accepted. Additional methods may be called during the function to
  113. * set response headers, set HTTP return/error codes, etc.
  114. */
  115. typedef lib::function<bool(connection_hdl)> validate_handler;
  116. /// The type and function signature of a http handler
  117. /**
  118. * The http handler is called when an HTTP connection is made that does not
  119. * attempt to upgrade the connection to the WebSocket protocol. This allows
  120. * WebSocket++ servers to respond to these requests with regular HTTP responses.
  121. *
  122. * This can be used to deliver error pages & dashboards and to deliver static
  123. * files such as the base HTML & JavaScript for an otherwise single page
  124. * WebSocket application.
  125. *
  126. * Note: WebSocket++ is designed to be a high performance WebSocket server. It
  127. * is not tuned to provide a full featured, high performance, HTTP web server
  128. * solution. The HTTP handler is appropriate only for low volume HTTP traffic.
  129. * If you expect to serve high volumes of HTTP traffic a dedicated HTTP web
  130. * server is strongly recommended.
  131. *
  132. * The default HTTP handler will return a 426 Upgrade Required error. Custom
  133. * handlers may override the response status code to deliver any type of
  134. * response.
  135. */
  136. typedef lib::function<void(connection_hdl)> http_handler;
  137. //
  138. typedef lib::function<void(lib::error_code const & ec, size_t bytes_transferred)> read_handler;
  139. typedef lib::function<void(lib::error_code const & ec)> write_frame_handler;
  140. // constants related to the default WebSocket protocol versions available
  141. #ifdef _WEBSOCKETPP_INITIALIZER_LISTS_ // simplified C++11 version
  142. /// Container that stores the list of protocol versions supported
  143. /**
  144. * @todo Move this to configs to allow compile/runtime disabling or enabling
  145. * of protocol versions
  146. */
  147. static std::vector<int> const versions_supported = {0,7,8,13};
  148. #else
  149. /// Helper array to get around lack of initializer lists pre C++11
  150. static int const helper[] = {0,7,8,13};
  151. /// Container that stores the list of protocol versions supported
  152. /**
  153. * @todo Move this to configs to allow compile/runtime disabling or enabling
  154. * of protocol versions
  155. */
  156. static std::vector<int> const versions_supported(helper,helper+4);
  157. #endif
  158. namespace session {
  159. namespace state {
  160. // externally visible session state (states based on the RFC)
  161. enum value {
  162. connecting = 0,
  163. open = 1,
  164. closing = 2,
  165. closed = 3
  166. };
  167. } // namespace state
  168. namespace fail {
  169. namespace status {
  170. enum value {
  171. GOOD = 0, // no failure yet!
  172. SYSTEM = 1, // system call returned error, check that code
  173. WEBSOCKET = 2, // websocket close codes contain error
  174. UNKNOWN = 3, // No failure information is available
  175. TIMEOUT_TLS = 4, // TLS handshake timed out
  176. TIMEOUT_WS = 5 // WS handshake timed out
  177. };
  178. } // namespace status
  179. } // namespace fail
  180. namespace internal_state {
  181. // More granular internal states. These are used for multi-threaded
  182. // connection synchronization and preventing values that are not yet or no
  183. // longer available from being used.
  184. enum value {
  185. USER_INIT = 0,
  186. TRANSPORT_INIT = 1,
  187. READ_HTTP_REQUEST = 2,
  188. WRITE_HTTP_REQUEST = 3,
  189. READ_HTTP_RESPONSE = 4,
  190. WRITE_HTTP_RESPONSE = 5,
  191. PROCESS_HTTP_REQUEST = 6,
  192. PROCESS_CONNECTION = 7
  193. };
  194. } // namespace internal_state
  195. namespace http_state {
  196. // states to keep track of the progress of http connections
  197. enum value {
  198. init = 0,
  199. deferred = 1,
  200. headers_written = 2,
  201. body_written = 3,
  202. closed = 4
  203. };
  204. } // namespace http_state
  205. } // namespace session
  206. /// Represents an individual WebSocket connection
  207. template <typename config>
  208. class connection
  209. : public config::transport_type::transport_con_type
  210. , public config::connection_base
  211. {
  212. public:
  213. /// Type of this connection
  214. typedef connection<config> type;
  215. /// Type of a shared pointer to this connection
  216. typedef lib::shared_ptr<type> ptr;
  217. /// Type of a weak pointer to this connection
  218. typedef lib::weak_ptr<type> weak_ptr;
  219. /// Type of the concurrency component of this connection
  220. typedef typename config::concurrency_type concurrency_type;
  221. /// Type of the access logging policy
  222. typedef typename config::alog_type alog_type;
  223. /// Type of the error logging policy
  224. typedef typename config::elog_type elog_type;
  225. /// Type of the transport component of this connection
  226. typedef typename config::transport_type::transport_con_type
  227. transport_con_type;
  228. /// Type of a shared pointer to the transport component of this connection
  229. typedef typename transport_con_type::ptr transport_con_ptr;
  230. typedef lib::function<void(ptr)> termination_handler;
  231. typedef typename concurrency_type::scoped_lock_type scoped_lock_type;
  232. typedef typename concurrency_type::mutex_type mutex_type;
  233. typedef typename config::request_type request_type;
  234. typedef typename config::response_type response_type;
  235. typedef typename config::message_type message_type;
  236. typedef typename message_type::ptr message_ptr;
  237. typedef typename config::con_msg_manager_type con_msg_manager_type;
  238. typedef typename con_msg_manager_type::ptr con_msg_manager_ptr;
  239. /// Type of RNG
  240. typedef typename config::rng_type rng_type;
  241. typedef processor::processor<config> processor_type;
  242. typedef lib::shared_ptr<processor_type> processor_ptr;
  243. // Message handler (needs to know message type)
  244. typedef lib::function<void(connection_hdl,message_ptr)> message_handler;
  245. /// Type of a pointer to a transport timer handle
  246. typedef typename transport_con_type::timer_ptr timer_ptr;
  247. // Misc Convenience Types
  248. typedef session::internal_state::value istate_type;
  249. private:
  250. enum terminate_status {
  251. failed = 1,
  252. closed,
  253. unknown
  254. };
  255. public:
  256. explicit connection(bool p_is_server, std::string const & ua, const lib::shared_ptr<alog_type>& alog,
  257. const lib::shared_ptr<elog_type>& elog, rng_type & rng)
  258. : transport_con_type(p_is_server, alog, elog)
  259. , m_handle_read_frame(lib::bind(
  260. &type::handle_read_frame,
  261. this,
  262. lib::placeholders::_1,
  263. lib::placeholders::_2
  264. ))
  265. , m_write_frame_handler(lib::bind(
  266. &type::handle_write_frame,
  267. this,
  268. lib::placeholders::_1
  269. ))
  270. , m_user_agent(ua)
  271. , m_open_handshake_timeout_dur(config::timeout_open_handshake)
  272. , m_close_handshake_timeout_dur(config::timeout_close_handshake)
  273. , m_pong_timeout_dur(config::timeout_pong)
  274. , m_max_message_size(config::max_message_size)
  275. , m_state(session::state::connecting)
  276. , m_internal_state(session::internal_state::USER_INIT)
  277. , m_msg_manager(new con_msg_manager_type())
  278. , m_send_buffer_size(0)
  279. , m_write_flag(false)
  280. , m_read_flag(true)
  281. , m_is_server(p_is_server)
  282. , m_alog(alog)
  283. , m_elog(elog)
  284. , m_rng(rng)
  285. , m_local_close_code(close::status::abnormal_close)
  286. , m_remote_close_code(close::status::abnormal_close)
  287. , m_is_http(false)
  288. , m_http_state(session::http_state::init)
  289. , m_was_clean(false)
  290. {
  291. m_alog->write(log::alevel::devel,"connection constructor");
  292. }
  293. /// Get a shared pointer to this component
  294. ptr get_shared() {
  295. return lib::static_pointer_cast<type>(transport_con_type::get_shared());
  296. }
  297. ///////////////////////////
  298. // Set Handler Callbacks //
  299. ///////////////////////////
  300. /// Set open handler
  301. /**
  302. * The open handler is called after the WebSocket handshake is complete and
  303. * the connection is considered OPEN.
  304. *
  305. * @param h The new open_handler
  306. */
  307. void set_open_handler(open_handler h) {
  308. m_open_handler = h;
  309. }
  310. /// Set close handler
  311. /**
  312. * The close handler is called immediately after the connection is closed.
  313. *
  314. * @param h The new close_handler
  315. */
  316. void set_close_handler(close_handler h) {
  317. m_close_handler = h;
  318. }
  319. /// Set fail handler
  320. /**
  321. * The fail handler is called whenever the connection fails while the
  322. * handshake is bring processed.
  323. *
  324. * @param h The new fail_handler
  325. */
  326. void set_fail_handler(fail_handler h) {
  327. m_fail_handler = h;
  328. }
  329. /// Set ping handler
  330. /**
  331. * The ping handler is called whenever the connection receives a ping
  332. * control frame. The ping payload is included.
  333. *
  334. * The ping handler's return time controls whether or not a pong is
  335. * sent in response to this ping. Returning false will suppress the
  336. * return pong. If no ping handler is set a pong will be sent.
  337. *
  338. * @param h The new ping_handler
  339. */
  340. void set_ping_handler(ping_handler h) {
  341. m_ping_handler = h;
  342. }
  343. /// Set pong handler
  344. /**
  345. * The pong handler is called whenever the connection receives a pong
  346. * control frame. The pong payload is included.
  347. *
  348. * @param h The new pong_handler
  349. */
  350. void set_pong_handler(pong_handler h) {
  351. m_pong_handler = h;
  352. }
  353. /// Set pong timeout handler
  354. /**
  355. * If the transport component being used supports timers, the pong timeout
  356. * handler is called whenever a pong control frame is not received with the
  357. * configured timeout period after the application sends a ping.
  358. *
  359. * The config setting `timeout_pong` controls the length of the timeout
  360. * period. It is specified in milliseconds.
  361. *
  362. * This can be used to probe the health of the remote endpoint's WebSocket
  363. * implementation. This does not guarantee that the remote application
  364. * itself is still healthy but can be a useful diagnostic.
  365. *
  366. * Note: receipt of this callback doesn't mean the pong will never come.
  367. * This functionality will not suppress delivery of the pong in question
  368. * should it arrive after the timeout.
  369. *
  370. * @param h The new pong_timeout_handler
  371. */
  372. void set_pong_timeout_handler(pong_timeout_handler h) {
  373. m_pong_timeout_handler = h;
  374. }
  375. /// Set interrupt handler
  376. /**
  377. * The interrupt handler is called whenever the connection is manually
  378. * interrupted by the application.
  379. *
  380. * @param h The new interrupt_handler
  381. */
  382. void set_interrupt_handler(interrupt_handler h) {
  383. m_interrupt_handler = h;
  384. }
  385. /// Set http handler
  386. /**
  387. * The http handler is called after an HTTP request other than a WebSocket
  388. * upgrade request is received. It allows a WebSocket++ server to respond
  389. * to regular HTTP requests on the same port as it processes WebSocket
  390. * connections. This can be useful for hosting error messages, flash
  391. * policy files, status pages, and other simple HTTP responses. It is not
  392. * intended to be used as a primary web server.
  393. *
  394. * @param h The new http_handler
  395. */
  396. void set_http_handler(http_handler h) {
  397. m_http_handler = h;
  398. }
  399. /// Set validate handler
  400. /**
  401. * The validate handler is called after a WebSocket handshake has been
  402. * parsed but before a response is returned. It provides the application
  403. * a chance to examine the request and determine whether or not it wants
  404. * to accept the connection.
  405. *
  406. * Returning false from the validate handler will reject the connection.
  407. * If no validate handler is present, all connections will be allowed.
  408. *
  409. * @param h The new validate_handler
  410. */
  411. void set_validate_handler(validate_handler h) {
  412. m_validate_handler = h;
  413. }
  414. /// Set message handler
  415. /**
  416. * The message handler is called after a new message has been received.
  417. *
  418. * @param h The new message_handler
  419. */
  420. void set_message_handler(message_handler h) {
  421. m_message_handler = h;
  422. }
  423. //////////////////////////////////////////
  424. // Connection timeouts and other limits //
  425. //////////////////////////////////////////
  426. /// Set open handshake timeout
  427. /**
  428. * Sets the length of time the library will wait after an opening handshake
  429. * has been initiated before cancelling it. This can be used to prevent
  430. * excessive wait times for outgoing clients or excessive resource usage
  431. * from broken clients or DoS attacks on servers.
  432. *
  433. * Connections that time out will have their fail handlers called with the
  434. * open_handshake_timeout error code.
  435. *
  436. * The default value is specified via the compile time config value
  437. * 'timeout_open_handshake'. The default value in the core config
  438. * is 5000ms. A value of 0 will disable the timer entirely.
  439. *
  440. * To be effective, the transport you are using must support timers. See
  441. * the documentation for your transport policy for details about its
  442. * timer support.
  443. *
  444. * @param dur The length of the open handshake timeout in ms
  445. */
  446. void set_open_handshake_timeout(long dur) {
  447. m_open_handshake_timeout_dur = dur;
  448. }
  449. /// Set close handshake timeout
  450. /**
  451. * Sets the length of time the library will wait after a closing handshake
  452. * has been initiated before cancelling it. This can be used to prevent
  453. * excessive wait times for outgoing clients or excessive resource usage
  454. * from broken clients or DoS attacks on servers.
  455. *
  456. * Connections that time out will have their close handlers called with the
  457. * close_handshake_timeout error code.
  458. *
  459. * The default value is specified via the compile time config value
  460. * 'timeout_close_handshake'. The default value in the core config
  461. * is 5000ms. A value of 0 will disable the timer entirely.
  462. *
  463. * To be effective, the transport you are using must support timers. See
  464. * the documentation for your transport policy for details about its
  465. * timer support.
  466. *
  467. * @param dur The length of the close handshake timeout in ms
  468. */
  469. void set_close_handshake_timeout(long dur) {
  470. m_close_handshake_timeout_dur = dur;
  471. }
  472. /// Set pong timeout
  473. /**
  474. * Sets the length of time the library will wait for a pong response to a
  475. * ping. This can be used as a keepalive or to detect broken connections.
  476. *
  477. * Pong responses that time out will have the pong timeout handler called.
  478. *
  479. * The default value is specified via the compile time config value
  480. * 'timeout_pong'. The default value in the core config
  481. * is 5000ms. A value of 0 will disable the timer entirely.
  482. *
  483. * To be effective, the transport you are using must support timers. See
  484. * the documentation for your transport policy for details about its
  485. * timer support.
  486. *
  487. * @param dur The length of the pong timeout in ms
  488. */
  489. void set_pong_timeout(long dur) {
  490. m_pong_timeout_dur = dur;
  491. }
  492. /// Get maximum message size
  493. /**
  494. * Get maximum message size. Maximum message size determines the point at
  495. * which the connection will fail with the message_too_big protocol error.
  496. *
  497. * The default is set by the endpoint that creates the connection.
  498. *
  499. * @since 0.3.0
  500. */
  501. size_t get_max_message_size() const {
  502. return m_max_message_size;
  503. }
  504. /// Set maximum message size
  505. /**
  506. * Set maximum message size. Maximum message size determines the point at
  507. * which the connection will fail with the message_too_big protocol error.
  508. * This value may be changed during the connection.
  509. *
  510. * The default is set by the endpoint that creates the connection.
  511. *
  512. * @since 0.3.0
  513. *
  514. * @param new_value The value to set as the maximum message size.
  515. */
  516. void set_max_message_size(size_t new_value) {
  517. m_max_message_size = new_value;
  518. if (m_processor) {
  519. m_processor->set_max_message_size(new_value);
  520. }
  521. }
  522. /// Get maximum HTTP message body size
  523. /**
  524. * Get maximum HTTP message body size. Maximum message body size determines
  525. * the point at which the connection will stop reading an HTTP request whose
  526. * body is too large.
  527. *
  528. * The default is set by the endpoint that creates the connection.
  529. *
  530. * @since 0.5.0
  531. *
  532. * @return The maximum HTTP message body size
  533. */
  534. size_t get_max_http_body_size() const {
  535. return m_request.get_max_body_size();
  536. }
  537. /// Set maximum HTTP message body size
  538. /**
  539. * Set maximum HTTP message body size. Maximum message body size determines
  540. * the point at which the connection will stop reading an HTTP request whose
  541. * body is too large.
  542. *
  543. * The default is set by the endpoint that creates the connection.
  544. *
  545. * @since 0.5.0
  546. *
  547. * @param new_value The value to set as the maximum message size.
  548. */
  549. void set_max_http_body_size(size_t new_value) {
  550. m_request.set_max_body_size(new_value);
  551. }
  552. //////////////////////////////////
  553. // Uncategorized public methods //
  554. //////////////////////////////////
  555. /// Get the size of the outgoing write buffer (in payload bytes)
  556. /**
  557. * Retrieves the number of bytes in the outgoing write buffer that have not
  558. * already been dispatched to the transport layer. This represents the bytes
  559. * that are presently cancelable without uncleanly ending the websocket
  560. * connection
  561. *
  562. * This method invokes the m_write_lock mutex
  563. *
  564. * @return The current number of bytes in the outgoing send buffer.
  565. */
  566. size_t get_buffered_amount() const;
  567. /// Get the size of the outgoing write buffer (in payload bytes)
  568. /**
  569. * @deprecated use `get_buffered_amount` instead
  570. */
  571. size_t buffered_amount() const {
  572. return get_buffered_amount();
  573. }
  574. ////////////////////
  575. // Action Methods //
  576. ////////////////////
  577. /// Create a message and then add it to the outgoing send queue
  578. /**
  579. * Convenience method to send a message given a payload string and
  580. * optionally an opcode. Default opcode is utf8 text.
  581. *
  582. * This method locks the m_write_lock mutex
  583. *
  584. * @param payload The payload string to generated the message with
  585. *
  586. * @param op The opcode to generated the message with. Default is
  587. * frame::opcode::text
  588. */
  589. lib::error_code send(std::string const & payload, frame::opcode::value op =
  590. frame::opcode::text);
  591. /// Send a message (raw array overload)
  592. /**
  593. * Convenience method to send a message given a raw array and optionally an
  594. * opcode. Default opcode is binary.
  595. *
  596. * This method locks the m_write_lock mutex
  597. *
  598. * @param payload A pointer to the array containing the bytes to send.
  599. *
  600. * @param len Length of the array.
  601. *
  602. * @param op The opcode to generated the message with. Default is
  603. * frame::opcode::binary
  604. */
  605. lib::error_code send(void const * payload, size_t len, frame::opcode::value
  606. op = frame::opcode::binary);
  607. /// Add a message to the outgoing send queue
  608. /**
  609. * If presented with a prepared message it is added without validation or
  610. * framing. If presented with an unprepared message it is validated, framed,
  611. * and then added
  612. *
  613. * Errors are returned via an exception
  614. * \todo make exception system_error rather than error_code
  615. *
  616. * This method invokes the m_write_lock mutex
  617. *
  618. * @param msg A message_ptr to the message to send.
  619. */
  620. lib::error_code send(message_ptr msg);
  621. /// Asyncronously invoke handler::on_inturrupt
  622. /**
  623. * Signals to the connection to asyncronously invoke the on_inturrupt
  624. * callback for this connection's handler once it is safe to do so.
  625. *
  626. * When the on_inturrupt handler callback is called it will be from
  627. * within the transport event loop with all the thread safety features
  628. * guaranteed by the transport to regular handlers
  629. *
  630. * Multiple inturrupt signals can be active at once on the same connection
  631. *
  632. * @return An error code
  633. */
  634. lib::error_code interrupt();
  635. /// Transport inturrupt callback
  636. void handle_interrupt();
  637. /// Pause reading of new data
  638. /**
  639. * Signals to the connection to halt reading of new data. While reading is paused,
  640. * the connection will stop reading from its associated socket. In turn this will
  641. * result in TCP based flow control kicking in and slowing data flow from the remote
  642. * endpoint.
  643. *
  644. * This is useful for applications that push new requests to a queue to be processed
  645. * by another thread and need a way to signal when their request queue is full without
  646. * blocking the network processing thread.
  647. *
  648. * Use `resume_reading()` to resume.
  649. *
  650. * If supported by the transport this is done asynchronously. As such reading may not
  651. * stop until the current read operation completes. Typically you can expect to
  652. * receive no more bytes after initiating a read pause than the size of the read
  653. * buffer.
  654. *
  655. * If reading is paused for this connection already nothing is changed.
  656. */
  657. lib::error_code pause_reading();
  658. /// Pause reading callback
  659. void handle_pause_reading();
  660. /// Resume reading of new data
  661. /**
  662. * Signals to the connection to resume reading of new data after it was paused by
  663. * `pause_reading()`.
  664. *
  665. * If reading is not paused for this connection already nothing is changed.
  666. */
  667. lib::error_code resume_reading();
  668. /// Resume reading callback
  669. void handle_resume_reading();
  670. /// Send a ping
  671. /**
  672. * Initiates a ping with the given payload/
  673. *
  674. * There is no feedback directly from ping except in cases of immediately
  675. * detectable errors. Feedback will be provided via on_pong or
  676. * on_pong_timeout callbacks.
  677. *
  678. * Ping locks the m_write_lock mutex
  679. *
  680. * @param payload Payload to be used for the ping
  681. */
  682. void ping(std::string const & payload);
  683. /// exception free variant of ping
  684. void ping(std::string const & payload, lib::error_code & ec);
  685. /// Utility method that gets called back when the ping timer expires
  686. void handle_pong_timeout(std::string payload, lib::error_code const & ec);
  687. /// Send a pong
  688. /**
  689. * Initiates a pong with the given payload.
  690. *
  691. * There is no feedback from a pong once sent.
  692. *
  693. * Pong locks the m_write_lock mutex
  694. *
  695. * @param payload Payload to be used for the pong
  696. */
  697. void pong(std::string const & payload);
  698. /// exception free variant of pong
  699. void pong(std::string const & payload, lib::error_code & ec);
  700. /// Close the connection
  701. /**
  702. * Initiates the close handshake process.
  703. *
  704. * If close returns successfully the connection will be in the closing
  705. * state and no additional messages may be sent. All messages sent prior
  706. * to calling close will be written out before the connection is closed.
  707. *
  708. * If no reason is specified none will be sent. If no code is specified
  709. * then no code will be sent.
  710. *
  711. * The handler's on_close callback will be called once the close handshake
  712. * is complete.
  713. *
  714. * Reasons will be automatically truncated to the maximum length (123 bytes)
  715. * if necessary.
  716. *
  717. * @param code The close code to send
  718. * @param reason The close reason to send
  719. */
  720. void close(close::status::value const code, std::string const & reason);
  721. /// exception free variant of close
  722. void close(close::status::value const code, std::string const & reason,
  723. lib::error_code & ec);
  724. ////////////////////////////////////////////////
  725. // Pass-through access to the uri information //
  726. ////////////////////////////////////////////////
  727. /// Returns the secure flag from the connection URI
  728. /**
  729. * This value is available after the HTTP request has been fully read and
  730. * may be called from any thread.
  731. *
  732. * @return Whether or not the connection URI is flagged secure.
  733. */
  734. bool get_secure() const;
  735. /// Returns the host component of the connection URI
  736. /**
  737. * This value is available after the HTTP request has been fully read and
  738. * may be called from any thread.
  739. *
  740. * @return The host component of the connection URI
  741. */
  742. std::string const & get_host() const;
  743. /// Returns the resource component of the connection URI
  744. /**
  745. * This value is available after the HTTP request has been fully read and
  746. * may be called from any thread.
  747. *
  748. * @return The resource component of the connection URI
  749. */
  750. std::string const & get_resource() const;
  751. /// Returns the port component of the connection URI
  752. /**
  753. * This value is available after the HTTP request has been fully read and
  754. * may be called from any thread.
  755. *
  756. * @return The port component of the connection URI
  757. */
  758. uint16_t get_port() const;
  759. /// Gets the connection URI
  760. /**
  761. * This should really only be called by internal library methods unless you
  762. * really know what you are doing.
  763. *
  764. * @return A pointer to the connection's URI
  765. */
  766. uri_ptr get_uri() const;
  767. /// Sets the connection URI
  768. /**
  769. * This should really only be called by internal library methods unless you
  770. * really know what you are doing.
  771. *
  772. * @param uri The new URI to set
  773. */
  774. void set_uri(uri_ptr uri);
  775. /////////////////////////////
  776. // Subprotocol negotiation //
  777. /////////////////////////////
  778. /// Gets the negotated subprotocol
  779. /**
  780. * Retrieves the subprotocol that was negotiated during the handshake. This
  781. * method is valid in the open handler and later.
  782. *
  783. * @return The negotiated subprotocol
  784. */
  785. std::string const & get_subprotocol() const;
  786. /// Gets all of the subprotocols requested by the client
  787. /**
  788. * Retrieves the subprotocols that were requested during the handshake. This
  789. * method is valid in the validate handler and later.
  790. *
  791. * @return A vector of the requested subprotocol
  792. */
  793. std::vector<std::string> const & get_requested_subprotocols() const;
  794. /// Adds the given subprotocol string to the request list (exception free)
  795. /**
  796. * Adds a subprotocol to the list to send with the opening handshake. This
  797. * may be called multiple times to request more than one. If the server
  798. * supports one of these, it may choose one. If so, it will return it
  799. * in it's handshake reponse and the value will be available via
  800. * get_subprotocol(). Subprotocol requests should be added in order of
  801. * preference.
  802. *
  803. * @param request The subprotocol to request
  804. * @param ec A reference to an error code that will be filled in the case of
  805. * errors
  806. */
  807. void add_subprotocol(std::string const & request, lib::error_code & ec);
  808. /// Adds the given subprotocol string to the request list
  809. /**
  810. * Adds a subprotocol to the list to send with the opening handshake. This
  811. * may be called multiple times to request more than one. If the server
  812. * supports one of these, it may choose one. If so, it will return it
  813. * in it's handshake reponse and the value will be available via
  814. * get_subprotocol(). Subprotocol requests should be added in order of
  815. * preference.
  816. *
  817. * @param request The subprotocol to request
  818. */
  819. void add_subprotocol(std::string const & request);
  820. /// Select a subprotocol to use (exception free)
  821. /**
  822. * Indicates which subprotocol should be used for this connection. Valid
  823. * only during the validate handler callback. Subprotocol selected must have
  824. * been requested by the client. Consult get_requested_subprotocols() for a
  825. * list of valid subprotocols.
  826. *
  827. * This member function is valid on server endpoints/connections only
  828. *
  829. * @param value The subprotocol to select
  830. * @param ec A reference to an error code that will be filled in the case of
  831. * errors
  832. */
  833. void select_subprotocol(std::string const & value, lib::error_code & ec);
  834. /// Select a subprotocol to use
  835. /**
  836. * Indicates which subprotocol should be used for this connection. Valid
  837. * only during the validate handler callback. Subprotocol selected must have
  838. * been requested by the client. Consult get_requested_subprotocols() for a
  839. * list of valid subprotocols.
  840. *
  841. * This member function is valid on server endpoints/connections only
  842. *
  843. * @param value The subprotocol to select
  844. */
  845. void select_subprotocol(std::string const & value);
  846. /////////////////////////////////////////////////////////////
  847. // Pass-through access to the request and response objects //
  848. /////////////////////////////////////////////////////////////
  849. /// Retrieve a request header
  850. /**
  851. * Retrieve the value of a header from the handshake HTTP request.
  852. *
  853. * @param key Name of the header to get
  854. * @return The value of the header
  855. */
  856. std::string const & get_request_header(std::string const & key) const;
  857. /// Retrieve a request body
  858. /**
  859. * Retrieve the value of the request body. This value is typically used with
  860. * PUT and POST requests to upload files or other data. Only HTTP
  861. * connections will ever have bodies. WebSocket connection's will always
  862. * have blank bodies.
  863. *
  864. * @return The value of the request body.
  865. */
  866. std::string const & get_request_body() const;
  867. /// Retrieve a response header
  868. /**
  869. * Retrieve the value of a header from the handshake HTTP request.
  870. *
  871. * @param key Name of the header to get
  872. * @return The value of the header
  873. */
  874. std::string const & get_response_header(std::string const & key) const;
  875. /// Get response HTTP status code
  876. /**
  877. * Gets the response status code
  878. *
  879. * @since 0.7.0
  880. *
  881. * @return The response status code sent
  882. */
  883. http::status_code::value get_response_code() const {
  884. return m_response.get_status_code();
  885. }
  886. /// Get response HTTP status message
  887. /**
  888. * Gets the response status message
  889. *
  890. * @since 0.7.0
  891. *
  892. * @return The response status message sent
  893. */
  894. std::string const & get_response_msg() const {
  895. return m_response.get_status_msg();
  896. }
  897. /// Set response status code and message
  898. /**
  899. * Sets the response status code to `code` and looks up the corresponding
  900. * message for standard codes. Non-standard codes will be entered as Unknown
  901. * use set_status(status_code::value,std::string) overload to set both
  902. * values explicitly.
  903. *
  904. * This member function is valid only from the http() and validate() handler
  905. * callbacks.
  906. *
  907. * @param code Code to set
  908. * @param msg Message to set
  909. * @see websocketpp::http::response::set_status
  910. */
  911. void set_status(http::status_code::value code);
  912. /// Set response status code and message
  913. /**
  914. * Sets the response status code and message to independent custom values.
  915. * use set_status(status_code::value) to set the code and have the standard
  916. * message be automatically set.
  917. *
  918. * This member function is valid only from the http() and validate() handler
  919. * callbacks.
  920. *
  921. * @param code Code to set
  922. * @param msg Message to set
  923. * @see websocketpp::http::response::set_status
  924. */
  925. void set_status(http::status_code::value code, std::string const & msg);
  926. /// Set response body content
  927. /**
  928. * Set the body content of the HTTP response to the parameter string. Note
  929. * set_body will also set the Content-Length HTTP header to the appropriate
  930. * value. If you want the Content-Length header to be something else set it
  931. * to something else after calling set_body
  932. *
  933. * This member function is valid only from the http() and validate() handler
  934. * callbacks.
  935. *
  936. * @param value String data to include as the body content.
  937. * @see websocketpp::http::response::set_body
  938. */
  939. void set_body(std::string const & value);
  940. /// Append a header
  941. /**
  942. * If a header with this name already exists the value will be appended to
  943. * the existing header to form a comma separated list of values. Use
  944. * `connection::replace_header` to overwrite existing values.
  945. *
  946. * This member function is valid only from the http() and validate() handler
  947. * callbacks, or to a client connection before connect has been called.
  948. *
  949. * @param key Name of the header to set
  950. * @param val Value to add
  951. * @see replace_header
  952. * @see websocketpp::http::parser::append_header
  953. */
  954. void append_header(std::string const & key, std::string const & val);
  955. /// Replace a header
  956. /**
  957. * If a header with this name already exists the old value will be replaced
  958. * Use `connection::append_header` to append to a list of existing values.
  959. *
  960. * This member function is valid only from the http() and validate() handler
  961. * callbacks, or to a client connection before connect has been called.
  962. *
  963. * @param key Name of the header to set
  964. * @param val Value to set
  965. * @see append_header
  966. * @see websocketpp::http::parser::replace_header
  967. */
  968. void replace_header(std::string const & key, std::string const & val);
  969. /// Remove a header
  970. /**
  971. * Removes a header from the response.
  972. *
  973. * This member function is valid only from the http() and validate() handler
  974. * callbacks, or to a client connection before connect has been called.
  975. *
  976. * @param key The name of the header to remove
  977. * @see websocketpp::http::parser::remove_header
  978. */
  979. void remove_header(std::string const & key);
  980. /// Get request object
  981. /**
  982. * Direct access to request object. This can be used to call methods of the
  983. * request object that are not part of the standard request API that
  984. * connection wraps.
  985. *
  986. * Note use of this method involves using behavior specific to the
  987. * configured HTTP policy. Such behavior may not work with alternate HTTP
  988. * policies.
  989. *
  990. * @since 0.3.0-alpha3
  991. *
  992. * @return A const reference to the raw request object
  993. */
  994. request_type const & get_request() const {
  995. return m_request;
  996. }
  997. /// Get response object
  998. /**
  999. * Direct access to the HTTP response sent or received as a part of the
  1000. * opening handshake. This can be used to call methods of the response
  1001. * object that are not part of the standard request API that connection
  1002. * wraps.
  1003. *
  1004. * Note use of this method involves using behavior specific to the
  1005. * configured HTTP policy. Such behavior may not work with alternate HTTP
  1006. * policies.
  1007. *
  1008. * @since 0.7.0
  1009. *
  1010. * @return A const reference to the raw response object
  1011. */
  1012. response_type const & get_response() const {
  1013. return m_response;
  1014. }
  1015. /// Defer HTTP Response until later (Exception free)
  1016. /**
  1017. * Used in the http handler to defer the HTTP response for this connection
  1018. * until later. Handshake timers will be canceled and the connection will be
  1019. * left open until `send_http_response` or an equivalent is called.
  1020. *
  1021. * Warning: deferred connections won't time out and as a result can tie up
  1022. * resources.
  1023. *
  1024. * @since 0.6.0
  1025. *
  1026. * @return A status code, zero on success, non-zero otherwise
  1027. */
  1028. lib::error_code defer_http_response();
  1029. /// Send deferred HTTP Response (exception free)
  1030. /**
  1031. * Sends an http response to an HTTP connection that was deferred. This will
  1032. * send a complete response including all headers, status line, and body
  1033. * text. The connection will be closed afterwards.
  1034. *
  1035. * @since 0.6.0
  1036. *
  1037. * @param ec A status code, zero on success, non-zero otherwise
  1038. */
  1039. void send_http_response(lib::error_code & ec);
  1040. /// Send deferred HTTP Response
  1041. void send_http_response();
  1042. // TODO HTTPNBIO: write_headers
  1043. // function that processes headers + status so far and writes it to the wire
  1044. // beginning the HTTP response body state. This method will ignore anything
  1045. // in the response body.
  1046. // TODO HTTPNBIO: write_body_message
  1047. // queues the specified message_buffer for async writing
  1048. // TODO HTTPNBIO: finish connection
  1049. //
  1050. // TODO HTTPNBIO: write_response
  1051. // Writes the whole response, headers + body and closes the connection
  1052. /////////////////////////////////////////////////////////////
  1053. // Pass-through access to the other connection information //
  1054. /////////////////////////////////////////////////////////////
  1055. /// Get Connection Handle
  1056. /**
  1057. * The connection handle is a token that can be shared outside the
  1058. * WebSocket++ core for the purposes of identifying a connection and
  1059. * sending it messages.
  1060. *
  1061. * @return A handle to the connection
  1062. */
  1063. connection_hdl get_handle() const {
  1064. return m_connection_hdl;
  1065. }
  1066. /// Get whether or not this connection is part of a server or client
  1067. /**
  1068. * @return whether or not the connection is attached to a server endpoint
  1069. */
  1070. bool is_server() const {
  1071. return m_is_server;
  1072. }
  1073. /// Return the same origin policy origin value from the opening request.
  1074. /**
  1075. * This value is available after the HTTP request has been fully read and
  1076. * may be called from any thread.
  1077. *
  1078. * @return The connection's origin value from the opening handshake.
  1079. */
  1080. std::string const & get_origin() const;
  1081. /// Return the connection state.
  1082. /**
  1083. * Values can be connecting, open, closing, and closed
  1084. *
  1085. * @return The connection's current state.
  1086. */
  1087. session::state::value get_state() const;
  1088. /// Get the WebSocket close code sent by this endpoint.
  1089. /**
  1090. * @return The WebSocket close code sent by this endpoint.
  1091. */
  1092. close::status::value get_local_close_code() const {
  1093. return m_local_close_code;
  1094. }
  1095. /// Get the WebSocket close reason sent by this endpoint.
  1096. /**
  1097. * @return The WebSocket close reason sent by this endpoint.
  1098. */
  1099. std::string const & get_local_close_reason() const {
  1100. return m_local_close_reason;
  1101. }
  1102. /// Get the WebSocket close code sent by the remote endpoint.
  1103. /**
  1104. * @return The WebSocket close code sent by the remote endpoint.
  1105. */
  1106. close::status::value get_remote_close_code() const {
  1107. return m_remote_close_code;
  1108. }
  1109. /// Get the WebSocket close reason sent by the remote endpoint.
  1110. /**
  1111. * @return The WebSocket close reason sent by the remote endpoint.
  1112. */
  1113. std::string const & get_remote_close_reason() const {
  1114. return m_remote_close_reason;
  1115. }
  1116. /// Get the internal error code for a closed/failed connection
  1117. /**
  1118. * Retrieves a machine readable detailed error code indicating the reason
  1119. * that the connection was closed or failed. Valid only after the close or
  1120. * fail handler is called.
  1121. *
  1122. * @return Error code indicating the reason the connection was closed or
  1123. * failed
  1124. */
  1125. lib::error_code get_ec() const {
  1126. return m_ec;
  1127. }
  1128. /// Get a message buffer
  1129. /**
  1130. * Warning: The API related to directly sending message buffers may change
  1131. * before the 1.0 release. If you plan to use it, please keep an eye on any
  1132. * breaking changes notifications in future release notes. Also if you have
  1133. * any feedback about usage and capabilities now is a great time to provide
  1134. * it.
  1135. *
  1136. * Message buffers are used to store message payloads and other message
  1137. * metadata.
  1138. *
  1139. * The size parameter is a hint only. Your final payload does not need to
  1140. * match it. There may be some performance benefits if the initial size
  1141. * guess is equal to or slightly higher than the final payload size.
  1142. *
  1143. * @param op The opcode for the new message
  1144. * @param size A hint to optimize the initial allocation of payload space.
  1145. * @return A new message buffer
  1146. */
  1147. message_ptr get_message(websocketpp::frame::opcode::value op, size_t size)
  1148. const
  1149. {
  1150. return m_msg_manager->get_message(op, size);
  1151. }
  1152. ////////////////////////////////////////////////////////////////////////
  1153. // The remaining public member functions are for internal/policy use //
  1154. // only. Do not call from application code unless you understand what //
  1155. // you are doing. //
  1156. ////////////////////////////////////////////////////////////////////////
  1157. void read_handshake(size_t num_bytes);
  1158. void handle_read_handshake(lib::error_code const & ec,
  1159. size_t bytes_transferred);
  1160. void handle_read_http_response(lib::error_code const & ec,
  1161. size_t bytes_transferred);
  1162. void handle_write_http_response(lib::error_code const & ec);
  1163. void handle_send_http_request(lib::error_code const & ec);
  1164. void handle_open_handshake_timeout(lib::error_code const & ec);
  1165. void handle_close_handshake_timeout(lib::error_code const & ec);
  1166. void handle_read_frame(lib::error_code const & ec, size_t bytes_transferred);
  1167. void read_frame();
  1168. /// Get array of WebSocket protocol versions that this connection supports.
  1169. std::vector<int> const & get_supported_versions() const;
  1170. /// Sets the handler for a terminating connection. Should only be used
  1171. /// internally by the endpoint class.
  1172. void set_termination_handler(termination_handler new_handler);
  1173. void terminate(lib::error_code const & ec);
  1174. void handle_terminate(terminate_status tstat, lib::error_code const & ec);
  1175. /// Checks if there are frames in the send queue and if there are sends one
  1176. /**
  1177. * \todo unit tests
  1178. *
  1179. * This method locks the m_write_lock mutex
  1180. */
  1181. void write_frame();
  1182. /// Process the results of a frame write operation and start the next write
  1183. /**
  1184. * \todo unit tests
  1185. *
  1186. * This method locks the m_write_lock mutex
  1187. *
  1188. * @param terminate Whether or not to terminate the connection upon
  1189. * completion of this write.
  1190. *
  1191. * @param ec A status code from the transport layer, zero on success,
  1192. * non-zero otherwise.
  1193. */
  1194. void handle_write_frame(lib::error_code const & ec);
  1195. // protected:
  1196. // This set of methods would really like to be protected, but doing so
  1197. // requires that the endpoint be able to friend the connection. This is
  1198. // allowed with C++11, but not prior versions
  1199. /// Start the connection state machine
  1200. void start();
  1201. /// Set Connection Handle
  1202. /**
  1203. * The connection handle is a token that can be shared outside the
  1204. * WebSocket++ core for the purposes of identifying a connection and
  1205. * sending it messages.
  1206. *
  1207. * @param hdl A connection_hdl that the connection will use to refer
  1208. * to itself.
  1209. */
  1210. void set_handle(connection_hdl hdl) {
  1211. m_connection_hdl = hdl;
  1212. transport_con_type::set_handle(hdl);
  1213. }
  1214. protected:
  1215. void handle_transport_init(lib::error_code const & ec);
  1216. /// Set m_processor based on information in m_request. Set m_response
  1217. /// status and return an error code indicating status.
  1218. lib::error_code initialize_processor();
  1219. /// Perform WebSocket handshake validation of m_request using m_processor.
  1220. /// set m_response and return an error code indicating status.
  1221. lib::error_code process_handshake_request();
  1222. private:
  1223. /// Completes m_response, serializes it, and sends it out on the wire.
  1224. void write_http_response(lib::error_code const & ec);
  1225. /// Sends an opening WebSocket connect request
  1226. void send_http_request();
  1227. /// Alternate path for write_http_response in error conditions
  1228. void write_http_response_error(lib::error_code const & ec);
  1229. /// Process control message
  1230. /**
  1231. *
  1232. */
  1233. void process_control_frame(message_ptr msg);
  1234. /// Send close acknowledgement
  1235. /**
  1236. * If no arguments are present no close code/reason will be specified.
  1237. *
  1238. * Note: the close code/reason values provided here may be overrided by
  1239. * other settings (such as silent close).
  1240. *
  1241. * @param code The close code to send
  1242. * @param reason The close reason to send
  1243. * @return A status code, zero on success, non-zero otherwise
  1244. */
  1245. lib::error_code send_close_ack(close::status::value code =
  1246. close::status::blank, std::string const & reason = std::string());
  1247. /// Send close frame
  1248. /**
  1249. * If no arguments are present no close code/reason will be specified.
  1250. *
  1251. * Note: the close code/reason values provided here may be overrided by
  1252. * other settings (such as silent close).
  1253. *
  1254. * The ack flag determines what to do in the case of a blank status and
  1255. * whether or not to terminate the TCP connection after sending it.
  1256. *
  1257. * @param code The close code to send
  1258. * @param reason The close reason to send
  1259. * @param ack Whether or not this is an acknowledgement close frame
  1260. * @return A status code, zero on success, non-zero otherwise
  1261. */
  1262. lib::error_code send_close_frame(close::status::value code =
  1263. close::status::blank, std::string const & reason = std::string(), bool ack = false,
  1264. bool terminal = false);
  1265. /// Get a pointer to a new WebSocket protocol processor for a given version
  1266. /**
  1267. * @param version Version number of the WebSocket protocol to get a
  1268. * processor for. Negative values indicate invalid/unknown versions and will
  1269. * always return a null ptr
  1270. *
  1271. * @return A shared_ptr to a new instance of the appropriate processor or a
  1272. * null ptr if there is no installed processor that matches the version
  1273. * number.
  1274. */
  1275. processor_ptr get_processor(int version) const;
  1276. /// Add a message to the write queue
  1277. /**
  1278. * Adds a message to the write queue and updates any associated shared state
  1279. *
  1280. * Must be called while holding m_write_lock
  1281. *
  1282. * @todo unit tests
  1283. *
  1284. * @param msg The message to push
  1285. */
  1286. void write_push(message_ptr msg);
  1287. /// Pop a message from the write queue
  1288. /**
  1289. * Removes and returns a message from the write queue and updates any
  1290. * associated shared state.
  1291. *
  1292. * Must be called while holding m_write_lock
  1293. *
  1294. * @todo unit tests
  1295. *
  1296. * @return the message_ptr at the front of the queue
  1297. */
  1298. message_ptr write_pop();
  1299. /// Prints information about the incoming connection to the access log
  1300. /**
  1301. * Prints information about the incoming connection to the access log.
  1302. * Includes: connection type, websocket version, remote endpoint, user agent
  1303. * path, status code.
  1304. */
  1305. void log_open_result();
  1306. /// Prints information about a connection being closed to the access log
  1307. /**
  1308. * Includes: local and remote close codes and reasons
  1309. */
  1310. void log_close_result();
  1311. /// Prints information about a connection being failed to the access log
  1312. /**
  1313. * Includes: error code and message for why it was failed
  1314. */
  1315. void log_fail_result();
  1316. /// Prints information about HTTP connections
  1317. /**
  1318. * Includes: TODO
  1319. */
  1320. void log_http_result();
  1321. /// Prints information about an arbitrary error code on the specified channel
  1322. template <typename error_type>
  1323. void log_err(log::level l, char const * msg, error_type const & ec) {
  1324. std::stringstream s;
  1325. s << msg << " error: " << ec << " (" << ec.message() << ")";
  1326. m_elog->write(l, s.str());
  1327. }
  1328. // internal handler functions
  1329. read_handler m_handle_read_frame;
  1330. write_frame_handler m_write_frame_handler;
  1331. // static settings
  1332. std::string const m_user_agent;
  1333. /// Pointer to the connection handle
  1334. connection_hdl m_connection_hdl;
  1335. /// Handler objects
  1336. open_handler m_open_handler;
  1337. close_handler m_close_handler;
  1338. fail_handler m_fail_handler;
  1339. ping_handler m_ping_handler;
  1340. pong_handler m_pong_handler;
  1341. pong_timeout_handler m_pong_timeout_handler;
  1342. interrupt_handler m_interrupt_handler;
  1343. http_handler m_http_handler;
  1344. validate_handler m_validate_handler;
  1345. message_handler m_message_handler;
  1346. /// constant values
  1347. long m_open_handshake_timeout_dur;
  1348. long m_close_handshake_timeout_dur;
  1349. long m_pong_timeout_dur;
  1350. size_t m_max_message_size;
  1351. /// External connection state
  1352. /**
  1353. * Lock: m_connection_state_lock
  1354. */
  1355. session::state::value m_state;
  1356. /// Internal connection state
  1357. /**
  1358. * Lock: m_connection_state_lock
  1359. */
  1360. istate_type m_internal_state;
  1361. mutable mutex_type m_connection_state_lock;
  1362. /// The lock used to protect the message queue
  1363. /**
  1364. * Serializes access to the write queue as well as shared state within the
  1365. * processor.
  1366. */
  1367. mutex_type m_write_lock;
  1368. // connection resources
  1369. char m_buf[config::connection_read_buffer_size];
  1370. size_t m_buf_cursor;
  1371. termination_handler m_termination_handler;
  1372. con_msg_manager_ptr m_msg_manager;
  1373. timer_ptr m_handshake_timer;
  1374. timer_ptr m_ping_timer;
  1375. /// @todo this is not memory efficient. this value is not used after the
  1376. /// handshake.
  1377. std::string m_handshake_buffer;
  1378. /// Pointer to the processor object for this connection
  1379. /**
  1380. * The processor provides functionality that is specific to the WebSocket
  1381. * protocol version that the client has negotiated. It also contains all of
  1382. * the state necessary to encode and decode the incoming and outgoing
  1383. * WebSocket byte streams
  1384. *
  1385. * Use of the prepare_data_frame method requires lock: m_write_lock
  1386. */
  1387. processor_ptr m_processor;
  1388. /// Queue of unsent outgoing messages
  1389. /**
  1390. * Lock: m_write_lock
  1391. */
  1392. std::queue<message_ptr> m_send_queue;
  1393. /// Size in bytes of the outstanding payloads in the write queue
  1394. /**
  1395. * Lock: m_write_lock
  1396. */
  1397. size_t m_send_buffer_size;
  1398. /// buffer holding the various parts of the current message being writen
  1399. /**
  1400. * Lock m_write_lock
  1401. */
  1402. std::vector<transport::buffer> m_send_buffer;
  1403. /// a list of pointers to hold on to the messages being written to keep them
  1404. /// from going out of scope before the write is complete.
  1405. std::vector<message_ptr> m_current_msgs;
  1406. /// True if there is currently an outstanding transport write
  1407. /**
  1408. * Lock m_write_lock
  1409. */
  1410. bool m_write_flag;
  1411. /// True if this connection is presently reading new data
  1412. bool m_read_flag;
  1413. // connection data
  1414. request_type m_request;
  1415. response_type m_response;
  1416. uri_ptr m_uri;
  1417. std::string m_subprotocol;
  1418. // connection data that might not be necessary to keep around for the life
  1419. // of the whole connection.
  1420. std::vector<std::string> m_requested_subprotocols;
  1421. bool const m_is_server;
  1422. const lib::shared_ptr<alog_type> m_alog;
  1423. const lib::shared_ptr<elog_type> m_elog;
  1424. rng_type & m_rng;
  1425. // Close state
  1426. /// Close code that was sent on the wire by this endpoint
  1427. close::status::value m_local_close_code;
  1428. /// Close reason that was sent on the wire by this endpoint
  1429. std::string m_local_close_reason;
  1430. /// Close code that was received on the wire from the remote endpoint
  1431. close::status::value m_remote_close_code;
  1432. /// Close reason that was received on the wire from the remote endpoint
  1433. std::string m_remote_close_reason;
  1434. /// Detailed internal error code
  1435. lib::error_code m_ec;
  1436. /// A flag that gets set once it is determined that the connection is an
  1437. /// HTTP connection and not a WebSocket one.
  1438. bool m_is_http;
  1439. /// A flag that gets set when the completion of an http connection is
  1440. /// deferred until later.
  1441. session::http_state::value m_http_state;
  1442. bool m_was_clean;
  1443. };
  1444. } // namespace websocketpp
  1445. #include <websocketpp/impl/connection_impl.hpp>
  1446. #endif // WEBSOCKETPP_CONNECTION_HPP