mirror of
https://github.com/XRPLF/rippled.git
synced 2026-04-29 15:37:57 +00:00
adjust transport async_accept and async_connect to use connection_ptr instead of connection_hdl
prevents a newly created connection_ptr from being destroyed immediately after accepting or connecting.
This commit is contained in:
@@ -156,14 +156,12 @@ struct mock_endpoint : public websocketpp::transport::asio::endpoint<config> {
|
||||
&mock_endpoint::handle_connect,
|
||||
this,
|
||||
m_con,
|
||||
websocketpp::lib::placeholders::_1,
|
||||
websocketpp::lib::placeholders::_2
|
||||
websocketpp::lib::placeholders::_1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void handle_connect(connection_ptr con, websocketpp::connection_hdl,
|
||||
const websocketpp::lib::error_code & ec)
|
||||
void handle_connect(connection_ptr con, websocketpp::lib::error_code const & ec)
|
||||
{
|
||||
BOOST_CHECK( !ec );
|
||||
con->start();
|
||||
|
||||
@@ -66,8 +66,7 @@ public:
|
||||
|
||||
explicit client() : endpoint_type(false)
|
||||
{
|
||||
endpoint_type::m_alog.write(log::alevel::devel,
|
||||
"client constructor");
|
||||
endpoint_type::m_alog.write(log::alevel::devel, "client constructor");
|
||||
}
|
||||
|
||||
/// Get a new connection
|
||||
@@ -77,15 +76,17 @@ public:
|
||||
* applying connection specific settings before performing the opening
|
||||
* handshake.
|
||||
*
|
||||
* @param [in] location URI to open the connection to as a uri_ptr
|
||||
* @param [out] ec An status code indicating failure reasons, if any
|
||||
*
|
||||
* @return A connection_ptr to the new connection
|
||||
*/
|
||||
connection_ptr get_connection(uri_ptr location, lib::error_code &ec) {
|
||||
connection_ptr get_connection(uri_ptr location, lib::error_code & ec) {
|
||||
if (location->get_secure() && !transport_type::is_secure()) {
|
||||
ec = error::make_error_code(error::endpoint_not_secure);
|
||||
return connection_ptr();
|
||||
}
|
||||
|
||||
// create connection
|
||||
connection_ptr con = endpoint_type::create_connection();
|
||||
|
||||
if (!con) {
|
||||
@@ -95,7 +96,6 @@ public:
|
||||
|
||||
con->set_uri(location);
|
||||
|
||||
// Success
|
||||
ec = lib::error_code();
|
||||
return con;
|
||||
}
|
||||
@@ -106,10 +106,12 @@ public:
|
||||
* suitable for passing to connect(connection_ptr). This overload allows
|
||||
* default construction of the uri_ptr from a standard string.
|
||||
*
|
||||
* @param [in] u URI to open the connection to as a string
|
||||
* @param [out] ec An status code indicating failure reasons, if any
|
||||
*
|
||||
* @return A connection_ptr to the new connection
|
||||
*/
|
||||
connection_ptr get_connection(const std::string& u, lib::error_code &ec) {
|
||||
// parse uri
|
||||
connection_ptr get_connection(std::string const & u, lib::error_code & ec) {
|
||||
uri_ptr location(new uri(u));
|
||||
|
||||
if (!location->get_valid()) {
|
||||
@@ -137,35 +139,17 @@ public:
|
||||
lib::bind(
|
||||
&type::handle_connect,
|
||||
this,
|
||||
lib::placeholders::_1,
|
||||
lib::placeholders::_2
|
||||
con,
|
||||
lib::placeholders::_1
|
||||
)
|
||||
);
|
||||
|
||||
return con;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// connect(...)
|
||||
private:
|
||||
// handle_connect
|
||||
void handle_connect(connection_hdl hdl, const lib::error_code & ec) {
|
||||
lib::error_code hdl_ec;
|
||||
connection_ptr con = endpoint_type::get_con_from_hdl(hdl,hdl_ec);
|
||||
|
||||
if (hdl_ec == error::bad_connection) {
|
||||
endpoint_type::m_elog.write(log::elevel::fatal,
|
||||
"handle_connect got an invalid handle back");
|
||||
} else if (hdl_ec) {
|
||||
// There was some other unknown error attempting to convert the hdl
|
||||
// to a connection.
|
||||
endpoint_type::m_elog.write(log::elevel::fatal,
|
||||
"handle_connect error in get_con_from_hdl: "+hdl_ec.message());
|
||||
//con->terminate();
|
||||
} else if (ec) {
|
||||
// TODO
|
||||
// Set connection's failure reasons
|
||||
void handle_connect(connection_ptr con, lib::error_code const & ec) {
|
||||
if (ec) {
|
||||
con->terminate(ec);
|
||||
|
||||
endpoint_type::m_elog.write(log::elevel::rerror,
|
||||
|
||||
@@ -90,37 +90,20 @@ public:
|
||||
lib::bind(
|
||||
&type::handle_accept,
|
||||
this,
|
||||
lib::placeholders::_1,
|
||||
lib::placeholders::_2
|
||||
con,
|
||||
lib::placeholders::_1
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void handle_accept(connection_hdl hdl, const lib::error_code& ec) {
|
||||
lib::error_code hdl_ec;
|
||||
connection_ptr con = endpoint_type::get_con_from_hdl(hdl,hdl_ec);
|
||||
void handle_accept(connection_ptr con, const lib::error_code& ec) {
|
||||
if (ec) {
|
||||
con->terminate(ec);
|
||||
|
||||
if (hdl_ec == error::bad_connection) {
|
||||
// The connection we were trying to connect went out of scope
|
||||
// This really shouldn't happen
|
||||
endpoint_type::m_elog.write(log::elevel::fatal,
|
||||
"handle_accept got an invalid handle back");
|
||||
//con->terminate();
|
||||
} else if (hdl_ec) {
|
||||
// There was some other unknown error attempting to convert the hdl
|
||||
// to a connection.
|
||||
endpoint_type::m_elog.write(log::elevel::fatal,
|
||||
"handle_accept error in get_con_from_hdl: "+hdl_ec.message());
|
||||
//con->terminate();
|
||||
endpoint_type::m_elog.write(log::elevel::rerror,
|
||||
"handle_accept error: "+ec.message());
|
||||
} else {
|
||||
if (ec) {
|
||||
con->terminate(ec);
|
||||
|
||||
endpoint_type::m_elog.write(log::elevel::rerror,
|
||||
"handle_accept error: "+ec.message());
|
||||
} else {
|
||||
con->start();
|
||||
}
|
||||
con->start();
|
||||
}
|
||||
|
||||
// TODO: are there cases where we should terminate this loop?
|
||||
|
||||
@@ -45,6 +45,11 @@ namespace transport {
|
||||
*/
|
||||
namespace asio {
|
||||
|
||||
// Forward declaration of class endpoint so that it can be friended/referenced
|
||||
// before being included.
|
||||
template <typename config>
|
||||
class endpoint;
|
||||
|
||||
typedef lib::function<void(boost::system::error_code const &)>
|
||||
socket_shutdown_handler;
|
||||
|
||||
|
||||
@@ -84,6 +84,11 @@ public:
|
||||
/// Type of a pointer to the ASIO timer class
|
||||
typedef lib::shared_ptr<boost::asio::deadline_timer> timer_ptr;
|
||||
|
||||
// connection is friends with its associated endpoint to allow the endpoint
|
||||
// to call private/protected utility methods that we don't want to expose
|
||||
// to the public api.
|
||||
friend class endpoint<config>;
|
||||
|
||||
// generate and manage our own io_service
|
||||
explicit connection(bool is_server, alog_type& alog, elog_type& elog)
|
||||
: m_is_server(is_server)
|
||||
@@ -102,29 +107,13 @@ public:
|
||||
return socket_con_type::is_secure();
|
||||
}
|
||||
|
||||
/// Finish constructing the transport
|
||||
/// Sets the tcp init handler
|
||||
/**
|
||||
* init_asio is called once immediately after construction to initialize
|
||||
* boost::asio components to the io_service
|
||||
* The tcp init handler is called after the tcp connection has been
|
||||
* established.
|
||||
*
|
||||
* TODO: this method is not protected because the endpoint needs to call it.
|
||||
* need to figure out if there is a way to friend the endpoint safely across
|
||||
* different compilers.
|
||||
*
|
||||
* @param io_service A pointer to the io_service to register with this
|
||||
* connection
|
||||
*
|
||||
* @return Status code for the success or failure of the initialization
|
||||
* @param h The handler to call on tcp init.
|
||||
*/
|
||||
lib::error_code init_asio (io_service_ptr io_service) {
|
||||
// do we need to store or use the io_service at this level?
|
||||
m_io_service = io_service;
|
||||
|
||||
//m_strand.reset(new boost::asio::strand(*io_service));
|
||||
|
||||
return socket_con_type::init_asio(io_service, m_is_server);
|
||||
}
|
||||
|
||||
void set_tcp_init_handler(tcp_init_handler h) {
|
||||
m_tcp_init_handler = h;
|
||||
}
|
||||
@@ -251,26 +240,6 @@ public:
|
||||
return m_connection_hdl;
|
||||
}
|
||||
|
||||
/// initialize the proxy buffers and http parsers
|
||||
/**
|
||||
*
|
||||
* @param authority The address of the server we want the proxy to tunnel to
|
||||
* in the format of a URI authority (host:port)
|
||||
*/
|
||||
lib::error_code proxy_init(const std::string & authority) {
|
||||
if (!m_proxy_data) {
|
||||
return websocketpp::error::make_error_code(
|
||||
websocketpp::error::invalid_state);
|
||||
}
|
||||
m_proxy_data->req.set_version("HTTP/1.1");
|
||||
m_proxy_data->req.set_method("CONNECT");
|
||||
|
||||
m_proxy_data->req.set_uri(authority);
|
||||
m_proxy_data->req.replace_header("Host",authority);
|
||||
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
/// Call back a function after a period of time.
|
||||
/**
|
||||
* Sets a timer that calls back a function after the specified period of
|
||||
@@ -311,10 +280,10 @@ public:
|
||||
* The timer pointer is included to ensure the timer isn't destroyed until
|
||||
* after it has expired.
|
||||
*
|
||||
* TODO: candidate for protected status
|
||||
*
|
||||
* @param t Pointer to the timer in question
|
||||
*
|
||||
* @param callback The function to call back
|
||||
*
|
||||
* @param ec The status code
|
||||
*/
|
||||
void handle_timer(timer_ptr t, timer_handler callback, const
|
||||
@@ -367,6 +336,47 @@ protected:
|
||||
);
|
||||
}
|
||||
|
||||
/// initialize the proxy buffers and http parsers
|
||||
/**
|
||||
*
|
||||
* @param authority The address of the server we want the proxy to tunnel to
|
||||
* in the format of a URI authority (host:port)
|
||||
*
|
||||
* @return Status code indicating what errors occurred, if any
|
||||
*/
|
||||
lib::error_code proxy_init(std::string const & authority) {
|
||||
if (!m_proxy_data) {
|
||||
return websocketpp::error::make_error_code(
|
||||
websocketpp::error::invalid_state);
|
||||
}
|
||||
m_proxy_data->req.set_version("HTTP/1.1");
|
||||
m_proxy_data->req.set_method("CONNECT");
|
||||
|
||||
m_proxy_data->req.set_uri(authority);
|
||||
m_proxy_data->req.replace_header("Host",authority);
|
||||
|
||||
return lib::error_code();
|
||||
}
|
||||
|
||||
/// Finish constructing the transport
|
||||
/**
|
||||
* init_asio is called once immediately after construction to initialize
|
||||
* boost::asio components to the io_service
|
||||
*
|
||||
* @param io_service A pointer to the io_service to register with this
|
||||
* connection
|
||||
*
|
||||
* @return Status code for the success or failure of the initialization
|
||||
*/
|
||||
lib::error_code init_asio (io_service_ptr io_service) {
|
||||
// do we need to store or use the io_service at this level?
|
||||
m_io_service = io_service;
|
||||
|
||||
//m_strand.reset(new boost::asio::strand(*io_service));
|
||||
|
||||
return socket_con_type::init_asio(io_service, m_is_server);
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
@@ -577,7 +577,6 @@ public:
|
||||
lib::bind(
|
||||
&type::handle_accept,
|
||||
this,
|
||||
tcon->get_handle(),
|
||||
callback,
|
||||
lib::placeholders::_1
|
||||
)
|
||||
@@ -612,18 +611,19 @@ protected:
|
||||
m_elog = e;
|
||||
}
|
||||
|
||||
void handle_accept(connection_hdl hdl, accept_handler callback,
|
||||
const boost::system::error_code& error)
|
||||
void handle_accept(accept_handler callback, boost::system::error_code const
|
||||
& boost_ec)
|
||||
{
|
||||
if (error) {
|
||||
//con->terminate();
|
||||
// TODO: Better translation of errors at this point
|
||||
callback(hdl,make_error_code(error::pass_through));
|
||||
return;
|
||||
lib::error_code ret_ec;
|
||||
|
||||
m_alog->write(log::alevel::devel, "asio::handle_accept");
|
||||
|
||||
if (boost_ec) {
|
||||
log_err(log::elevel::devel,"asio handle_accept",boost_ec);
|
||||
ret_ec = make_error_code(error::pass_through);
|
||||
}
|
||||
|
||||
//con->start();
|
||||
callback(hdl,lib::error_code());
|
||||
callback(ret_ec);
|
||||
}
|
||||
|
||||
/// Initiate a new connection
|
||||
@@ -649,13 +649,13 @@ protected:
|
||||
uri_ptr pu(new uri(proxy));
|
||||
|
||||
if (!pu->get_valid()) {
|
||||
cb(tcon->get_handle(),make_error_code(error::proxy_invalid));
|
||||
cb(make_error_code(error::proxy_invalid));
|
||||
return;
|
||||
}
|
||||
|
||||
ec = tcon->proxy_init(u->get_authority());
|
||||
if (ec) {
|
||||
cb(tcon->get_handle(),ec);
|
||||
cb(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -677,7 +677,6 @@ protected:
|
||||
lib::bind(
|
||||
&type::handle_resolve_timeout,
|
||||
this,
|
||||
tcon,
|
||||
dns_timer,
|
||||
cb,
|
||||
lib::placeholders::_1
|
||||
@@ -698,8 +697,8 @@ protected:
|
||||
);
|
||||
}
|
||||
|
||||
void handle_resolve_timeout(transport_con_ptr tcon, timer_ptr dns_timer,
|
||||
connect_handler callback, const lib::error_code & ec)
|
||||
void handle_resolve_timeout(timer_ptr dns_timer, connect_handler callback,
|
||||
lib::error_code const & ec)
|
||||
{
|
||||
lib::error_code ret_ec;
|
||||
|
||||
@@ -718,11 +717,11 @@ protected:
|
||||
|
||||
m_alog->write(log::alevel::devel,"DNS resolution timed out");
|
||||
m_resolver->cancel();
|
||||
callback(tcon->get_handle(),ret_ec);
|
||||
callback(ret_ec);
|
||||
}
|
||||
|
||||
void handle_resolve(transport_con_ptr tcon, timer_ptr dns_timer,
|
||||
connect_handler callback, const boost::system::error_code& ec,
|
||||
connect_handler callback, boost::system::error_code const & ec,
|
||||
boost::asio::ip::tcp::resolver::iterator iterator)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted ||
|
||||
@@ -736,7 +735,7 @@ protected:
|
||||
|
||||
if (ec) {
|
||||
log_err(log::elevel::info,"asio async_resolve",ec);
|
||||
callback(tcon->get_handle(),make_error_code(error::pass_through));
|
||||
callback(make_error_code(error::pass_through));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -759,7 +758,7 @@ protected:
|
||||
con_timer = set_timer(
|
||||
config::timeout_connect,
|
||||
lib::bind(
|
||||
&type::handle_resolve_timeout,
|
||||
&type::handle_connect_timeout,
|
||||
this,
|
||||
tcon,
|
||||
con_timer,
|
||||
@@ -783,7 +782,7 @@ protected:
|
||||
}
|
||||
|
||||
void handle_connect_timeout(transport_con_ptr tcon, timer_ptr con_timer,
|
||||
connect_handler callback, const lib::error_code & ec)
|
||||
connect_handler callback, lib::error_code const & ec)
|
||||
{
|
||||
lib::error_code ret_ec;
|
||||
|
||||
@@ -802,11 +801,11 @@ protected:
|
||||
|
||||
m_alog->write(log::alevel::devel,"TCP connect timed out");
|
||||
tcon->cancel_socket();
|
||||
callback(tcon->get_handle(),ret_ec);
|
||||
callback(ret_ec);
|
||||
}
|
||||
|
||||
void handle_connect(transport_con_ptr tcon, timer_ptr con_timer,
|
||||
connect_handler callback, const boost::system::error_code& ec)
|
||||
connect_handler callback, boost::system::error_code const & ec)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted ||
|
||||
con_timer->expires_from_now().is_negative())
|
||||
@@ -819,7 +818,7 @@ protected:
|
||||
|
||||
if (ec) {
|
||||
log_err(log::elevel::info,"asio async_connect",ec);
|
||||
callback(tcon->get_handle(),make_error_code(error::pass_through));
|
||||
callback(make_error_code(error::pass_through));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -828,7 +827,7 @@ protected:
|
||||
"Async connect to "+tcon->get_remote_endpoint()+" successful.");
|
||||
}
|
||||
|
||||
callback(tcon->get_handle(),lib::error_code());
|
||||
callback(lib::error_code());
|
||||
}
|
||||
|
||||
bool is_listening() const {
|
||||
|
||||
@@ -71,12 +71,10 @@ namespace websocketpp {
|
||||
namespace transport {
|
||||
|
||||
/// The type and signature of the callback passed to the accept method
|
||||
typedef lib::function<void(connection_hdl, lib::error_code const &)>
|
||||
accept_handler;
|
||||
typedef lib::function<void(lib::error_code const &)> accept_handler;
|
||||
|
||||
/// The type and signature of the callback passed to the connect method
|
||||
typedef lib::function<void(connection_hdl, lib::error_code const &)>
|
||||
connect_handler;
|
||||
typedef lib::function<void(lib::error_code const &)> connect_handler;
|
||||
|
||||
} // namespace transport
|
||||
} // namespace websocketpp
|
||||
|
||||
@@ -141,7 +141,7 @@ protected:
|
||||
* @param cb The function to call back with the results when complete.
|
||||
*/
|
||||
void async_connect(transport_con_ptr tcon, uri_ptr u, connect_handler cb) {
|
||||
cb(tcon->get_handle(),lib::error_code());
|
||||
cb(lib::error_code());
|
||||
}
|
||||
|
||||
/// Initialize a connection
|
||||
|
||||
Reference in New Issue
Block a user