|
38 | 38 | #include <map>
|
39 | 39 | #include <memory>
|
40 | 40 | #include <optional>
|
| 41 | +#include <queue> |
41 | 42 | #include <thread>
|
42 | 43 | #include <unordered_set>
|
43 | 44 | #include <vector>
|
@@ -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);
|
@@ -1133,6 +1134,26 @@ class CConnman
|
1133 | 1134 | */
|
1134 | 1135 | std::vector<CService> m_onion_binds;
|
1135 | 1136 |
|
| 1137 | + /** |
| 1138 | + * Mutex protecting m_i2p_sam_sessions. |
| 1139 | + */ |
| 1140 | + Mutex m_unused_i2p_sessions_mutex; |
| 1141 | + |
| 1142 | + /** |
| 1143 | + * A pool of created I2P SAM transient sessions that should be used instead |
| 1144 | + * of creating new ones in order to reduce the load on the I2P network. |
| 1145 | + * Creating a session in I2P is not cheap, thus if this is not empty, then |
| 1146 | + * pick an entry from it instead of creating a new session. If connecting to |
| 1147 | + * a host fails, then the created session is put to this pool for reuse. |
| 1148 | + */ |
| 1149 | + std::queue<std::unique_ptr<i2p::sam::Session>> m_unused_i2p_sessions GUARDED_BY(m_unused_i2p_sessions_mutex); |
| 1150 | + |
| 1151 | + /** |
| 1152 | + * Cap on the size of `m_unused_i2p_sessions`, to ensure it does not |
| 1153 | + * unexpectedly use too much memory. |
| 1154 | + */ |
| 1155 | + static constexpr size_t MAX_UNUSED_I2P_SESSIONS_SIZE{10}; |
| 1156 | + |
1136 | 1157 | /**
|
1137 | 1158 | * RAII helper to atomically create a copy of `m_nodes` and add a reference
|
1138 | 1159 | * to each of the nodes. The nodes are released when this object is destroyed.
|
|
0 commit comments