@@ -933,7 +933,7 @@ namespace net_utils
933
933
boost::uuids::random_generator ()(),
934
934
*real_remote,
935
935
is_income,
936
- connection_basic::m_ssl_support == ssl_support_t ::e_ssl_support_enabled
936
+ connection_basic::m_ssl_support
937
937
);
938
938
m_host = real_remote->host_str ();
939
939
try { host_count (1 ); } catch (...) { /* ignore */ }
@@ -1618,7 +1618,7 @@ namespace net_utils
1618
1618
}
1619
1619
// ---------------------------------------------------------------------------------
1620
1620
template <class t_protocol_handler >
1621
- 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 )
1621
+ 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 )
1622
1622
{
1623
1623
TRY_ENTRY ();
1624
1624
@@ -1694,7 +1694,7 @@ namespace net_utils
1694
1694
{
1695
1695
// Handshake
1696
1696
MDEBUG (" Handshaking SSL..." );
1697
- if (!new_connection_l->handshake (boost::asio::ssl::stream_base::client ))
1697
+ if (!new_connection_l->client_handshake (ssl_options ))
1698
1698
{
1699
1699
if (ssl_support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect)
1700
1700
{
@@ -1708,6 +1708,7 @@ namespace net_utils
1708
1708
sock_.close ();
1709
1709
return CONNECT_FAILURE;
1710
1710
}
1711
+ new_connection_l->set_ssl_enabled ();
1711
1712
}
1712
1713
1713
1714
return CONNECT_SUCCESS;
@@ -1716,11 +1717,11 @@ namespace net_utils
1716
1717
}
1717
1718
// ---------------------------------------------------------------------------------
1718
1719
template <class t_protocol_handler >
1719
- 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 )
1720
+ 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 )
1720
1721
{
1721
1722
TRY_ENTRY ();
1722
1723
1723
- connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support ) );
1724
+ connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_options. support ) );
1724
1725
connections_mutex.lock ();
1725
1726
connections_.insert (new_connection_l);
1726
1727
MDEBUG (" connections_ size now " << connections_.size ());
@@ -1808,24 +1809,22 @@ namespace net_utils
1808
1809
// boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port);
1809
1810
boost::asio::ip::tcp::endpoint remote_endpoint (*iterator);
1810
1811
1811
- auto try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_support );
1812
+ auto try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_options );
1812
1813
if (try_connect_result == CONNECT_FAILURE)
1813
1814
return false ;
1814
- if (ssl_support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect && try_connect_result == CONNECT_NO_SSL)
1815
+ if (ssl_options. support == epee::net_utils::ssl_support_t ::e_ssl_support_autodetect && try_connect_result == CONNECT_NO_SSL)
1815
1816
{
1816
1817
// we connected, but could not connect with SSL, try without
1817
1818
MERROR (" SSL handshake failed on an autodetect connection, reconnecting without SSL" );
1818
1819
new_connection_l->disable_ssl ();
1819
- 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);
1820
+ ssl_options = epee::net_utils::ssl_support_t ::e_ssl_support_disabled;
1821
+ try_connect_result = try_connect (new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout, ssl_options);
1820
1822
if (try_connect_result != CONNECT_SUCCESS)
1821
1823
return false ;
1822
1824
}
1823
1825
1824
1826
// start adds the connection to the config object's list, so we don't need to have it locally anymore
1825
- connections_mutex.lock ();
1826
- connections_.erase (new_connection_l);
1827
- connections_mutex.unlock ();
1828
- bool r = new_connection_l->start (false , 1 < m_threads_count);
1827
+ bool r = remove_connection (new_connection_l) && new_connection_l->start (false , 1 < m_threads_count);
1829
1828
if (r)
1830
1829
{
1831
1830
new_connection_l->get_context (conn_context);
@@ -1844,10 +1843,10 @@ namespace net_utils
1844
1843
}
1845
1844
// ---------------------------------------------------------------------------------
1846
1845
template <class t_protocol_handler > template <class t_callback >
1847
- 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 )
1846
+ 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 )
1848
1847
{
1849
1848
TRY_ENTRY ();
1850
- connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support ) );
1849
+ connection_ptr new_connection_l (new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_options. support ) );
1851
1850
connections_mutex.lock ();
1852
1851
connections_.insert (new_connection_l);
1853
1852
MDEBUG (" connections_ size now " << connections_.size ());
@@ -1924,60 +1923,113 @@ namespace net_utils
1924
1923
return false ;
1925
1924
}
1926
1925
}
1927
-
1928
- boost::shared_ptr<boost::asio::deadline_timer> sh_deadline (new boost::asio::deadline_timer (io_context_));
1929
- // start deadline
1930
- sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout));
1931
- sh_deadline->async_wait ([=](const boost::system::error_code& error)
1926
+
1927
+ ssl_options.configure (new_connection_l->socket_ , boost::asio::ssl::stream_base::client);
1928
+ return connect_async_internal (new_connection_l, remote_endpoint, conn_timeout, cb);
1929
+ CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async" , false );
1930
+ }
1931
+
1932
+ template <class t_protocol_handler > template <class t_callback >
1933
+ 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)
1934
+ {
1935
+ if (!new_connection_l)
1936
+ return false ;
1937
+
1938
+ TRY_ENTRY ();
1939
+
1940
+ const auto on_timer = [=](boost::system::error_code error)
1932
1941
{
1933
- if (error != boost::asio::error::operation_aborted)
1934
- {
1935
- _dbg3 (" Failed to connect to " << adr << ' :' << port << " , because of timeout (" << conn_timeout << " )" );
1936
- new_connection_l->socket ().close ();
1937
- }
1938
- });
1939
- // start async connect
1940
- sock_.async_connect (remote_endpoint, [=](const boost::system::error_code& ec_)
1942
+ if (error != boost::asio::error::operation_aborted)
1943
+ {
1944
+ _dbg3 (" Failed to connect to " << remote_endpoint << " , because of timeout (" << conn_timeout << ' )' );
1945
+ new_connection_l->socket ().close (error); // ignore errors
1946
+ }
1947
+ };
1948
+
1949
+ auto sh_deadline = std::make_shared<boost::asio::deadline_timer>(io_context_);
1950
+ sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout));
1951
+ sh_deadline->async_wait (new_connection_l->wrap (on_timer));
1952
+
1953
+ new_connection_l->socket ().async_connect (remote_endpoint, new_connection_l->wrap ([=](const boost::system::error_code& ec_)
1941
1954
{
1942
- t_connection_context conn_context = AUTO_VAL_INIT (conn_context);
1943
- boost::system::error_code ignored_ec;
1944
- boost::asio::ip::tcp::socket::endpoint_type lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1955
+ const auto on_cancel = [=](const boost::system::error_code& error)
1956
+ {
1957
+ boost::system::error_code ignored_ec{};
1958
+ const auto lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1959
+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] to " << remote_endpoint << " from " << lep << " failed: " << error.message ());
1960
+ if (remove_connection (new_connection_l))
1961
+ cb (t_connection_context{}, error);
1962
+ };
1963
+
1945
1964
if (!ec_)
1946
1965
{// success
1947
- if (!sh_deadline->cancel ())
1948
- {
1949
- cb (conn_context, boost::asio::error::operation_aborted);// this mean that deadline timer already queued callback with cancel operation, rare situation
1950
- }else
1951
- {
1952
- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Connected success to " << adr << ' :' << port <<
1953
- " from " << lep.address ().to_string () << ' :' << lep.port ());
1954
-
1955
- // start adds the connection to the config object's list, so we don't need to have it locally anymore
1956
- connections_mutex.lock ();
1957
- connections_.erase (new_connection_l);
1958
- connections_mutex.unlock ();
1959
- bool r = new_connection_l->start (false , 1 < m_threads_count);
1960
- if (r)
1966
+ const auto on_ready = [=] ()
1961
1967
{
1962
- new_connection_l->get_context (conn_context);
1963
- cb (conn_context, ec_);
1964
- }
1965
- else
1968
+ if (sh_deadline->cancel ())
1969
+ {
1970
+ boost::system::error_code ignored_ec{};
1971
+ const auto lep = new_connection_l->socket ().local_endpoint (ignored_ec);
1972
+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Connected successfully to " << remote_endpoint <<
1973
+ " from " << lep.address ().to_string () << ' :' << lep.port ());
1974
+
1975
+ if (remove_connection (new_connection_l) && new_connection_l->start (false , 1 < m_threads_count))
1976
+ {
1977
+ t_connection_context conn_context{};
1978
+ new_connection_l->get_context (conn_context);
1979
+ cb (conn_context, ec_);
1980
+ }
1981
+ else
1982
+ on_cancel (boost::asio::error::fault);
1983
+ }
1984
+ else // if timer already expired
1985
+ on_cancel (boost::asio::error::operation_aborted);
1986
+ };
1987
+
1988
+ if (new_connection_l->get_ssl_support () != ssl_support_t ::e_ssl_support_disabled)
1989
+ {
1990
+ // set new timer for handshake
1991
+ if (sh_deadline->expires_from_now (boost::posix_time::milliseconds (conn_timeout)))
1966
1992
{
1967
- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Failed to start connection to " << adr << ' :' << port);
1968
- cb (conn_context, boost::asio::error::fault);
1993
+ sh_deadline->async_wait (new_connection_l->wrap (on_timer));
1994
+ new_connection_l->socket_ .async_handshake (boost::asio::ssl::stream_base::client, new_connection_l->wrap ([=] (const boost::system::error_code& ec)
1995
+ {
1996
+ if (ec)
1997
+ {
1998
+ if (new_connection_l->get_ssl_support () == ssl_support_t ::e_ssl_support_autodetect)
1999
+ {
2000
+ _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] SSL connection to " <<
2001
+ remote_endpoint << " failed: " << ec.message () << " . Trying without SSL" );
2002
+ new_connection_l->disable_ssl ();
2003
+ connect_async_internal (new_connection_l, remote_endpoint, conn_timeout, cb);
2004
+ }
2005
+ else // ssl mandatory and failed
2006
+ on_cancel (ec);
2007
+ }
2008
+ else // ssl handshake complete
2009
+ on_ready ();
2010
+ }));
1969
2011
}
2012
+ else // if timer already expired
2013
+ on_cancel (boost::asio::error::operation_aborted);
1970
2014
}
1971
- }else
1972
- {
1973
- _dbg3 (" [sock " << new_connection_l->socket ().native_handle () << " ] Failed to connect to " << adr << ' :' << port <<
1974
- " from " << lep.address ().to_string () << ' :' << lep.port () << " : " << ec_.message () << ' :' << ec_.value ());
1975
- cb (conn_context, ec_);
2015
+ else // ssl disabled
2016
+ on_ready ();
1976
2017
}
1977
- });
2018
+ else // ec_ has error
2019
+ on_cancel (ec_);
2020
+ }));
2021
+ return true ;
2022
+ CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async_internal" , false );
2023
+ }
2024
+
2025
+ template <class t_protocol_handler >
2026
+ bool boosted_tcp_server<t_protocol_handler>::remove_connection(const connection_ptr& new_connection)
2027
+ {
2028
+ if (!new_connection)
2029
+ return false ;
2030
+ const boost::lock_guard<boost::mutex> sync{connections_mutex};
2031
+ connections_.erase (new_connection);
1978
2032
return true ;
1979
- CATCH_ENTRY_L0 (" boosted_tcp_server<t_protocol_handler>::connect_async" , false );
1980
2033
}
1981
-
1982
2034
} // namespace
1983
2035
} // namespace
0 commit comments