diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index df64c6c952..9bf093a9fa 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -191,13 +191,27 @@ protected: /** * init_asio is called once immediately after construction to initialize * boost::asio components to the io_service + * + * The transport initialization sequence consists of the following steps: + * - Pre-init: the underlying socket is initialized to the point where + * bytes may be written. No bytes are actually written in this stage + * - Proxy negotiation: if a proxy is set, a request is made to it to start + * a tunnel to the final destination. This stage ends when the proxy is + * ready to forward the + * next byte to the remote endpoint. + * - Post-init: Perform any i/o with the remote endpoint, such as setting up + * tunnels for encryption. This stage ends when the connection is ready to + * read or write the WebSocket handshakes. At this point the original + * callback function is called. */ void init(init_handler callback) { - m_alog.write(log::alevel::devel,"asio connection init"); + if (m_alog.static_test(log::alevel::devel)) { + m_alog.write(log::alevel::devel,"asio connection init"); + } - socket_con_type::init( + socket_con_type::pre_init( lib::bind( - &type::handle_init, + &type::handle_pre_init, this, callback, lib::placeholders::_1 @@ -205,7 +219,11 @@ protected: ); } - void handle_init(init_handler callback, const lib::error_code& ec) { + void handle_pre_init(init_handler callback, const lib::error_code& ec) { + if (m_alog.static_test(log::alevel::devel)) { + m_alog.write(log::alevel::devel,"asio connection handle pre_init"); + } + if (m_tcp_init_handler) { m_tcp_init_handler(m_connection_hdl); } @@ -214,16 +232,42 @@ protected: callback(ec); } - // If no error, and we are an insecure connection with a proxy set - // issue a proxy connect. + // If we have a proxy set issue a proxy connect, otherwise skip to post_init if (!m_proxy.empty()) { proxy_write(callback); } else { - callback(ec); + post_init(callback); } } + void post_init(init_handler callback) { + if (m_alog.static_test(log::alevel::devel)) { + m_alog.write(log::alevel::devel,"asio connection post_init"); + } + + socket_con_type::post_init( + lib::bind( + &type::handle_post_init, + this, + callback, + lib::placeholders::_1 + ) + ); + } + + void handle_post_init(init_handler callback, const lib::error_code& ec) { + if (m_alog.static_test(log::alevel::devel)) { + m_alog.write(log::alevel::devel,"asio connection handle_post_init"); + } + + callback(ec); + } + void proxy_write(init_handler callback) { + if (m_alog.static_test(log::alevel::devel)) { + m_alog.write(log::alevel::devel,"asio connection proxy_write"); + } + if (!m_proxy_data) { m_elog.write(log::elevel::library, "assertion failed: !m_proxy_data in asio::connection::proxy_write"); @@ -253,6 +297,10 @@ protected: void handle_proxy_write(init_handler callback, const boost::system::error_code& ec) { + if (m_alog.static_test(log::alevel::devel)) { + m_alog.write(log::alevel::devel,"asio connection handle_proxy_write"); + } + m_bufs.clear(); if (ec) { @@ -265,6 +313,10 @@ protected: } void proxy_read(init_handler callback) { + if (m_alog.static_test(log::alevel::devel)) { + m_alog.write(log::alevel::devel,"asio connection proxy_read"); + } + if (!m_proxy_data) { m_elog.write(log::elevel::library, "assertion failed: !m_proxy_data in asio::connection::proxy_read"); @@ -289,6 +341,10 @@ protected: void handle_proxy_read(init_handler callback, const boost::system::error_code& ec, size_t bytes_transferred) { + if (m_alog.static_test(log::alevel::devel)) { + m_alog.write(log::alevel::devel,"asio connection handle_proxy_read"); + } + if (ec) { m_elog.write(log::elevel::info, "asio handle_proxy_read error: "+ec.message()); @@ -340,8 +396,8 @@ protected: // anymore m_proxy_data.reset(); - // call the original init handler back. - callback(lib::error_code()); + // Continue with post proxy initialization + post_init(callback); } } diff --git a/websocketpp/transport/asio/endpoint.hpp b/websocketpp/transport/asio/endpoint.hpp index 89c0aedeca..5a629dca39 100644 --- a/websocketpp/transport/asio/endpoint.hpp +++ b/websocketpp/transport/asio/endpoint.hpp @@ -433,7 +433,7 @@ protected: boost::asio::ip::tcp::resolver::iterator it, end; for (it = iterator; it != end; ++it) { - s << (*it).endpoint() << "\n"; + s << (*it).endpoint() << " "; } m_alog->write(log::alevel::devel,s.str()); diff --git a/websocketpp/transport/asio/security/base.hpp b/websocketpp/transport/asio/security/base.hpp index bf73db7e51..7c71ce3059 100644 --- a/websocketpp/transport/asio/security/base.hpp +++ b/websocketpp/transport/asio/security/base.hpp @@ -57,6 +57,8 @@ /// Connection /// TODO +/// pre_init(init_handler); +/// post_init(init_handler); namespace websocketpp { namespace transport { diff --git a/websocketpp/transport/asio/security/none.hpp b/websocketpp/transport/asio/security/none.hpp index a70769c23f..373bdfb89c 100644 --- a/websocketpp/transport/asio/security/none.hpp +++ b/websocketpp/transport/asio/security/none.hpp @@ -158,8 +158,16 @@ protected: return lib::error_code(); } - /// Initialize security policy for reading - void init(init_handler callback) { + /// Pre-initialize security policy + /** + * Called by the transport after a new connection is created to initialize + * the socket component of the connection. This method is not allowed to + * write any bytes to the wire. This initialization happens before any + * proxies or other intermediate wrappers are negotiated. + * + * @param callback Handler to call back with completion information + */ + void pre_init(init_handler callback) { if (m_state != READY) { callback(socket::make_error(socket::error::invalid_state)); return; @@ -174,6 +182,18 @@ protected: callback(lib::error_code()); } + /// Post-initialize security policy + /** + * Called by the transport after all intermediate proxies have been + * negotiated. This gives the security policy the chance to talk with the + * real remote endpoint for a bit before the websocket handshake. + * + * @param callback Handler to call back with completion information + */ + void post_init(init_handler callback) { + callback(lib::error_code()); + } + /// Sets the connection handle /** * The connection handle is passed to any handlers to identify the diff --git a/websocketpp/transport/asio/security/tls.hpp b/websocketpp/transport/asio/security/tls.hpp index 8c5e365330..b0d3ca0b4a 100644 --- a/websocketpp/transport/asio/security/tls.hpp +++ b/websocketpp/transport/asio/security/tls.hpp @@ -197,8 +197,58 @@ protected: return lib::error_code(); } + /// Pre-initialize security policy + /** + * Called by the transport after a new connection is created to initialize + * the socket component of the connection. This method is not allowed to + * write any bytes to the wire. This initialization happens before any + * proxies or other intermediate wrappers are negotiated. + * + * @param callback Handler to call back with completion information + */ + void pre_init(init_handler callback) { + if (m_socket_init_handler) { + m_socket_init_handler(m_hdl,get_socket()); + } + + callback(lib::error_code()); + } + + /// Post-initialize security policy + /** + * Called by the transport after all intermediate proxies have been + * negotiated. This gives the security policy the chance to talk with the + * real remote endpoint for a bit before the websocket handshake. + * + * @param callback Handler to call back with completion information + */ + void post_init(init_handler callback) { + // register timeout + m_timer->expires_from_now(boost::posix_time::milliseconds(5000)); + // TEMP + m_timer->async_wait( + lib::bind( + &type::handle_timeout, + this, + callback, + lib::placeholders::_1 + ) + ); + + // TLS handshake + m_socket->async_handshake( + get_handshake_type(), + lib::bind( + &type::handle_init, + this, + callback, + lib::placeholders::_1 + ) + ); + } + /// Initialize security policy for reading - void init(init_handler callback) { + /*void init(init_handler callback) { if (m_socket_init_handler) { m_socket_init_handler(m_hdl,get_socket()); } @@ -225,7 +275,7 @@ protected: lib::placeholders::_1 ) ); - } + }*/ /// Sets the connection handle /**