@@ -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 */ }
@@ -1624,7 +1624,7 @@ namespace net_utils
16241624 }
16251625 // ---------------------------------------------------------------------------------
16261626 template <class t_protocol_handler >
1627- 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 )
1627+ 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 )
16281628 {
16291629 TRY_ENTRY ();
16301630
@@ -1700,7 +1700,7 @@ namespace net_utils
17001700 {
17011701 // Handshake
17021702 MDEBUG (" Handshaking SSL..." );
1703- if (!new_connection_l->handshake (boost::asio::ssl::stream_base::client ))
1703+ if (!new_connection_l->client_handshake (ssl_options ))
17041704 {
17051705 if (ssl_support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect)
17061706 {
@@ -1714,6 +1714,7 @@ namespace net_utils
17141714 sock_.close ();
17151715 return CONNECT_FAILURE;
17161716 }
1717+ new_connection_l->set_ssl_enabled ();
17171718 }
17181719
17191720 return CONNECT_SUCCESS;
@@ -1722,11 +1723,11 @@ namespace net_utils
17221723 }
17231724 // ---------------------------------------------------------------------------------
17241725 template <class t_protocol_handler >
1725- 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 )
1726+ 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 )
17261727 {
17271728 TRY_ENTRY ();
17281729
1729- connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support ) );
1730+ connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_options. support ) );
17301731 connections_mutex.lock ();
17311732 connections_.insert (new_connection_l);
17321733 MDEBUG (" connections_ size now " << connections_.size ());
@@ -1814,24 +1815,22 @@ namespace net_utils
18141815 // boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port);
18151816 boost::asio::ip::tcp::endpoint remote_endpoint (*iterator);
18161817
1817- auto try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_support );
1818+ auto try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_options );
18181819 if (try_connect_result == CONNECT_FAILURE)
18191820 return false ;
1820- if (ssl_support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect && try_connect_result == CONNECT_NO_SSL)
1821+ if (ssl_options. support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect && try_connect_result == CONNECT_NO_SSL)
18211822 {
18221823 // we connected, but could not connect with SSL, try without
18231824 MERROR (" SSL handshake failed on an autodetect connection, reconnecting without SSL" );
18241825 new_connection_l->disable_ssl ();
1825- 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);
1826+ ssl_options = epee::net_utils::ssl_support_t ::e_ssl_support_disabled;
1827+ try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_options);
18261828 if (try_connect_result != CONNECT_SUCCESS)
18271829 return false ;
18281830 }
18291831
18301832 // start adds the connection to the config object's list, so we don't need to have it locally anymore
1831- connections_mutex.lock ();
1832- connections_.erase (new_connection_l);
1833- connections_mutex.unlock ();
1834- bool r = new_connection_l->start (false , 1 < m_threads_count);
1833+ bool r = remove_connection (new_connection_l) && new_connection_l->start (false , 1 < m_threads_count);
18351834 if (r)
18361835 {
18371836 new_connection_l->get_context (conn_context);
@@ -1850,10 +1849,10 @@ namespace net_utils
18501849 }
18511850 // ---------------------------------------------------------------------------------
18521851 template <class t_protocol_handler > template <class t_callback >
1853- 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 )
1852+ 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 )
18541853 {
18551854 TRY_ENTRY ();
1856- connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support ) );
1855+ connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_options. support ) );
18571856 connections_mutex.lock ();
18581857 connections_.insert (new_connection_l);
18591858 MDEBUG (" connections_ size now " << connections_.size ());
@@ -1930,60 +1929,113 @@ namespace net_utils
19301929 return false ;
19311930 }
19321931 }
1933-
1934- boost::shared_ptr<boost::asio::deadline_timer> sh_deadline (new boost::asio::deadline_timer (io_context_));
1935- // start deadline
1936- sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout));
1937- sh_deadline->async_wait ([=](const boost::system::error_code& error)
1932+
1933+ ssl_options.configure (new_connection_l->socket_ , boost::asio::ssl::stream_base::client);
1934+ return connect_async_internal (new_connection_l, remote_endpoint, conn_timeout, cb);
1935+ CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async" , false );
1936+ }
1937+
1938+ template <class t_protocol_handler > template <class t_callback >
1939+ 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)
1940+ {
1941+ if (!new_connection_l)
1942+ return false ;
1943+
1944+ TRY_ENTRY ();
1945+
1946+ const auto on_timer = [=](boost::system::error_code error)
19381947 {
1939- if (error != boost::asio::error::operation_aborted)
1940- {
1941- _dbg3 (" Failed to connect to " << adr << ' :' << port << " , because of timeout (" << conn_timeout << " )" );
1942- new_connection_l->socket ().close ();
1943- }
1944- });
1945- // start async connect
1946- sock_.async_connect (remote_endpoint, [=](const boost::system::error_code& ec_)
1948+ if (error != boost::asio::error::operation_aborted)
1949+ {
1950+ _dbg3 (" Failed to connect to " << remote_endpoint << " , because of timeout (" << conn_timeout << ' )' );
1951+ new_connection_l->socket ().close (error); // ignore errors
1952+ }
1953+ };
1954+
1955+ auto sh_deadline = std::make_shared<boost::asio::deadline_timer>(io_context_);
1956+ sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout));
1957+ sh_deadline->async_wait (new_connection_l->wrap (on_timer));
1958+
1959+ new_connection_l->socket ().async_connect (remote_endpoint, new_connection_l->wrap ([=](const boost::system::error_code& ec_)
19471960 {
1948- t_connection_context conn_context = AUTO_VAL_INIT (conn_context);
1949- boost::system::error_code ignored_ec;
1950- boost::asio::ip::tcp::socket::endpoint_type lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1961+ const auto on_cancel = [=](const boost::system::error_code& error)
1962+ {
1963+ boost::system::error_code ignored_ec{};
1964+ const auto lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1965+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] to " << remote_endpoint << " from " << lep << " failed: " << error.message ());
1966+ if (remove_connection (new_connection_l))
1967+ cb (t_connection_context{}, error);
1968+ };
1969+
19511970 if (!ec_)
19521971 {// success
1953- if (!sh_deadline->cancel ())
1954- {
1955- cb (conn_context, boost::asio::error::operation_aborted);// this mean that deadline timer already queued callback with cancel operation, rare situation
1956- }else
1957- {
1958- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Connected success to " << adr << ' :' << port <<
1959- " from " << lep.address ().to_string () << ' :' << lep.port ());
1960-
1961- // start adds the connection to the config object's list, so we don't need to have it locally anymore
1962- connections_mutex.lock ();
1963- connections_.erase (new_connection_l);
1964- connections_mutex.unlock ();
1965- bool r = new_connection_l->start (false , 1 < m_threads_count);
1966- if (r)
1972+ const auto on_ready = [=] ()
19671973 {
1968- new_connection_l->get_context (conn_context);
1969- cb (conn_context, ec_);
1970- }
1971- else
1974+ if (sh_deadline->cancel ())
1975+ {
1976+ boost::system::error_code ignored_ec{};
1977+ const auto lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1978+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Connected successfully to " << remote_endpoint <<
1979+ " from " << lep.address ().to_string () << ' :' << lep.port ());
1980+
1981+ if (remove_connection (new_connection_l) && new_connection_l->start (false , 1 < m_threads_count))
1982+ {
1983+ t_connection_context conn_context{};
1984+ new_connection_l->get_context (conn_context);
1985+ cb (conn_context, ec_);
1986+ }
1987+ else
1988+ on_cancel (boost::asio::error::fault);
1989+ }
1990+ else // if timer already expired
1991+ on_cancel (boost::asio::error::operation_aborted);
1992+ };
1993+
1994+ if (new_connection_l->get_ssl_support () != ssl_support_t ::e_ssl_support_disabled)
1995+ {
1996+ // set new timer for handshake
1997+ if (sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout)))
19721998 {
1973- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Failed to start connection to " << adr << ' :' << port);
1974- cb (conn_context, boost::asio::error::fault);
1999+ sh_deadline->async_wait (new_connection_l->wrap (on_timer));
2000+ new_connection_l->socket_ .async_handshake (boost::asio::ssl::stream_base::client, new_connection_l->wrap ([=] (const boost::system::error_code& ec)
2001+ {
2002+ if (ec)
2003+ {
2004+ if (new_connection_l->get_ssl_support () == ssl_support_t ::e_ssl_support_autodetect)
2005+ {
2006+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] SSL connection to " <<
2007+ remote_endpoint << " failed: " << ec.message () << " . Trying without SSL" );
2008+ new_connection_l->disable_ssl ();
2009+ connect_async_internal (new_connection_l, remote_endpoint, conn_timeout, cb);
2010+ }
2011+ else // ssl mandatory and failed
2012+ on_cancel (ec);
2013+ }
2014+ else // ssl handshake complete
2015+ on_ready ();
2016+ }));
19752017 }
2018+ else // if timer already expired
2019+ on_cancel (boost::asio::error::operation_aborted);
19762020 }
1977- }else
1978- {
1979- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Failed to connect to " << adr << ' :' << port <<
1980- " from " << lep.address ().to_string () << ' :' << lep.port () << " : " << ec_.message () << ' :' << ec_.value ());
1981- cb (conn_context, ec_);
2021+ else // ssl disabled
2022+ on_ready ();
19822023 }
1983- });
2024+ else // ec_ has error
2025+ on_cancel (ec_);
2026+ }));
2027+ return true ;
2028+ CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async_internal" , false );
2029+ }
2030+
2031+ template <class t_protocol_handler >
2032+ bool boosted_tcp_server<t_protocol_handler>::remove_connection(const connection_ptr& new_connection)
2033+ {
2034+ if (!new_connection)
2035+ return false ;
2036+ const boost::lock_guard<boost::mutex> sync{connections_mutex};
2037+ connections_.erase (new_connection);
19842038 return true ;
1985- CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async" , false );
19862039 }
1987-
19882040} // namespace
19892041} // namespace
0 commit comments