28#ifndef WEBSOCKETPP_CONNECTION_IMPL_HPP
29#define WEBSOCKETPP_CONNECTION_IMPL_HPP
50namespace istate = session::internal_state;
52template <
typename config>
57 "connection set_termination_handler");
61 m_termination_handler = new_handler;
64template <
typename config>
67 return m_processor->get_origin(m_request);
70template <
typename config>
73 return m_send_buffer_size;
76template <
typename config>
82template <
typename config>
86 message_ptr msg = m_msg_manager->get_message(
op,payload.size());
87 msg->append_payload(payload);
88 msg->set_compressed(
true);
93template <
typename config>
98 msg->append_payload(payload,
len);
103template <
typename config>
111 scoped_lock_type
lock(m_connection_state_lock);
118 bool needs_writing =
false;
120 if (msg->get_prepared()) {
123 scoped_lock_type
lock(m_write_lock);
124 write_push(outgoing_msg);
125 needs_writing = !m_write_flag && !m_send_queue.empty();
127 outgoing_msg = m_msg_manager->get_message();
133 scoped_lock_type
lock(m_write_lock);
134 lib::error_code ec = m_processor->prepare_data_frame(msg,outgoing_msg);
140 write_push(outgoing_msg);
141 needs_writing = !m_write_flag && !m_send_queue.empty();
145 transport_con_type::dispatch(lib::bind(
151 return lib::error_code();
154template <
typename config>
163 std::stringstream ss;
164 ss <<
"connection::ping called from invalid state " << m_state;
177 ec = m_processor->prepare_ping(payload,msg);
181 if (m_pong_timeout_handler) {
184 m_ping_timer->cancel();
187 if (m_pong_timeout_dur > 0) {
188 m_ping_timer = transport_con_type::set_timer(
191 &type::handle_pong_timeout,
194 lib::placeholders::_1
202 set but the transport in use does not support timeouts.");
206 bool needs_writing =
false;
210 needs_writing = !m_write_flag && !m_send_queue.empty();
214 transport_con_type::dispatch(lib::bind(
220 ec = lib::error_code();
223template<
typename config>
232template<
typename config>
234 lib::error_code
const & ec)
246 if (m_pong_timeout_handler) {
247 m_pong_timeout_handler(m_connection_hdl,payload);
251template <
typename config>
260 std::stringstream ss;
261 ss <<
"connection::pong called from invalid state " << m_state;
274 ec = m_processor->prepare_pong(payload,msg);
277 bool needs_writing =
false;
281 needs_writing = !m_write_flag && !m_send_queue.empty();
285 transport_con_type::dispatch(lib::bind(
291 ec = lib::error_code();
294template<
typename config>
303template <
typename config>
305 std::string
const & reason, lib::error_code & ec)
312 std::string tr(reason,0,std::min<size_t>(reason.size(),
313 frame::limits::close_reason_size));
325template<
typename config>
327 std::string
const & reason)
330 close(code,reason,ec);
340template <
typename config>
343 return transport_con_type::interrupt(
345 &type::handle_interrupt,
352template <
typename config>
354 if (m_interrupt_handler) {
355 m_interrupt_handler(m_connection_hdl);
359template <
typename config>
362 return transport_con_type::dispatch(
364 &type::handle_pause_reading,
371template <
typename config>
377template <
typename config>
380 return transport_con_type::dispatch(
382 &type::handle_resume_reading,
389template <
typename config>
405template <
typename config>
408 return m_uri->get_secure();
411template <
typename config>
414 return m_uri->get_host();
417template <
typename config>
420 return m_uri->get_resource();
423template <
typename config>
426 return m_uri->get_port();
429template <
typename config>
435template <
typename config>
446template <
typename config>
448 return m_subprotocol;
451template <
typename config>
452std::vector<std::string>
const &
454 return m_requested_subprotocols;
457template <
typename config>
459 lib::error_code & ec)
468 http::is_not_token_char) !=
value.end())
474 m_requested_subprotocols.push_back(
value);
477template <
typename config>
480 this->add_subprotocol(
value,ec);
487template <
typename config>
489 lib::error_code & ec)
497 ec = lib::error_code();
501 std::vector<std::string>::iterator it;
503 it = std::find(m_requested_subprotocols.begin(),
504 m_requested_subprotocols.end(),
507 if (it == m_requested_subprotocols.end()) {
512 m_subprotocol =
value;
515template <
typename config>
518 this->select_subprotocol(
value,ec);
525template <
typename config>
528 return m_request.get_header(key);
531template <
typename config>
534 return m_request.get_body();
537template <
typename config>
540 return m_response.get_header(key);
544template <
typename config>
548 throw exception(
"Call to set_status from invalid state",
551 m_response.set_status(code);
555template <
typename config>
557 std::string
const & msg)
560 throw exception(
"Call to set_status from invalid state",
564 m_response.set_status(code,msg);
568template <
typename config>
571 throw exception(
"Call to set_status from invalid state",
575 m_response.set_body(
value);
578template <
typename config>
581 throw exception(
"Call to set_status from invalid state",
585 m_response.set_body(std::move(
value));
589template <
typename config>
591 std::string
const & val)
596 m_response.append_header(key,val);
598 throw exception(
"Call to append_header from invalid state",
604 m_request.append_header(key,val);
606 throw exception(
"Call to append_header from invalid state",
613template <
typename config>
615 std::string
const & val)
620 m_response.replace_header(key,val);
622 throw exception(
"Call to replace_header from invalid state",
628 m_request.replace_header(key,val);
630 throw exception(
"Call to replace_header from invalid state",
637template <
typename config>
643 m_response.remove_header(key);
645 throw exception(
"Call to remove_header from invalid state",
651 m_request.remove_header(key);
653 throw exception(
"Call to remove_header from invalid state",
670template <
typename config>
674 if (m_handshake_timer) {
675 m_handshake_timer->cancel();
676 m_handshake_timer.reset();
682 return lib::error_code();
695template <
typename config>
707 this->write_http_response(lib::error_code());
708 ec = lib::error_code();
711template <
typename config>
714 this->send_http_response(ec);
725template <
typename config>
740 transport_con_type::init(
742 &type::handle_transport_init,
744 lib::placeholders::_1
749template <
typename config>
753 lib::error_code ecm = ec;
757 "handle_transport_init must be called from transport init state");
763 s <<
"handle_transport_init received error: "<< ecm.message();
773 this->read_handshake(1);
778 m_processor = get_processor(config::client_version);
779 this->send_http_request();
783template <
typename config>
787 if (m_open_handshake_timeout_dur > 0) {
788 m_handshake_timer = transport_con_type::set_timer(
789 m_open_handshake_timeout_dur,
791 &type::handle_open_handshake_timeout,
793 lib::placeholders::_1
798 transport_con_type::async_read_at_least(
801 config::connection_read_buffer_size,
803 &type::handle_read_handshake,
805 lib::placeholders::_1,
806 lib::placeholders::_2
813template <
typename config>
815 size_t bytes_transferred)
819 lib::error_code ecm = ec;
833 "handle_read_handshake invoked after connection was closed");
844 "got (expected) eof/state error from closed con");
854 if (bytes_transferred > config::connection_read_buffer_size) {
860 size_t bytes_processed = 0;
862 bytes_processed = m_request.consume(m_buf,bytes_transferred);
863 }
catch (http::exception &e) {
866 m_response.set_status(e.m_error_code,e.m_error_msg);
873 if (bytes_processed > bytes_transferred) {
881 s <<
"bytes_transferred: " << bytes_transferred
882 <<
" bytes, bytes processed: " << bytes_processed <<
" bytes";
886 if (m_request.ready()) {
887 lib::error_code processor_ec = this->initialize_processor();
889 this->write_http_response_error(processor_ec);
893 if (m_processor && m_processor->get_version() == 0) {
896 if (bytes_transferred-bytes_processed >= 8) {
897 m_request.replace_header(
898 "Sec-WebSocket-Key3",
899 std::string(m_buf+bytes_processed,m_buf+bytes_processed+8)
901 bytes_processed += 8;
913 if (!m_request.get_header(
"Sec-WebSocket-Key3").empty()) {
922 std::copy(m_buf+bytes_processed,m_buf+bytes_transferred,m_buf);
923 m_buf_cursor = bytes_transferred-bytes_processed;
929 lib::error_code handshake_ec = this->process_handshake_request();
935 this->write_http_response(handshake_ec);
939 transport_con_type::async_read_at_least(
942 config::connection_read_buffer_size,
944 &type::handle_read_handshake,
946 lib::placeholders::_1,
947 lib::placeholders::_2
958template <
typename config>
962 "write_http_response_error called in invalid state");
969 this->write_http_response(ec);
974template <
typename config>
976 size_t bytes_transferred)
980 lib::error_code ecm = ec;
1009 "handle_read_frame: got invalid istate in closed state");
1025 log_err(echannel,
"handle_read_frame", ecm);
1040 std::stringstream
s;
1041 s <<
"p = " <<
p <<
" bytes transferred = " << bytes_transferred;
1045 while (
p < bytes_transferred) {
1047 std::stringstream
s;
1048 s <<
"calling consume with " << bytes_transferred-
p <<
" bytes";
1052 lib::error_code consume_ec;
1055 std::stringstream
s;
1060 p += m_processor->consume(
1061 reinterpret_cast<uint8_t*
>(m_buf)+
p,
1062 bytes_transferred-
p,
1067 std::stringstream
s;
1068 s <<
"bytes left after consume: " << bytes_transferred-
p;
1074 if (config::drop_on_protocol_error) {
1078 lib::error_code close_ec;
1081 consume_ec.message(),
1094 if (m_processor->ready()) {
1096 std::stringstream
s;
1097 s <<
"Complete message received. Dispatching";
1109 }
else if (m_message_handler) {
1110 m_message_handler(m_connection_hdl, msg);
1113 process_control_frame(msg);
1122template <
typename config>
1128 transport_con_type::async_read_at_least(
1138 config::connection_read_buffer_size,
1143template <
typename config>
1149 return lib::error_code();
1160 m_processor = get_processor(version);
1164 return lib::error_code();
1172 std::stringstream ss;
1174 std::vector<int>::const_iterator it;
1175 for (it = versions_supported.begin(); it != versions_supported.end(); it++)
1181 m_response.replace_header(
"Sec-WebSocket-Version",
ss.str());
1185template <
typename config>
1196 (transport_con_type::is_secure() ?
"https" :
"http")
1199 if (!m_uri->get_valid()) {
1205 if (m_http_handler) {
1207 m_http_handler(m_connection_hdl);
1217 return lib::error_code();
1220 lib::error_code ec = m_processor->validate_handshake(m_request);
1232 std::pair<lib::error_code,std::string> neg_results;
1233 neg_results = m_processor->negotiate_extensions(m_request);
1235 if (neg_results.first) {
1240 return neg_results.first;
1245 if (neg_results.second.size() > 0) {
1246 m_response.replace_header(
"Sec-WebSocket-Extensions",
1247 neg_results.second);
1252 m_uri = m_processor->get_uri(m_request);
1255 if (!m_uri->get_valid()) {
1262 lib::error_code subp_ec = m_processor->extract_subprotocols(m_request,
1263 m_requested_subprotocols);
1270 if (!m_validate_handler || m_validate_handler(m_connection_hdl)) {
1275 ec = m_processor->process_handshake(m_request,m_subprotocol,m_response);
1278 std::stringstream
s;
1279 s <<
"Processing error: " << ec <<
"(" << ec.message() <<
")";
1299 return lib::error_code();
1302template <
typename config>
1318 m_response.set_version(
"HTTP/1.1");
1321 if (m_response.get_header(
"Server").empty()) {
1322 if (!m_user_agent.empty()) {
1323 m_response.replace_header(
"Server",m_user_agent);
1325 m_response.remove_header(
"Server");
1333 m_handshake_buffer = m_processor->get_raw(m_response);
1336 m_handshake_buffer = m_response.raw();
1341 if (!m_response.get_header(
"Sec-WebSocket-Key3").empty()) {
1348 transport_con_type::async_write(
1349 m_handshake_buffer.data(),
1350 m_handshake_buffer.size(),
1352 &type::handle_write_http_response,
1354 lib::placeholders::_1
1359template <
typename config>
1363 lib::error_code ecm = ec;
1377 "handle_write_http_response invoked after connection was closed");
1388 "got (expected) eof/state error from closed con");
1397 if (m_handshake_timer) {
1398 m_handshake_timer->cancel();
1399 m_handshake_timer.reset();
1409 std::stringstream
s;
1410 s <<
"Handshake ended with HTTP error: "
1411 << m_response.get_status_code();
1417 this->log_http_result();
1421 "got to writing HTTP results with m_ec set: "+m_ec.message());
1430 this->log_open_result();
1435 if (m_open_handler) {
1436 m_open_handler(m_connection_hdl);
1439 this->handle_read_frame(lib::error_code(), m_buf_cursor);
1442template <
typename config>
1443void connection<config>::send_http_request() {
1452 ec = m_processor->client_handshake_request(m_request,m_uri,
1453 m_requested_subprotocols);
1465 if (m_request.get_header(
"User-Agent").empty()) {
1466 if (!m_user_agent.empty()) {
1467 m_request.replace_header(
"User-Agent",m_user_agent);
1469 m_request.remove_header(
"User-Agent");
1473 m_handshake_buffer = m_request.raw();
1479 if (m_open_handshake_timeout_dur > 0) {
1480 m_handshake_timer = transport_con_type::set_timer(
1481 m_open_handshake_timeout_dur,
1483 &type::handle_open_handshake_timeout,
1485 lib::placeholders::_1
1490 transport_con_type::async_write(
1491 m_handshake_buffer.data(),
1492 m_handshake_buffer.size(),
1494 &type::handle_send_http_request,
1496 lib::placeholders::_1
1501template <
typename config>
1505 lib::error_code ecm = ec;
1521 "handle_send_http_request invoked after connection was closed");
1532 "got (expected) eof/state error from closed con");
1541 transport_con_type::async_read_at_least(
1544 config::connection_read_buffer_size,
1546 &type::handle_read_http_response,
1548 lib::placeholders::_1,
1549 lib::placeholders::_2
1554template <
typename config>
1556 size_t bytes_transferred)
1560 lib::error_code ecm = ec;
1574 "handle_read_http_response invoked after connection was closed");
1585 "got (expected) eof/state error from closed con");
1594 size_t bytes_processed = 0;
1597 bytes_processed = m_response.consume(m_buf,bytes_transferred);
1598 }
catch (http::exception & e) {
1600 std::string(
"error in handle_read_http_response: ")+e.what());
1607 if (m_response.headers_ready()) {
1608 if (m_handshake_timer) {
1609 m_handshake_timer->cancel();
1610 m_handshake_timer.reset();
1613 lib::error_code validate_ec = m_processor->validate_server_handshake_response(
1625 std::pair<lib::error_code,std::string> neg_results;
1626 neg_results = m_processor->negotiate_extensions(m_response);
1628 if (neg_results.first) {
1637 + neg_results.first.message());
1646 this->log_open_result();
1648 if (m_open_handler) {
1649 m_open_handler(m_connection_hdl);
1655 std::copy(m_buf+bytes_processed,m_buf+bytes_transferred,m_buf);
1656 m_buf_cursor = bytes_transferred-bytes_processed;
1658 this->handle_read_frame(lib::error_code(), m_buf_cursor);
1660 transport_con_type::async_read_at_least(
1663 config::connection_read_buffer_size,
1665 &type::handle_read_http_response,
1667 lib::placeholders::_1,
1668 lib::placeholders::_2
1674template <
typename config>
1676 lib::error_code
const & ec)
1682 "open handle_open_handshake_timeout error: "+ec.message());
1690template <
typename config>
1692 lib::error_code
const & ec)
1698 "asio open handle_close_handshake_timeout error: "+ec.message());
1706template <
typename config>
1713 if (m_handshake_timer) {
1714 m_handshake_timer->cancel();
1715 m_handshake_timer.reset();
1718 terminate_status tstat =
unknown;
1721 m_local_close_code = close::status::abnormal_close;
1722 m_local_close_reason = ec.message();
1743 "terminate called on connection that was already terminated");
1749 transport_con_type::async_shutdown(
1751 &type::handle_terminate,
1754 lib::placeholders::_1
1759template <
typename config>
1761 lib::error_code
const & ec)
1773 if (tstat == failed) {
1775 if (m_fail_handler) {
1776 m_fail_handler(m_connection_hdl);
1779 }
else if (tstat == closed) {
1780 if (m_close_handler) {
1781 m_close_handler(m_connection_hdl);
1791 if (m_termination_handler) {
1793 m_termination_handler(type::get_shared());
1794 }
catch (std::exception
const & e) {
1796 std::string(
"termination_handler call failed. Reason was: ")+e.what());
1801template <
typename config>
1819 while (next_message) {
1820 m_current_msgs.push_back(next_message);
1821 if (!next_message->get_terminal()) {
1822 next_message = write_pop();
1828 if (m_current_msgs.empty()) {
1835 m_write_flag =
true;
1839 typename std::vector<message_ptr>::iterator it;
1840 for (it = m_current_msgs.begin(); it != m_current_msgs.end(); ++it) {
1841 std::string
const & header = (*it)->get_header();
1842 std::string
const & payload = (*it)->get_payload();
1851 std::stringstream general,header,payload;
1853 general <<
"Dispatching write containing " << m_current_msgs.size()
1854 <<
" message(s) containing ";
1855 header <<
"Header Bytes: \n";
1856 payload <<
"Payload Bytes: \n";
1861 for (
size_t i = 0; i < m_current_msgs.size(); i++) {
1862 hbytes += m_current_msgs[i]->get_header().size();
1863 pbytes += m_current_msgs[i]->get_payload().size();
1866 header <<
"[" << i <<
"] ("
1867 << m_current_msgs[i]->get_header().size() <<
") "
1872 payload <<
"[" << i <<
"] ("
1873 << m_current_msgs[i]->get_payload().size() <<
") ["<<m_current_msgs[i]->get_opcode()<<
"] "
1875 m_current_msgs[i]->get_payload() :
1883 general << hbytes <<
" header bytes and " << pbytes <<
" payload bytes";
1891 transport_con_type::async_write(
1893 m_write_frame_handler
1897template <
typename config>
1904 bool terminal = m_current_msgs.back()->get_terminal();
1906 m_send_buffer.clear();
1907 m_current_msgs.clear();
1921 bool needs_writing =
false;
1926 m_write_flag =
false;
1928 needs_writing = !m_send_queue.empty();
1931 if (needs_writing) {
1932 transport_con_type::dispatch(lib::bind(
1939template <
typename config>
1942 return versions_supported;
1945template <
typename config>
1953 std::stringstream
s;
1954 s <<
"Control frame received with opcode " <<
op;
1967 bool should_reply =
true;
1969 if (m_ping_handler) {
1970 should_reply = m_ping_handler(m_connection_hdl, msg->get_payload());
1974 this->
pong(msg->get_payload(),ec);
1980 if (m_pong_handler) {
1981 m_pong_handler(m_connection_hdl, msg->get_payload());
1984 m_ping_timer->cancel();
1993 if (config::drop_on_protocol_error) {
1994 s <<
"Received invalid close code " << m_remote_close_code
1995 <<
" dropping connection per config.";
1999 s <<
"Received invalid close code " << m_remote_close_code
2000 <<
" sending acknowledgement and closing";
2002 ec = send_close_ack(close::status::protocol_error,
2003 "Invalid close code");
2013 if (config::drop_on_protocol_error) {
2015 "Received invalid close reason. Dropping connection per config");
2019 "Received invalid close reason. Sending acknowledgement and closing");
2020 ec = send_close_ack(close::status::protocol_error,
2021 "Invalid close reason");
2031 s <<
"Received close frame with code " << m_remote_close_code
2032 <<
" and reason " << m_remote_close_reason;
2035 ec = send_close_ack();
2066template <
typename config>
2068 std::string
const & reason)
2070 return send_close_frame(code,reason,
true,m_is_server);
2073template <
typename config>
2075 std::string
const & reason,
bool ack,
bool terminal)
2087 if (config::silent_close) {
2089 m_local_close_code = close::status::no_status;
2090 m_local_close_reason.clear();
2091 }
else if (code != close::status::blank) {
2093 m_local_close_code = code;
2094 m_local_close_reason = reason;
2097 m_local_close_code = close::status::no_status;
2098 m_local_close_reason.clear();
2099 }
else if (m_remote_close_code == close::status::no_status) {
2101 "acknowledging a no-status close with normal code");
2102 m_local_close_code = close::status::normal;
2103 m_local_close_reason.clear();
2106 m_local_close_code = m_remote_close_code;
2107 m_local_close_reason = m_remote_close_reason;
2110 std::stringstream
s;
2111 s <<
"Closing with code: " << m_local_close_code <<
", and reason: "
2112 << m_local_close_reason;
2120 lib::error_code ec = m_processor->prepare_close(m_local_close_code,
2121 m_local_close_reason,msg);
2130 msg->set_terminal(
true);
2141 if (m_close_handshake_timeout_dur > 0) {
2142 m_handshake_timer = transport_con_type::set_timer(
2143 m_close_handshake_timeout_dur,
2145 &type::handle_close_handshake_timeout,
2147 lib::placeholders::_1
2152 bool needs_writing =
false;
2154 scoped_lock_type
lock(m_write_lock);
2156 needs_writing = !m_write_flag && !m_send_queue.empty();
2159 if (needs_writing) {
2160 transport_con_type::dispatch(lib::bind(
2166 return lib::error_code();
2169template <
typename config>
2171connection<config>::get_processor(
int version)
const {
2178 p = lib::make_shared<processor::hybi00<config> >(
2179 transport_con_type::is_secure(),
2185 p = lib::make_shared<processor::hybi07<config> >(
2186 transport_con_type::is_secure(),
2193 p = lib::make_shared<processor::hybi08<config> >(
2194 transport_con_type::is_secure(),
2201 p = lib::make_shared<processor::hybi13<config> >(
2202 transport_con_type::is_secure(),
2213 p->set_max_message_size(m_max_message_size);
2218template <
typename config>
2219void connection<config>::write_push(
typename config::message_type::ptr msg)
2225 m_send_buffer_size += msg->get_payload().
size();
2226 m_send_queue.push(msg);
2229 std::stringstream
s;
2230 s <<
"write_push: message count: " << m_send_queue.size()
2231 <<
" buffer size: " << m_send_buffer_size;
2236template <
typename config>
2237typename config::message_type::ptr connection<config>::write_pop()
2241 if (m_send_queue.empty()) {
2245 msg = m_send_queue.front();
2247 m_send_buffer_size -= msg->get_payload().size();
2251 std::stringstream
s;
2252 s <<
"write_pop: message count: " << m_send_queue.size()
2253 <<
" buffer size: " << m_send_buffer_size;
2259template <
typename config>
2260void connection<config>::log_open_result()
2262 std::stringstream
s;
2272 s << (
version == -1 ?
"HTTP" :
"WebSocket") <<
" Connection ";
2275 s << transport_con_type::get_remote_endpoint() <<
" ";
2278 if (version != -1) {
2283 std::string ua = m_request.get_header(
"User-Agent");
2292 s << (m_uri ? m_uri->get_resource() :
"NULL") <<
" ";
2295 s << m_response.get_status_code();
2300template <
typename config>
2301void connection<config>::log_close_result()
2303 std::stringstream
s;
2306 <<
"close local:[" << m_local_close_code
2307 << (m_local_close_reason.empty() ?
"" :
","+m_local_close_reason)
2308 <<
"] remote:[" << m_remote_close_code
2309 << (m_remote_close_reason.empty() ?
"" :
","+m_remote_close_reason) <<
"]";
2314template <
typename config>
2315void connection<config>::log_fail_result()
2317 std::stringstream
s;
2322 s <<
"WebSocket Connection ";
2325 s << transport_con_type::get_remote_endpoint();
2333 std::string ua = m_request.get_header(
"User-Agent");
2342 s << (m_uri ? m_uri->get_resource() :
"-");
2345 s <<
" " << m_response.get_status_code();
2348 s <<
" " << m_ec <<
" " << m_ec.message();
2353template <
typename config>
2354void connection<config>::log_http_result() {
2355 std::stringstream
s;
2363 s << (m_request.get_header(
"host").empty() ?
"-" : m_request.get_header(
"host"))
2364 <<
" " << transport_con_type::get_remote_endpoint()
2365 <<
" \"" << m_request.get_method()
2366 <<
" " << (m_uri ? m_uri->get_resource() :
"-")
2367 <<
" " << m_request.get_version() <<
"\" " << m_response.get_status_code()
2368 <<
" " << m_response.get_body().size();
2371 std::string ua = m_request.get_header(
"User-Agent");
Represents an individual WebSocket connection.
void handle_interrupt()
Transport inturrupt callback.
lib::function< void(ptr)> termination_handler
void handle_close_handshake_timeout(lib::error_code const &ec)
lib::error_code interrupt()
Asyncronously invoke handler::on_inturrupt.
void start()
Start the connection state machine.
std::string const & get_request_body() const
Retrieve a request body.
void ping(std::string const &payload)
Send a ping.
void handle_read_http_response(lib::error_code const &ec, size_t bytes_transferred)
lib::error_code defer_http_response()
Defer HTTP Response until later (Exception free)
lib::error_code resume_reading()
Resume reading of new data.
void add_subprotocol(std::string const &request, lib::error_code &ec)
Adds the given subprotocol string to the request list (exception free)
bool get_secure() const
Returns the secure flag from the connection URI.
lib::shared_ptr< processor_type > processor_ptr
void set_body(std::string const &value)
Set response body content.
size_t get_buffered_amount() const
Get the size of the outgoing write buffer (in payload bytes)
std::string const & get_origin() const
Return the same origin policy origin value from the opening request.
message_type::ptr message_ptr
std::string const & get_host() const
Returns the host component of the connection URI.
void handle_terminate(terminate_status tstat, lib::error_code const &ec)
std::string const & get_resource() const
Returns the resource component of the connection URI.
void select_subprotocol(std::string const &value, lib::error_code &ec)
Select a subprotocol to use (exception free)
std::string const & get_request_header(std::string const &key) const
Retrieve a request header.
lib::error_code process_handshake_request()
void handle_pause_reading()
Pause reading callback.
std::vector< int > const & get_supported_versions() const
Get array of WebSocket protocol versions that this connection supports.
void remove_header(std::string const &key)
Remove a header.
uri_ptr get_uri() const
Gets the connection URI.
void handle_write_http_response(lib::error_code const &ec)
void terminate(lib::error_code const &ec)
std::string const & get_response_header(std::string const &key) const
Retrieve a response header.
void handle_write_frame(lib::error_code const &ec)
Process the results of a frame write operation and start the next write.
void write_frame()
Checks if there are frames in the send queue and if there are sends one.
session::state::value get_state() const
Return the connection state.
void set_status(http::status_code::value code)
Set response status code and message.
void replace_header(std::string const &key, std::string const &val)
Replace a header.
concurrency_type::scoped_lock_type scoped_lock_type
void handle_read_handshake(lib::error_code const &ec, size_t bytes_transferred)
void read_handshake(size_t num_bytes)
void pong(std::string const &payload)
Send a pong.
void send_http_response()
Send deferred HTTP Response.
void handle_read_frame(lib::error_code const &ec, size_t bytes_transferred)
lib::error_code initialize_processor()
void set_uri(uri_ptr uri)
Sets the connection URI.
void set_termination_handler(termination_handler new_handler)
void handle_transport_init(lib::error_code const &ec)
lib::error_code pause_reading()
Pause reading of new data.
void handle_resume_reading()
Resume reading callback.
std::vector< std::string > const & get_requested_subprotocols() const
Gets all of the subprotocols requested by the client.
void close(close::status::value const code, std::string const &reason)
Close the connection.
std::string const & get_subprotocol() const
Gets the negotated subprotocol.
void handle_open_handshake_timeout(lib::error_code const &ec)
void handle_pong_timeout(std::string payload, lib::error_code const &ec)
Utility method that gets called back when the ping timer expires.
void handle_send_http_request(lib::error_code const &ec)
lib::error_code send(std::string const &payload, frame::opcode::value op=frame::opcode::text)
Create a message and then add it to the outgoing send queue.
void read_frame()
Issue a new transport read unless reading is paused.
uint16_t get_port() const
Returns the port component of the connection URI.
void append_header(std::string const &key, std::string const &val)
Append a header.
websocketpp::config::asio_tls_client::message_type::ptr message_ptr
void close(T *e, websocketpp::connection_hdl hdl)
static const Segment ss(Segment::ss)
bool terminal(value code)
Determine if the code represents an unrecoverable error.
uint16_t value
The type of a close code value.
std::string extract_reason(std::string const &payload, lib::error_code &ec)
Extract the reason string from a close payload.
status::value extract_code(std::string const &payload, lib::error_code &ec)
Extract a close code value from a close payload.
@ general
Catch-all library error.
@ unrequested_subprotocol
Selected subprotocol was not requested by the client.
@ client_only
Attempted to use a client specific feature on a server endpoint.
@ http_connection_ended
HTTP connection ended.
@ no_outgoing_buffers
The endpoint is out of outgoing message buffers.
@ http_parse_error
HTTP parse error.
@ invalid_state
The connection was in the wrong state for this operation.
@ extension_neg_failed
Extension negotiation failed.
@ rejected
Connection rejected.
@ unsupported_version
Unsupported WebSocket protocol version.
@ server_only
Attempted to use a server specific feature on a client endpoint.
@ close_handshake_timeout
WebSocket close handshake timed out.
@ invalid_subprotocol
Invalid subprotocol.
@ open_handshake_timeout
WebSocket opening handshake timed out.
@ invalid_version
Invalid WebSocket protocol version.
@ invalid_uri
An invalid uri was supplied.
lib::error_code make_error_code(error::value e)
bool is_control(value v)
Check if an opcode is for a control frame.
uint32_t level
Type of a channel package.
close::status::value to_ws(lib::error_code ec)
Converts a processor error_code into a websocket close code.
lib::error_code make_error_code(error::processor_errors e)
Create an error code with the given value and the processor category.
int get_websocket_version(request_type &r)
Extract the version from a WebSocket handshake request.
uri_ptr get_uri_from_host(request_type &request, std::string scheme)
Extract a URI ptr from the host header of the request.
bool is_websocket_handshake(request_type &r)
Determine whether or not a generic HTTP request is a WebSocket handshake.
@ operation_aborted
Operation aborted.
@ action_after_shutdown
read or write after shutdown
@ tls_short_read
TLS short read.
std::string to_hex(std::string const &input)
Convert std::string to ascii printed string of hex digits.
std::string string_replace_all(std::string subject, std::string const &search, std::string const &replace)
Replace all occurrances of a substring with another.
Namespace for the WebSocket++ project.
lib::shared_ptr< uri > uri_ptr
Pointer to a URI.
static level const fail
One line for each failed WebSocket connection with details.
static level const devel
Development messages (warning: very chatty)
static level const frame_payload
One line per frame, includes the full message payload (warning: chatty)
static level const connect
Information about new connections.
static level const frame_header
One line per frame, includes the full frame header.
static level const control
One line per control frame.
static level const disconnect
One line for each closed connection. Includes closing codes and reasons.
static level const http
Access related to HTTP requests.
static level const devel
Low level debugging information (warning: very chatty)
static level const rerror
A simple utility buffer class.