@@ -935,7 +935,7 @@ namespace net_utils
935935 boost::uuids::random_generator ()(),
936936 *real_remote,
937937 is_income,
938- connection_basic::m_ssl_support == ssl_support_t ::e_ssl_support_enabled
938+ connection_basic::m_ssl_support
939939 );
940940 m_host = real_remote->host_str ();
941941 try { host_count (1 ); } catch (...) { /* ignore */ }
@@ -1628,7 +1628,7 @@ namespace net_utils
16281628 }
16291629 // ---------------------------------------------------------------------------------
16301630 template <class t_protocol_handler >
1631- typename boosted_tcp_server<t_protocol_handler>::try_connect_result_t boosted_tcp_server<t_protocol_handler>::try_connect(connection_ptr new_connection_l, const std::string& adr, const std::string& port, boost::asio::ip::tcp::socket &sock_, const boost::asio::ip::tcp::endpoint &remote_endpoint, const std::string &bind_ip, uint32_t conn_timeout, epee::net_utils::ssl_support_t ssl_support )
1631+ typename boosted_tcp_server<t_protocol_handler>::try_connect_result_t boosted_tcp_server<t_protocol_handler>::try_connect(connection_ptr new_connection_l, const std::string& adr, const std::string& port, boost::asio::ip::tcp::socket &sock_, const boost::asio::ip::tcp::endpoint &remote_endpoint, const std::string &bind_ip, uint32_t conn_timeout, epee::net_utils::ssl_options_t & ssl_options )
16321632 {
16331633 TRY_ENTRY ();
16341634
@@ -1704,7 +1704,7 @@ namespace net_utils
17041704 {
17051705 // Handshake
17061706 MDEBUG (" Handshaking SSL..." );
1707- if (!new_connection_l->handshake (boost::asio::ssl::stream_base::client ))
1707+ if (!new_connection_l->client_handshake (ssl_options ))
17081708 {
17091709 if (ssl_support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect)
17101710 {
@@ -1718,6 +1718,7 @@ namespace net_utils
17181718 sock_.close ();
17191719 return CONNECT_FAILURE;
17201720 }
1721+ new_connection_l->set_ssl_enabled ();
17211722 }
17221723
17231724 return CONNECT_SUCCESS;
@@ -1726,11 +1727,11 @@ namespace net_utils
17261727 }
17271728 // ---------------------------------------------------------------------------------
17281729 template <class t_protocol_handler >
1729- bool boosted_tcp_server<t_protocol_handler>::connect(const std::string& adr, const std::string& port, uint32_t conn_timeout, t_connection_context& conn_context, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support )
1730+ bool boosted_tcp_server<t_protocol_handler>::connect(const std::string& adr, const std::string& port, uint32_t conn_timeout, t_connection_context& conn_context, const std::string& bind_ip, epee::net_utils::ssl_options_t ssl_options )
17301731 {
17311732 TRY_ENTRY ();
17321733
1733- connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support ) );
1734+ connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_options. support ) );
17341735 connections_mutex.lock ();
17351736 connections_.insert (new_connection_l);
17361737 MDEBUG (" connections_ size now " << connections_.size ());
@@ -1818,24 +1819,22 @@ namespace net_utils
18181819 // boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port);
18191820 boost::asio::ip::tcp::endpoint remote_endpoint (*iterator);
18201821
1821- auto try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_support );
1822+ auto try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_options );
18221823 if (try_connect_result == CONNECT_FAILURE)
18231824 return false ;
1824- if (ssl_support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect && try_connect_result == CONNECT_NO_SSL)
1825+ if (ssl_options. support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect && try_connect_result == CONNECT_NO_SSL)
18251826 {
18261827 // we connected, but could not connect with SSL, try without
18271828 MERROR (" SSL handshake failed on an autodetect connection, reconnecting without SSL" );
18281829 new_connection_l->disable_ssl ();
1829- try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, epee::net_utils::ssl_support_t ::e_ssl_support_disabled);
1830+ ssl_options = epee::net_utils::ssl_support_t ::e_ssl_support_disabled;
1831+ try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_options);
18301832 if (try_connect_result != CONNECT_SUCCESS)
18311833 return false ;
18321834 }
18331835
18341836 // start adds the connection to the config object's list, so we don't need to have it locally anymore
1835- connections_mutex.lock ();
1836- connections_.erase (new_connection_l);
1837- connections_mutex.unlock ();
1838- bool r = new_connection_l->start (false , 1 < m_threads_count);
1837+ bool r = remove_connection (new_connection_l) && new_connection_l->start (false , 1 < m_threads_count);
18391838 if (r)
18401839 {
18411840 new_connection_l->get_context (conn_context);
@@ -1854,10 +1853,10 @@ namespace net_utils
18541853 }
18551854 // ---------------------------------------------------------------------------------
18561855 template <class t_protocol_handler > template <class t_callback >
1857- bool boosted_tcp_server<t_protocol_handler>::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support , t_connection_context&& initial)
1856+ bool boosted_tcp_server<t_protocol_handler>::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip, epee::net_utils::ssl_options_t ssl_options , t_connection_context&& initial)
18581857 {
18591858 TRY_ENTRY ();
1860- connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support , std::move (initial)) );
1859+ connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_options. support , std::move (initial)) );
18611860 connections_mutex.lock ();
18621861 connections_.insert (new_connection_l);
18631862 MDEBUG (" connections_ size now " << connections_.size ());
@@ -1934,60 +1933,114 @@ namespace net_utils
19341933 return false ;
19351934 }
19361935 }
1937-
1938- boost::shared_ptr<boost::asio::deadline_timer> sh_deadline (new boost::asio::deadline_timer (io_context_));
1939- // start deadline
1940- sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout));
1941- sh_deadline->async_wait ([=](const boost::system::error_code& error)
1936+
1937+ ssl_options.configure (new_connection_l->socket_ , boost::asio::ssl::stream_base::client);
1938+ return connect_async_internal (new_connection_l, remote_endpoint, conn_timeout, cb);
1939+ CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async" , false );
1940+ }
1941+
1942+ template <class t_protocol_handler > template <class t_callback >
1943+ bool boosted_tcp_server<t_protocol_handler>::connect_async_internal(const connection_ptr& new_connection_l, const boost::asio::ip::tcp::endpoint& remote_endpoint, uint32_t conn_timeout, const t_callback &cb)
1944+ {
1945+ if (!new_connection_l)
1946+ return false ;
1947+
1948+ TRY_ENTRY ();
1949+
1950+ const auto on_timer = [=](boost::system::error_code error)
19421951 {
1943- if (error != boost::asio::error::operation_aborted)
1944- {
1945- _dbg3 (" Failed to connect to " << adr << ' :' << port << " , because of timeout (" << conn_timeout << " )" );
1946- new_connection_l->socket ().close ();
1947- }
1948- });
1949- // start async connect
1950- sock_.async_connect (remote_endpoint, [=](const boost::system::error_code& ec_)
1952+ if (error != boost::asio::error::operation_aborted)
1953+ {
1954+ _dbg3 (" Failed to connect to " << remote_endpoint << " , because of timeout (" << conn_timeout << ' )' );
1955+ new_connection_l->socket ().close (error); // ignore errors
1956+ }
1957+ };
1958+
1959+ auto sh_deadline = std::make_shared<boost::asio::deadline_timer>(io_context_);
1960+ sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout));
1961+ sh_deadline->async_wait (new_connection_l->wrap (on_timer));
1962+
1963+ new_connection_l->socket ().async_connect (remote_endpoint, new_connection_l->wrap ([=](const boost::system::error_code& ec_)
19511964 {
1952- t_connection_context conn_context = AUTO_VAL_INIT (conn_context);
1953- boost::system::error_code ignored_ec;
1954- boost::asio::ip::tcp::socket::endpoint_type lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1965+ const auto on_cancel = [=](const boost::system::error_code& error)
1966+ {
1967+ boost::system::error_code ignored_ec{};
1968+ const auto lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1969+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] to " << remote_endpoint << " from " << lep << " failed: " << error.message ());
1970+ if (remove_connection (new_connection_l))
1971+ cb (t_connection_context{}, error);
1972+ };
1973+
19551974 if (!ec_)
19561975 {// success
1957- if (!sh_deadline->cancel ())
1958- {
1959- cb (conn_context, boost::asio::error::operation_aborted);// this mean that deadline timer already queued callback with cancel operation, rare situation
1960- }else
1961- {
1962- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Connected success to " << adr << ' :' << port <<
1963- " from " << lep.address ().to_string () << ' :' << lep.port ());
1964-
1965- // start adds the connection to the config object's list, so we don't need to have it locally anymore
1966- connections_mutex.lock ();
1967- connections_.erase (new_connection_l);
1968- connections_mutex.unlock ();
1969- bool r = new_connection_l->start (false , 1 < m_threads_count);
1970- if (r)
1976+ const auto on_ready = [=] ()
19711977 {
1972- new_connection_l->get_context (conn_context);
1973- cb (conn_context, ec_);
1974- }
1975- else
1978+ if (sh_deadline->cancel ())
1979+ {
1980+ boost::system::error_code ignored_ec{};
1981+ const auto lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1982+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Connected successfully to " << remote_endpoint <<
1983+ " from " << lep.address ().to_string () << ' :' << lep.port ());
1984+
1985+ if (remove_connection (new_connection_l) && new_connection_l->start (false , 1 < m_threads_count))
1986+ {
1987+ t_connection_context conn_context{};
1988+ new_connection_l->get_context (conn_context);
1989+ cb (conn_context, ec_);
1990+ }
1991+ else
1992+ on_cancel (boost::asio::error::fault);
1993+ }
1994+ else // if timer already expired
1995+ on_cancel (boost::asio::error::operation_aborted);
1996+ };
1997+
1998+ if (new_connection_l->get_ssl_support () != ssl_support_t ::e_ssl_support_disabled)
1999+ {
2000+ // set new timer for handshake
2001+ if (sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout)))
19762002 {
1977- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Failed to start connection to " << adr << ' :' << port);
1978- cb (conn_context, boost::asio::error::fault);
2003+ sh_deadline->async_wait (new_connection_l->wrap (on_timer));
2004+ new_connection_l->socket_ .async_handshake (boost::asio::ssl::stream_base::client, new_connection_l->wrap ([=] (const boost::system::error_code& ec)
2005+ {
2006+ if (ec)
2007+ {
2008+ sh_deadline->cancel ();
2009+ if (new_connection_l->get_ssl_support () == ssl_support_t ::e_ssl_support_autodetect)
2010+ {
2011+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] SSL connection to " <<
2012+ remote_endpoint << " failed: " << ec.message () << " . Trying without SSL" );
2013+ new_connection_l->disable_ssl ();
2014+ connect_async_internal (new_connection_l, remote_endpoint, conn_timeout, cb);
2015+ }
2016+ else // ssl mandatory and failed
2017+ on_cancel (ec);
2018+ }
2019+ else // ssl handshake complete
2020+ on_ready ();
2021+ }));
19792022 }
2023+ else // if timer already expired
2024+ on_cancel (boost::asio::error::operation_aborted);
19802025 }
1981- }else
1982- {
1983- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Failed to connect to " << adr << ' :' << port <<
1984- " from " << lep.address ().to_string () << ' :' << lep.port () << " : " << ec_.message () << ' :' << ec_.value ());
1985- cb (conn_context, ec_);
2026+ else // ssl disabled
2027+ on_ready ();
19862028 }
1987- });
2029+ else // ec_ has error
2030+ on_cancel (ec_);
2031+ }));
2032+ return true ;
2033+ CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async_internal" , false );
2034+ }
2035+
2036+ template <class t_protocol_handler >
2037+ bool boosted_tcp_server<t_protocol_handler>::remove_connection(const connection_ptr& new_connection)
2038+ {
2039+ if (!new_connection)
2040+ return false ;
2041+ const boost::lock_guard<boost::mutex> sync{connections_mutex};
2042+ connections_.erase (new_connection);
19882043 return true ;
1989- CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async" , false );
19902044 }
1991-
19922045} // namespace
19932046} // namespace
0 commit comments