Skip to content

Commit 859f59b

Browse files
kwvgPastaPastaPasta
authored andcommitted
merge bitcoin#26837: I2P network optimizations
1 parent 9f80734 commit 859f59b

File tree

3 files changed

+60
-12
lines changed

3 files changed

+60
-12
lines changed

src/i2p.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,9 @@ void Session::CreateIfNotCreatedAlready()
380380
// in the reply in DESTINATION=.
381381
const Reply& reply = SendRequestAndGetReply(
382382
*sock,
383-
strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=TRANSIENT SIGNATURE_TYPE=7", session_id));
383+
strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=TRANSIENT SIGNATURE_TYPE=7 "
384+
"inbound.quantity=1 outbound.quantity=1",
385+
session_id));
384386

385387
m_private_key = DecodeI2PBase64(reply.Get("DESTINATION"));
386388
} else {
@@ -396,7 +398,8 @@ void Session::CreateIfNotCreatedAlready()
396398
const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));
397399

398400
SendRequestAndGetReply(*sock,
399-
strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
401+
strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s "
402+
"inbound.quantity=3 outbound.quantity=3",
400403
session_id,
401404
private_key_b64));
402405
}

src/net.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ static CAddress GetBindAddress(SOCKET sock)
420420

421421
CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type)
422422
{
423+
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
423424
assert(conn_type != ConnectionType::INBOUND);
424425

425426
if (pszDest == nullptr) {
@@ -487,8 +488,23 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
487488
if (m_i2p_sam_session) {
488489
connected = m_i2p_sam_session->Connect(addrConnect, conn, proxyConnectionFailed);
489490
} else {
490-
i2p_transient_session = std::make_unique<i2p::sam::Session>(proxy.proxy, &interruptNet);
491+
{
492+
LOCK(m_unused_i2p_sessions_mutex);
493+
if (m_unused_i2p_sessions.empty()) {
494+
i2p_transient_session =
495+
std::make_unique<i2p::sam::Session>(proxy.proxy, &interruptNet);
496+
} else {
497+
i2p_transient_session.swap(m_unused_i2p_sessions.front());
498+
m_unused_i2p_sessions.pop();
499+
}
500+
}
491501
connected = i2p_transient_session->Connect(addrConnect, conn, proxyConnectionFailed);
502+
if (!connected) {
503+
LOCK(m_unused_i2p_sessions_mutex);
504+
if (m_unused_i2p_sessions.size() < MAX_UNUSED_I2P_SESSIONS_SIZE) {
505+
m_unused_i2p_sessions.emplace(i2p_transient_session.release());
506+
}
507+
}
492508
}
493509

494510
if (connected) {
@@ -1347,6 +1363,7 @@ void CConnman::CreateNodeFromAcceptedSocket(SOCKET hSocket,
13471363

13481364
bool CConnman::AddConnection(const std::string& address, ConnectionType conn_type)
13491365
{
1366+
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
13501367
std::optional<int> max_connections;
13511368
switch (conn_type) {
13521369
case ConnectionType::INBOUND:
@@ -2316,6 +2333,7 @@ void CConnman::DumpAddresses()
23162333

23172334
void CConnman::ProcessAddrFetch()
23182335
{
2336+
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
23192337
std::string strDest;
23202338
{
23212339
LOCK(m_addr_fetches_mutex);
@@ -2382,6 +2400,7 @@ int CConnman::GetExtraBlockRelayCount() const
23822400

23832401
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDeterministicMNManager& dmnman)
23842402
{
2403+
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
23852404
FastRandomContext rng;
23862405
// Connect to specific addresses
23872406
if (!connect.empty())
@@ -2750,6 +2769,7 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() const
27502769

27512770
void CConnman::ThreadOpenAddedConnections()
27522771
{
2772+
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
27532773
while (true)
27542774
{
27552775
CSemaphoreGrant grant(*semAddnode);
@@ -2953,6 +2973,7 @@ void CConnman::ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman,
29532973
// if successful, this moves the passed grant to the constructed node
29542974
void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, ConnectionType conn_type, MasternodeConn masternode_connection, MasternodeProbeConn masternode_probe_connection)
29552975
{
2976+
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
29562977
assert(conn_type != ConnectionType::INBOUND);
29572978

29582979
//

src/net.h

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@
4141
#include <functional>
4242
#include <map>
4343
#include <memory>
44-
#include <thread>
4544
#include <optional>
4645
#include <queue>
46+
#include <thread>
4747
#include <vector>
4848

4949
class CConnman;
@@ -925,9 +925,9 @@ friend class CNode;
925925
const char* strDest, ConnectionType conn_type,
926926
MasternodeConn masternode_connection = MasternodeConn::IsNotConnection,
927927
MasternodeProbeConn masternode_probe_connection = MasternodeProbeConn::IsNotConnection)
928-
EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
928+
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex, !mutexMsgProc);
929929
void OpenMasternodeConnection(const CAddress& addrConnect, MasternodeProbeConn probe = MasternodeProbeConn::IsConnection)
930-
EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
930+
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex, !mutexMsgProc);
931931
bool CheckIncomingNonce(uint64_t nonce);
932932

933933
struct CFullyConnectedOnly {
@@ -1125,7 +1125,8 @@ friend class CNode;
11251125
* - Max total outbound connection capacity filled
11261126
* - Max connection capacity for type is filled
11271127
*/
1128-
bool AddConnection(const std::string& address, ConnectionType conn_type) EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
1128+
bool AddConnection(const std::string& address, ConnectionType conn_type)
1129+
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex, !mutexMsgProc);
11291130

11301131
bool AddPendingMasternode(const uint256& proTxHash);
11311132
void SetMasternodeQuorumNodes(Consensus::LLMQType llmqType, const uint256& quorumHash, const std::set<uint256>& proTxHashes);
@@ -1231,11 +1232,13 @@ friend class CNode;
12311232
const std::vector<NetWhitebindPermissions>& whiteBinds,
12321233
const std::vector<CService>& onion_binds);
12331234

1234-
void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !mutexMsgProc);
1235+
void ThreadOpenAddedConnections()
1236+
EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_unused_i2p_sessions_mutex, !mutexMsgProc);
12351237
void AddAddrFetch(const std::string& strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex);
1236-
void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !mutexMsgProc);
1238+
void ProcessAddrFetch()
1239+
EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_unused_i2p_sessions_mutex, !mutexMsgProc);
12371240
void ThreadOpenConnections(const std::vector<std::string> connect, CDeterministicMNManager& dmnman)
1238-
EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex, !mutexMsgProc);
1241+
EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex, !m_unused_i2p_sessions_mutex, !mutexMsgProc);
12391242
void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
12401243
void ThreadI2PAcceptIncoming(CMasternodeSync& mn_sync) EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
12411244
void AcceptConnection(const ListenSocket& hListenSocket, CMasternodeSync& mn_sync)
@@ -1341,7 +1344,7 @@ friend class CNode;
13411344
void ThreadDNSAddressSeed() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_nodes_mutex);
13421345
void ThreadOpenMasternodeConnections(CDeterministicMNManager& dmnman, CMasternodeMetaMan& mn_metaman,
13431346
CMasternodeSync& mn_sync)
1344-
EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_nodes_mutex, !mutexMsgProc);
1347+
EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_nodes_mutex, !m_unused_i2p_sessions_mutex, !mutexMsgProc);
13451348

13461349
uint64_t CalculateKeyedNetGroup(const CAddress& ad) const;
13471350

@@ -1357,7 +1360,8 @@ friend class CNode;
13571360
bool AlreadyConnectedToAddress(const CAddress& addr);
13581361

13591362
bool AttemptToEvictConnection();
1360-
CNode* ConnectNode(CAddress addrConnect, const char *pszDest = nullptr, bool fCountFailure = false, ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY);
1363+
CNode* ConnectNode(CAddress addrConnect, const char *pszDest = nullptr, bool fCountFailure = false, ConnectionType conn_type = ConnectionType::OUTBOUND_FULL_RELAY)
1364+
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
13611365
void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const;
13621366

13631367
void DeleteNode(CNode* pnode);
@@ -1563,6 +1567,26 @@ friend class CNode;
15631567
*/
15641568
std::vector<CService> m_onion_binds;
15651569

1570+
/**
1571+
* Mutex protecting m_i2p_sam_sessions.
1572+
*/
1573+
Mutex m_unused_i2p_sessions_mutex;
1574+
1575+
/**
1576+
* A pool of created I2P SAM transient sessions that should be used instead
1577+
* of creating new ones in order to reduce the load on the I2P network.
1578+
* Creating a session in I2P is not cheap, thus if this is not empty, then
1579+
* pick an entry from it instead of creating a new session. If connecting to
1580+
* a host fails, then the created session is put to this pool for reuse.
1581+
*/
1582+
std::queue<std::unique_ptr<i2p::sam::Session>> m_unused_i2p_sessions GUARDED_BY(m_unused_i2p_sessions_mutex);
1583+
1584+
/**
1585+
* Cap on the size of `m_unused_i2p_sessions`, to ensure it does not
1586+
* unexpectedly use too much memory.
1587+
*/
1588+
static constexpr size_t MAX_UNUSED_I2P_SESSIONS_SIZE{10};
1589+
15661590
friend struct CConnmanTest;
15671591
friend struct ConnmanTestMsg;
15681592
};

0 commit comments

Comments
 (0)