diff --git a/src/net.cpp b/src/net.cpp index 584b4280905..c4eb0d7b652 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -373,7 +373,12 @@ static CService GetBindAddress(const Sock& sock) return addr_bind; } -CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport) +CNode* CConnman::ConnectNode(CAddress addrConnect, + const char* pszDest, + bool fCountFailure, + ConnectionType conn_type, + bool use_v2transport, + const std::optional& proxy_override) { AssertLockNotHeld(m_unused_i2p_sessions_mutex); assert(conn_type != ConnectionType::INBOUND); @@ -439,7 +444,13 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo for (auto& target_addr: connect_to) { if (target_addr.IsValid()) { - const bool use_proxy{GetProxy(target_addr.GetNetwork(), proxy)}; + bool use_proxy; + if (proxy_override.has_value()) { + use_proxy = true; + proxy = proxy_override.value(); + } else { + use_proxy = GetProxy(target_addr.GetNetwork(), proxy); + } bool proxyConnectionFailed = false; if (target_addr.IsI2P() && use_proxy) { @@ -2858,7 +2869,7 @@ void CConnman::ThreadOpenConnections(const std::vector connect, std const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(m_max_automatic_connections - 1, 2)}; // Use BIP324 transport when both us and them have NODE_V2_P2P set. const bool use_v2transport(addrConnect.nServices & GetLocalServices() & NODE_P2P_V2); - OpenNetworkConnection(addrConnect, count_failures, std::move(grant), /*strDest=*/nullptr, conn_type, use_v2transport); + OpenNetworkConnection(addrConnect, count_failures, std::move(grant), /*pszDest=*/nullptr, conn_type, use_v2transport); } } } @@ -2967,7 +2978,13 @@ void CConnman::ThreadOpenAddedConnections() } // if successful, this moves the passed grant to the constructed node -void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CountingSemaphoreGrant<>&& grant_outbound, const char *pszDest, ConnectionType conn_type, bool use_v2transport) +bool CConnman::OpenNetworkConnection(const CAddress& addrConnect, + bool fCountFailure, + CountingSemaphoreGrant<>&& grant_outbound, + const char* pszDest, + ConnectionType conn_type, + bool use_v2transport, + const std::optional& proxy_override) { AssertLockNotHeld(m_unused_i2p_sessions_mutex); assert(conn_type != ConnectionType::INBOUND); @@ -2976,24 +2993,24 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai // Initiate outbound network connection // if (m_interrupt_net->interrupted()) { - return; + return false; } if (!fNetworkActive) { - return; + return false; } if (!pszDest) { bool banned_or_discouraged = m_banman && (m_banman->IsDiscouraged(addrConnect) || m_banman->IsBanned(addrConnect)); if (IsLocal(addrConnect) || banned_or_discouraged || AlreadyConnectedToAddress(addrConnect)) { - return; + return false; } } else if (AlreadyConnectedToHost(pszDest)) { - return; + return false; } - CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type, use_v2transport); + CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type, use_v2transport, proxy_override); if (!pnode) - return; + return false; pnode->grantOutbound = std::move(grant_outbound); m_msgproc->InitializeNode(*pnode, m_local_services); @@ -3011,6 +3028,8 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai pnode->ConnectionTypeAsString().c_str(), pnode->ConnectedThroughNetwork(), GetNodeCount(ConnectionDirection::Out)); + + return true; } Mutex NetEventsInterface::g_msgproc_mutex; diff --git a/src/net.h b/src/net.h index 92aabae6404..a6a12df8cd0 100644 --- a/src/net.h +++ b/src/net.h @@ -1143,7 +1143,28 @@ public: bool GetNetworkActive() const { return fNetworkActive; }; bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; }; void SetNetworkActive(bool active); - void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CountingSemaphoreGrant<>&& grant_outbound, const char* strDest, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex); + + /** + * Open a new P2P connection and initialize it with the PeerManager at `m_msgproc`. + * @param[in] addrConnect Address to connect to, if `pszDest` is `nullptr`. + * @param[in] fCountFailure Increment the number of connection attempts to this address in Addrman. + * @param[in] grant_outbound Take ownership of this grant, to be released later when the connection is closed. + * @param[in] pszDest Address to resolve and connect to. + * @param[in] conn_type Type of the connection to open, must not be `ConnectionType::INBOUND`. + * @param[in] use_v2transport Use P2P encryption, (aka V2 transport, BIP324). + * @param[in] proxy_override Optional proxy to use and override normal proxy selection. + * @retval true The connection was opened successfully. + * @retval false The connection attempt failed. + */ + bool OpenNetworkConnection(const CAddress& addrConnect, + bool fCountFailure, + CountingSemaphoreGrant<>&& grant_outbound, + const char* pszDest, + ConnectionType conn_type, + bool use_v2transport, + const std::optional& proxy_override = std::nullopt) + EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex); + bool CheckIncomingNonce(uint64_t nonce); void ASMapHealthCheck(); @@ -1394,7 +1415,25 @@ private: bool AlreadyConnectedToAddress(const CNetAddr& addr) const; bool AttemptToEvictConnection(); - CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex); + + /** + * Open a new P2P connection. + * @param[in] addrConnect Address to connect to, if `pszDest` is `nullptr`. + * @param[in] pszDest Address to resolve and connect to. + * @param[in] fCountFailure Increment the number of connection attempts to this address in Addrman. + * @param[in] conn_type Type of the connection to open, must not be `ConnectionType::INBOUND`. + * @param[in] use_v2transport Use P2P encryption, (aka V2 transport, BIP324). + * @param[in] proxy_override Optional proxy to use and override normal proxy selection. + * @return Newly created CNode object or nullptr if the connection failed. + */ + CNode* ConnectNode(CAddress addrConnect, + const char* pszDest, + bool fCountFailure, + ConnectionType conn_type, + bool use_v2transport, + const std::optional& proxy_override) + EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex); + void AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optional addr, const std::vector& ranges) const; void DeleteNode(CNode* pnode); diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp index 100acc4a587..5f9841dab1b 100644 --- a/src/test/fuzz/connman.cpp +++ b/src/test/fuzz/connman.cpp @@ -177,7 +177,7 @@ FUZZ_TARGET(connman, .init = initialize_connman) /*addrConnect=*/random_address, /*fCountFailure=*/fuzzed_data_provider.ConsumeBool(), /*grant_outbound=*/{}, - /*strDest=*/fuzzed_data_provider.ConsumeBool() ? nullptr : random_string.c_str(), + /*pszDest=*/fuzzed_data_provider.ConsumeBool() ? nullptr : random_string.c_str(), /*conn_type=*/conn_type, /*use_v2transport=*/fuzzed_data_provider.ConsumeBool()); }, diff --git a/src/test/util/net.cpp b/src/test/util/net.cpp index 73ae996b7aa..0f59e0d6c84 100644 --- a/src/test/util/net.cpp +++ b/src/test/util/net.cpp @@ -116,7 +116,7 @@ bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg&& ser_msg) co CNode* ConnmanTestMsg::ConnectNodePublic(PeerManager& peerman, const char* pszDest, ConnectionType conn_type) { - CNode* node = ConnectNode(CAddress{}, pszDest, /*fCountFailure=*/false, conn_type, /*use_v2transport=*/true); + CNode* node = ConnectNode(CAddress{}, pszDest, /*fCountFailure=*/false, conn_type, /*use_v2transport=*/true, /*proxy_override=*/std::nullopt); if (!node) return nullptr; node->SetCommonVersion(PROTOCOL_VERSION); peerman.InitializeNode(*node, ServiceFlags(NODE_NETWORK | NODE_WITNESS));