28#ifndef WEBSOCKETPP_TRANSPORT_ASIO_CON_HPP
29#define WEBSOCKETPP_TRANSPORT_ASIO_CON_HPP
66template <
typename config>
67class connection :
public config::socket_type::socket_con_type {
72 typedef lib::shared_ptr<type>
ptr;
91 typedef lib::shared_ptr<lib::asio::io_service::strand>
strand_ptr;
93 typedef lib::shared_ptr<lib::asio::steady_timer>
timer_ptr;
103 : m_is_server(is_server)
112 return lib::static_pointer_cast<type>(socket_con_type::get_shared());
116 return socket_con_type::is_secure();
132 socket_con_type::set_uri(u);
146 m_tcp_pre_init_handler = h;
175 m_tcp_post_init_handler = h;
194 m_proxy_data = lib::make_shared<proxy_data>();
195 ec = lib::error_code();
219 password, lib::error_code & ec)
227 std::string val =
"Basic "+
base64_encode(username +
":" + password);
228 m_proxy_data->req.replace_header(
"Proxy-Authorization",val);
229 ec = lib::error_code();
257 m_proxy_data->timeout_proxy = duration;
258 ec = lib::error_code();
285 std::string
ret = socket_con_type::get_remote_endpoint(ec);
297 return m_connection_hdl;
315 timer_ptr new_timer = lib::make_shared<lib::asio::steady_timer>(
320 if (config::enable_multithreading) {
321 new_timer->async_wait(m_strand->wrap(lib::bind(
325 lib::placeholders::_1
328 new_timer->async_wait(lib::bind(
332 lib::placeholders::_1
351 lib::asio::error_code
const & ec)
354 if (ec == lib::asio::error::operation_aborted) {
361 callback(lib::error_code());
419 socket_con_type::pre_init(
424 lib::placeholders::_1
442 m_proxy_data->req.set_version(
"HTTP/1.1");
443 m_proxy_data->req.set_method(
"CONNECT");
445 m_proxy_data->req.set_uri(authority);
446 m_proxy_data->req.replace_header(
"Host",authority);
448 return lib::error_code();
462 m_io_service = io_service;
464 if (config::enable_multithreading) {
465 m_strand = lib::make_shared<lib::asio::io_service::strand>(*io_service);
468 lib::error_code ec = socket_con_type::init_asio(io_service, m_strand,
479 if (m_tcp_pre_init_handler) {
480 m_tcp_pre_init_handler(m_connection_hdl);
489 if (!m_proxy.empty()) {
503 if (config::timeout_socket_post_init > 0) {
505 config::timeout_socket_post_init,
511 lib::placeholders::_1
516 socket_con_type::post_init(
522 lib::placeholders::_1
537 lib::error_code
const & ec)
539 lib::error_code ret_ec;
544 "asio post init timer cancelled");
551 if (socket_con_type::get_ec()) {
552 ret_ec = socket_con_type::get_ec();
573 lib::error_code
const & ec)
583 post_timer->cancel();
590 if (m_tcp_post_init_handler) {
591 m_tcp_post_init_handler(m_connection_hdl);
604 "assertion failed: !m_proxy_data in asio::connection::proxy_write");
609 m_proxy_data->write_buf = m_proxy_data->req.raw();
611 m_bufs.push_back(lib::asio::buffer(m_proxy_data->write_buf.data(),
612 m_proxy_data->write_buf.size()));
618 m_proxy_data->timeout_proxy,
623 lib::placeholders::_1
628 if (config::enable_multithreading) {
629 lib::asio::async_write(
630 socket_con_type::get_next_layer(),
632 m_strand->wrap(lib::bind(
635 lib::placeholders::_1
639 lib::asio::async_write(
640 socket_con_type::get_next_layer(),
645 lib::placeholders::_1
655 "asio handle_proxy_write timer cancelled");
662 "asio handle_proxy_write timer expired");
669 lib::asio::error_code
const & ec)
673 "asio connection handle_proxy_write");
681 if (ec == lib::asio::error::operation_aborted ||
690 m_proxy_data->timer->cancel();
705 "assertion failed: !m_proxy_data in asio::connection::proxy_read");
706 m_proxy_data->timer->cancel();
711 if (config::enable_multithreading) {
712 lib::asio::async_read_until(
713 socket_con_type::get_next_layer(),
714 m_proxy_data->read_buf,
716 m_strand->wrap(lib::bind(
719 lib::placeholders::_1, lib::placeholders::_2
723 lib::asio::async_read_until(
724 socket_con_type::get_next_layer(),
725 m_proxy_data->read_buf,
730 lib::placeholders::_1, lib::placeholders::_2
743 lib::asio::error_code
const & ec,
size_t)
747 "asio connection handle_proxy_read");
753 if (ec == lib::asio::error::operation_aborted ||
761 m_proxy_data->timer->cancel();
765 "asio handle_proxy_read error: "+ec.message());
770 "assertion failed: !m_proxy_data in asio::connection::handle_proxy_read");
775 std::istream input(&m_proxy_data->read_buf);
777 m_proxy_data->res.consume(input);
779 if (!m_proxy_data->res.headers_ready()) {
793 s <<
"Proxy connection error: "
794 << m_proxy_data->res.get_status_code()
796 << m_proxy_data->res.get_status_msg()
812 m_proxy_data.reset();
825 s <<
"asio async_read_at_least: " << num_bytes;
839 if (config::enable_multithreading) {
840 lib::asio::async_read(
841 socket_con_type::get_socket(),
842 lib::asio::buffer(
buf,
len),
843 lib::asio::transfer_at_least(num_bytes),
845 m_read_handler_allocator,
849 lib::placeholders::_1, lib::placeholders::_2
854 lib::asio::async_read(
855 socket_con_type::get_socket(),
856 lib::asio::buffer(
buf,
len),
857 lib::asio::transfer_at_least(num_bytes),
859 m_read_handler_allocator,
863 lib::placeholders::_1, lib::placeholders::_2
872 size_t bytes_transferred)
878 if (ec == lib::asio::error::eof) {
883 tec = socket_con_type::translate_ec(ec);
896 handler(tec,bytes_transferred);
901 "handle_async_read called with null read handler");
907 m_bufs.push_back(lib::asio::buffer(
buf,
len));
909 if (config::enable_multithreading) {
910 lib::asio::async_write(
911 socket_con_type::get_socket(),
914 m_write_handler_allocator,
918 lib::placeholders::_1, lib::placeholders::_2
923 lib::asio::async_write(
924 socket_con_type::get_socket(),
927 m_write_handler_allocator,
931 lib::placeholders::_1, lib::placeholders::_2
940 std::vector<buffer>::const_iterator it;
942 for (it = bufs.begin(); it != bufs.end(); ++it) {
943 m_bufs.push_back(lib::asio::buffer((*it).buf,(*it).len));
946 if (config::enable_multithreading) {
947 lib::asio::async_write(
948 socket_con_type::get_socket(),
951 m_write_handler_allocator,
955 lib::placeholders::_1, lib::placeholders::_2
960 lib::asio::async_write(
961 socket_con_type::get_socket(),
964 m_write_handler_allocator,
968 lib::placeholders::_1, lib::placeholders::_2
993 "handle_async_write called with null write handler");
1005 m_connection_hdl = hdl;
1006 socket_con_type::set_handle(hdl);
1014 if (config::enable_multithreading) {
1015 m_io_service->post(m_strand->wrap(handler));
1017 m_io_service->post(handler);
1019 return lib::error_code();
1023 if (config::enable_multithreading) {
1024 m_io_service->post(m_strand->wrap(handler));
1026 m_io_service->post(handler);
1028 return lib::error_code();
1043 config::timeout_socket_shutdown,
1049 lib::placeholders::_1
1053 socket_con_type::async_shutdown(
1059 lib::placeholders::_1
1071 lib::error_code
const & ec)
1073 lib::error_code ret_ec;
1078 "asio socket shutdown timer cancelled");
1089 "Asio transport socket shutdown timed out");
1095 callback, lib::asio::error_code
const & ec)
1097 if (ec == lib::asio::error::operation_aborted ||
1104 shutdown_timer->cancel();
1106 lib::error_code tec;
1108 if (ec == lib::asio::error::not_connected) {
1116 tec = socket_con_type::translate_ec(ec);
1134 "asio con handle_async_shutdown");
1142 lib::asio::error_code cec = socket_con_type::cancel_socket();
1144 if (cec == lib::asio::error::operation_not_supported) {
1155 template <
typename error_type>
1156 void log_err(
log::level l,
const char * msg,
const error_type & ec) {
1157 std::stringstream
s;
1158 s << msg <<
" error: " << ec <<
" (" << ec.message() <<
")";
1159 m_elog.write(
l,
s.str());
1163 const bool m_is_server;
1168 proxy_data() : timeout_proxy(
config::timeout_proxy) {}
1172 std::string write_buf;
1173 lib::asio::streambuf read_buf;
1178 std::string m_proxy;
1179 lib::shared_ptr<proxy_data> m_proxy_data;
1186 std::vector<lib::asio::const_buffer> m_bufs;
1189 lib::asio::error_code m_tec;
1195 handler_allocator m_read_handler_allocator;
1196 handler_allocator m_write_handler_allocator;
Asio based connection transport component.
void set_proxy_timeout(long duration)
Set the proxy timeout duration (exception)
void set_tcp_post_init_handler(tcp_init_handler h)
Sets the tcp post init handler.
void set_proxy_basic_auth(std::string const &username, std::string const &password)
Set the basic auth credentials to use (exception)
void handle_async_read(read_handler handler, lib::asio::error_code const &ec, size_t bytes_transferred)
void set_proxy_timeout(long duration, lib::error_code &ec)
Set the proxy timeout duration (exception free)
strand_ptr get_strand()
Get a pointer to this connection's strand.
void async_read_at_least(size_t num_bytes, char *buf, size_t len, read_handler handler)
read at least num_bytes bytes into buf and then call handler.
lib::error_code proxy_init(std::string const &authority)
initialize the proxy buffers and http parsers
void handle_pre_init(init_handler callback, lib::error_code const &ec)
lib::error_code interrupt(interrupt_handler handler)
Trigger the on_interrupt handler.
void proxy_read(init_handler callback)
lib::shared_ptr< type > ptr
Type of a shared pointer to this connection transport component.
void proxy_write(init_handler callback)
void handle_proxy_write(init_handler callback, lib::asio::error_code const &ec)
void handle_proxy_timeout(init_handler callback, lib::error_code const &ec)
void handle_async_write(write_handler handler, lib::asio::error_code const &ec, size_t)
Async write callback.
void handle_timer(timer_ptr, timer_handler callback, lib::asio::error_code const &ec)
Timer callback.
lib::error_code init_asio(io_service_ptr io_service)
Finish constructing the transport.
lib::error_code dispatch(dispatch_handler handler)
config::socket_type::socket_con_type socket_con_type
Type of the socket connection component.
void handle_post_init(timer_ptr post_timer, init_handler callback, lib::error_code const &ec)
Post init timeout callback.
lib::shared_ptr< lib::asio::io_service::strand > strand_ptr
Type of a pointer to the Asio io_service::strand being used.
void async_shutdown(shutdown_handler callback)
close and clean up the underlying socket
config::alog_type alog_type
Type of this transport's access logging policy.
lib::asio::error_code get_transport_ec() const
Get the internal transport error code for a closed/failed connection.
lib::shared_ptr< lib::asio::steady_timer > timer_ptr
Type of a pointer to the Asio timer class.
void set_proxy(std::string const &uri)
Set the proxy to connect through (exception)
void handle_post_init_timeout(timer_ptr, init_handler callback, lib::error_code const &ec)
Post init timeout callback.
void handle_async_shutdown_timeout(timer_ptr, init_handler callback, lib::error_code const &ec)
Async shutdown timeout handler.
void set_proxy(std::string const &uri, lib::error_code &ec)
Set the proxy to connect through (exception free)
void set_proxy_basic_auth(std::string const &username, std::string const &password, lib::error_code &ec)
Set the basic auth credentials to use (exception free)
void async_write(const char *buf, size_t len, write_handler handler)
Initiate a potentially asyncronous write of the given buffer.
void async_write(std::vector< buffer > const &bufs, write_handler handler)
Initiate a potentially asyncronous write of the given buffers.
config::request_type request_type
connection< config > type
Type of this connection transport component.
request_type::ptr request_ptr
response_type::ptr response_ptr
lib::asio::io_service * io_service_ptr
Type of a pointer to the Asio io_service being used.
timer_ptr set_timer(long duration, timer_handler callback)
Call back a function after a period of time.
void set_tcp_init_handler(tcp_init_handler h)
Sets the tcp pre init handler (deprecated)
void handle_proxy_read(init_handler callback, lib::asio::error_code const &ec, size_t)
Proxy read callback.
void set_uri(uri_ptr u)
Set uri hook.
std::string get_remote_endpoint() const
Get the remote endpoint address.
ptr get_shared()
Get a shared pointer to this component.
void cancel_socket_checked()
Cancel the underlying socket and log any errors.
void set_handle(connection_hdl hdl)
Set Connection Handle.
void set_tcp_pre_init_handler(tcp_init_handler h)
Sets the tcp pre init handler.
void post_init(init_handler callback)
config::response_type response_type
void handle_async_shutdown(timer_ptr shutdown_timer, shutdown_handler callback, lib::asio::error_code const &ec)
config::elog_type elog_type
Type of this transport's error logging policy.
std::string const & get_proxy() const
void init(init_handler callback)
Initialize transport for reading.
socket_con_type::ptr socket_con_ptr
Type of a shared pointer to the socket connection component.
connection_hdl get_handle() const
Get the connection handle.
connection(bool is_server, alog_type &alog, elog_type &elog)
Asio based endpoint transport component.
Asio based endpoint transport component.
@ invalid_state
The connection was in the wrong state for this operation.
lib::error_code make_error_code(error::value e)
boost::posix_time::time_duration milliseconds(long duration)
uint32_t level
Type of a channel package.
@ proxy_failed
The connection to the requested proxy server failed.
lib::function< void(connection_hdl)> tcp_init_handler
custom_alloc_handler< Handler > make_custom_alloc_handler(handler_allocator &a, Handler h)
@ pass_through
underlying transport pass through
@ operation_aborted
Operation aborted.
@ tls_error
Other TLS error.
@ tls_short_read
TLS short read.
lib::function< void(lib::error_code const &, size_t)> read_handler
The type and signature of the callback passed to the read method.
lib::function< void()> dispatch_handler
The type and signature of the callback passed to the dispatch method.
lib::function< void()> interrupt_handler
The type and signature of the callback passed to the interrupt method.
lib::function< void(lib::error_code const &)> timer_handler
The type and signature of the callback passed to the read method.
lib::function< void(lib::error_code const &)> write_handler
The type and signature of the callback passed to the write method.
lib::function< void(lib::error_code const &)> init_handler
The type and signature of the callback passed to the init hook.
lib::function< void(lib::error_code const &)> shutdown_handler
The type and signature of the callback passed to the shutdown method.
Namespace for the WebSocket++ project.
lib::weak_ptr< void > connection_hdl
A handle to uniquely identify a connection.
lib::shared_ptr< uri > uri_ptr
Pointer to a URI.
std::string base64_encode(unsigned char const *input, size_t len)
Encode a char buffer into a base64 string.
static level const devel
Development messages (warning: very chatty)
static level const devel
Low level debugging information (warning: very chatty)
static level const library