|
38 | 38 | #include <map> |
39 | 39 | #include <memory> |
40 | 40 | #include <optional> |
| 41 | +#include <queue> |
41 | 42 | #include <thread> |
42 | 43 | #include <vector> |
43 | 44 |
|
@@ -744,7 +745,7 @@ class CConnman |
744 | 745 | bool GetNetworkActive() const { return fNetworkActive; }; |
745 | 746 | bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; }; |
746 | 747 | void SetNetworkActive(bool active); |
747 | | - void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* strDest, ConnectionType conn_type); |
| 748 | + void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* strDest, ConnectionType conn_type) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex); |
748 | 749 | bool CheckIncomingNonce(uint64_t nonce); |
749 | 750 |
|
750 | 751 | bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func); |
@@ -820,7 +821,7 @@ class CConnman |
820 | 821 | * - Max total outbound connection capacity filled |
821 | 822 | * - Max connection capacity for type is filled |
822 | 823 | */ |
823 | | - bool AddConnection(const std::string& address, ConnectionType conn_type); |
| 824 | + bool AddConnection(const std::string& address, ConnectionType conn_type) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex); |
824 | 825 |
|
825 | 826 | size_t GetNodeCount(ConnectionDirection) const; |
826 | 827 | void GetNodeStats(std::vector<CNodeStats>& vstats) const; |
@@ -886,10 +887,10 @@ class CConnman |
886 | 887 | bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions); |
887 | 888 | bool InitBinds(const Options& options); |
888 | 889 |
|
889 | | - void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex); |
| 890 | + void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_unused_i2p_sessions_mutex); |
890 | 891 | void AddAddrFetch(const std::string& strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex); |
891 | | - void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex); |
892 | | - void ThreadOpenConnections(std::vector<std::string> connect) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex); |
| 892 | + void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_unused_i2p_sessions_mutex); |
| 893 | + void ThreadOpenConnections(std::vector<std::string> connect) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex, !m_unused_i2p_sessions_mutex); |
893 | 894 | void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc); |
894 | 895 | void ThreadI2PAcceptIncoming(); |
895 | 896 | void AcceptConnection(const ListenSocket& hListenSocket); |
@@ -956,7 +957,7 @@ class CConnman |
956 | 957 | bool AlreadyConnectedToAddress(const CAddress& addr); |
957 | 958 |
|
958 | 959 | bool AttemptToEvictConnection(); |
959 | | - CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type); |
| 960 | + CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex); |
960 | 961 | void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const; |
961 | 962 |
|
962 | 963 | void DeleteNode(CNode* pnode); |
@@ -1127,6 +1128,26 @@ class CConnman |
1127 | 1128 | */ |
1128 | 1129 | std::vector<CService> m_onion_binds; |
1129 | 1130 |
|
| 1131 | + /** |
| 1132 | + * Mutex protecting m_i2p_sam_sessions. |
| 1133 | + */ |
| 1134 | + Mutex m_unused_i2p_sessions_mutex; |
| 1135 | + |
| 1136 | + /** |
| 1137 | + * A pool of created I2P SAM transient sessions that should be used instead |
| 1138 | + * of creating new ones in order to reduce the load on the I2P network. |
| 1139 | + * Creating a session in I2P is not cheap, thus if this is not empty, then |
| 1140 | + * pick an entry from it instead of creating a new session. If connecting to |
| 1141 | + * a host fails, then the created session is put to this pool for reuse. |
| 1142 | + */ |
| 1143 | + std::queue<std::unique_ptr<i2p::sam::Session>> m_unused_i2p_sessions GUARDED_BY(m_unused_i2p_sessions_mutex); |
| 1144 | + |
| 1145 | + /** |
| 1146 | + * Cap on the size of `m_unused_i2p_sessions`, to ensure it does not |
| 1147 | + * unexpectedly use too much memory. |
| 1148 | + */ |
| 1149 | + static constexpr size_t MAX_UNUSED_I2P_SESSIONS_SIZE{10}; |
| 1150 | + |
1130 | 1151 | /** |
1131 | 1152 | * RAII helper to atomically create a copy of `m_nodes` and add a reference |
1132 | 1153 | * to each of the nodes. The nodes are released when this object is destroyed. |
|
0 commit comments