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