diff options
author | Vasil Dimov <vd@FreeBSD.org> | 2023-01-06 11:23:46 +0100 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2023-02-27 13:59:51 +0000 |
commit | 5027e93b6a1e5a5c87b9450c60e2a4572eb32653 (patch) | |
tree | 7f3556a8716e690a1a58b822f752dbf54467b668 /src/net.cpp | |
parent | a62c541ae8a579d19b8fc55bbb922f0939ab6110 (diff) | |
download | bitcoin-5027e93b6a1e5a5c87b9450c60e2a4572eb32653.tar.xz |
i2p: reuse created I2P sessions if not used
In the case of `i2pacceptincoming=0` we use transient addresses
(destinations) for ourselves for each outbound connection. It may
happen that we
* create the session (and thus our address/destination too)
* fail to connect to the particular peer (e.g. if they are offline)
* dispose the unused session.
This puts unnecessary load on the I2P network because session creation
is not cheap. Is exaggerated if `onlynet=i2p` is used in which case we
will be trying to connect to I2P peers more often.
To help with this, save the created but unused sessions and pick them
later instead of creating new ones.
Alleviates: https://github.com/bitcoin/bitcoin/issues/26754
Github-Pull: #26837
Rebased-From: b906b64eb76643feaede1da5987a0c4d466c581b
Diffstat (limited to 'src/net.cpp')
-rw-r--r-- | src/net.cpp | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/src/net.cpp b/src/net.cpp index 0cc14b1d2a..a6bf2a9dcc 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -436,6 +436,7 @@ static CAddress GetBindAddress(const Sock& sock) CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type) { + AssertLockNotHeld(m_unused_i2p_sessions_mutex); assert(conn_type != ConnectionType::INBOUND); if (pszDest == nullptr) { @@ -496,8 +497,23 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo if (m_i2p_sam_session) { connected = m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed); } else { - i2p_transient_session = std::make_unique<i2p::sam::Session>(proxy.proxy, &interruptNet); + { + LOCK(m_unused_i2p_sessions_mutex); + if (m_unused_i2p_sessions.empty()) { + i2p_transient_session = + std::make_unique<i2p::sam::Session>(proxy.proxy, &interruptNet); + } else { + i2p_transient_session.swap(m_unused_i2p_sessions.front()); + m_unused_i2p_sessions.pop(); + } + } connected = i2p_transient_session->Connect(addrConnect, conn, proxyConnectionFailed); + if (!connected) { + LOCK(m_unused_i2p_sessions_mutex); + if (m_unused_i2p_sessions.size() < MAX_UNUSED_I2P_SESSIONS_SIZE) { + m_unused_i2p_sessions.emplace(i2p_transient_session.release()); + } + } } if (connected) { @@ -1048,6 +1064,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock, bool CConnman::AddConnection(const std::string& address, ConnectionType conn_type) { + AssertLockNotHeld(m_unused_i2p_sessions_mutex); std::optional<int> max_connections; switch (conn_type) { case ConnectionType::INBOUND: @@ -1510,6 +1527,7 @@ void CConnman::DumpAddresses() void CConnman::ProcessAddrFetch() { + AssertLockNotHeld(m_unused_i2p_sessions_mutex); std::string strDest; { LOCK(m_addr_fetches_mutex); @@ -1578,6 +1596,7 @@ int CConnman::GetExtraBlockRelayCount() const void CConnman::ThreadOpenConnections(const std::vector<std::string> connect) { + AssertLockNotHeld(m_unused_i2p_sessions_mutex); SetSyscallSandboxPolicy(SyscallSandboxPolicy::NET_OPEN_CONNECTION); FastRandomContext rng; // Connect to specific addresses @@ -1929,6 +1948,7 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() const void CConnman::ThreadOpenAddedConnections() { + AssertLockNotHeld(m_unused_i2p_sessions_mutex); SetSyscallSandboxPolicy(SyscallSandboxPolicy::NET_ADD_CONNECTION); while (true) { @@ -1958,6 +1978,7 @@ void CConnman::ThreadOpenAddedConnections() // if successful, this moves the passed grant to the constructed node void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, ConnectionType conn_type) { + AssertLockNotHeld(m_unused_i2p_sessions_mutex); assert(conn_type != ConnectionType::INBOUND); // |