splits transport init into pre-and post proxy steps

This commit is contained in:
Peter Thorson
2013-05-05 16:14:38 -05:00
parent cb40f81978
commit adb0eedc24
5 changed files with 142 additions and 14 deletions

View File

@@ -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);
}
}

View File

@@ -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());

View File

@@ -57,6 +57,8 @@
/// Connection
/// TODO
/// pre_init(init_handler);
/// post_init(init_handler);
namespace websocketpp {
namespace transport {

View File

@@ -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

View File

@@ -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
/**