Skip to content

Commit c76de2e

Browse files
committed
net: support overriding the proxy selection in ConnectNode()
Normally `ConnectNode()` would choose whether to use a proxy and which one. Make it possible to override this from the callers and same for `OpenNetworkConnection()` - pass down the proxy to `ConnectNode()`. Document both functions. This is useful if we want to open connections to IPv4 or IPv6 peers through the Tor SOCKS5 proxy. Also have `OpenNetworkConnection()` return whether the connection succeeded or not. This can be used when the caller needs to keep track of how many (successful) connections were opened.
1 parent 75353a0 commit c76de2e

File tree

4 files changed

+72
-14
lines changed

4 files changed

+72
-14
lines changed

src/net.cpp

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,12 @@ static CService GetBindAddress(const Sock& sock)
373373
return addr_bind;
374374
}
375375

376-
CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport)
376+
CNode* CConnman::ConnectNode(CAddress addrConnect,
377+
const char* pszDest,
378+
bool fCountFailure,
379+
ConnectionType conn_type,
380+
bool use_v2transport,
381+
const std::optional<Proxy>& proxy_override)
377382
{
378383
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
379384
assert(conn_type != ConnectionType::INBOUND);
@@ -439,7 +444,13 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
439444

440445
for (auto& target_addr: connect_to) {
441446
if (target_addr.IsValid()) {
442-
const bool use_proxy{GetProxy(target_addr.GetNetwork(), proxy)};
447+
bool use_proxy;
448+
if (proxy_override.has_value()) {
449+
use_proxy = true;
450+
proxy = proxy_override.value();
451+
} else {
452+
use_proxy = GetProxy(target_addr.GetNetwork(), proxy);
453+
}
443454
bool proxyConnectionFailed = false;
444455

445456
if (target_addr.IsI2P() && use_proxy) {
@@ -2858,7 +2869,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, std
28582869
const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(m_max_automatic_connections - 1, 2)};
28592870
// Use BIP324 transport when both us and them have NODE_V2_P2P set.
28602871
const bool use_v2transport(addrConnect.nServices & GetLocalServices() & NODE_P2P_V2);
2861-
OpenNetworkConnection(addrConnect, count_failures, std::move(grant), /*strDest=*/nullptr, conn_type, use_v2transport);
2872+
OpenNetworkConnection(addrConnect, count_failures, std::move(grant), /*pszDest=*/nullptr, conn_type, use_v2transport);
28622873
}
28632874
}
28642875
}
@@ -2967,7 +2978,13 @@ void CConnman::ThreadOpenAddedConnections()
29672978
}
29682979

29692980
// if successful, this moves the passed grant to the constructed node
2970-
void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CountingSemaphoreGrant<>&& grant_outbound, const char *pszDest, ConnectionType conn_type, bool use_v2transport)
2981+
bool CConnman::OpenNetworkConnection(const CAddress& addrConnect,
2982+
bool fCountFailure,
2983+
CountingSemaphoreGrant<>&& grant_outbound,
2984+
const char* pszDest,
2985+
ConnectionType conn_type,
2986+
bool use_v2transport,
2987+
const std::optional<Proxy>& proxy_override)
29712988
{
29722989
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
29732990
assert(conn_type != ConnectionType::INBOUND);
@@ -2976,24 +2993,24 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
29762993
// Initiate outbound network connection
29772994
//
29782995
if (m_interrupt_net->interrupted()) {
2979-
return;
2996+
return false;
29802997
}
29812998
if (!fNetworkActive) {
2982-
return;
2999+
return false;
29833000
}
29843001
if (!pszDest) {
29853002
bool banned_or_discouraged = m_banman && (m_banman->IsDiscouraged(addrConnect) || m_banman->IsBanned(addrConnect));
29863003
if (IsLocal(addrConnect) || banned_or_discouraged || AlreadyConnectedToAddress(addrConnect)) {
2987-
return;
3004+
return false;
29883005
}
29893006
} else if (AlreadyConnectedToHost(pszDest)) {
2990-
return;
3007+
return false;
29913008
}
29923009

2993-
CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type, use_v2transport);
3010+
CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type, use_v2transport, proxy_override);
29943011

29953012
if (!pnode)
2996-
return;
3013+
return false;
29973014
pnode->grantOutbound = std::move(grant_outbound);
29983015

29993016
m_msgproc->InitializeNode(*pnode, m_local_services);
@@ -3011,6 +3028,8 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
30113028
pnode->ConnectionTypeAsString().c_str(),
30123029
pnode->ConnectedThroughNetwork(),
30133030
GetNodeCount(ConnectionDirection::Out));
3031+
3032+
return true;
30143033
}
30153034

30163035
Mutex NetEventsInterface::g_msgproc_mutex;

src/net.h

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,7 +1143,28 @@ class CConnman
11431143
bool GetNetworkActive() const { return fNetworkActive; };
11441144
bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };
11451145
void SetNetworkActive(bool active);
1146-
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);
1146+
1147+
/**
1148+
* Open a new P2P connection and initialize it with the PeerManager at `m_msgproc`.
1149+
* @param[in] addrConnect Address to connect to, if `pszDest` is `nullptr`.
1150+
* @param[in] fCountFailure Increment the number of connection attempts to this address in Addrman.
1151+
* @param[in] grant_outbound Take ownership of this grant, to be released later when the connection is closed.
1152+
* @param[in] pszDest Address to resolve and connect to.
1153+
* @param[in] conn_type Type of the connection to open, must not be `ConnectionType::INBOUND`.
1154+
* @param[in] use_v2transport Use P2P encryption, (aka V2 transport, BIP324).
1155+
* @param[in] proxy_override Optional proxy to use and override normal proxy selection.
1156+
* @retval true The connection was opened successfully.
1157+
* @retval false The connection attempt failed.
1158+
*/
1159+
bool OpenNetworkConnection(const CAddress& addrConnect,
1160+
bool fCountFailure,
1161+
CountingSemaphoreGrant<>&& grant_outbound,
1162+
const char* pszDest,
1163+
ConnectionType conn_type,
1164+
bool use_v2transport,
1165+
const std::optional<Proxy>& proxy_override = std::nullopt)
1166+
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
1167+
11471168
bool CheckIncomingNonce(uint64_t nonce);
11481169
void ASMapHealthCheck();
11491170

@@ -1394,7 +1415,25 @@ class CConnman
13941415
bool AlreadyConnectedToAddress(const CNetAddr& addr) const;
13951416

13961417
bool AttemptToEvictConnection();
1397-
CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
1418+
1419+
/**
1420+
* Open a new P2P connection.
1421+
* @param[in] addrConnect Address to connect to, if `pszDest` is `nullptr`.
1422+
* @param[in] pszDest Address to resolve and connect to.
1423+
* @param[in] fCountFailure Increment the number of connection attempts to this address in Addrman.
1424+
* @param[in] conn_type Type of the connection to open, must not be `ConnectionType::INBOUND`.
1425+
* @param[in] use_v2transport Use P2P encryption, (aka V2 transport, BIP324).
1426+
* @param[in] proxy_override Optional proxy to use and override normal proxy selection.
1427+
* @return Newly created CNode object or nullptr if the connection failed.
1428+
*/
1429+
CNode* ConnectNode(CAddress addrConnect,
1430+
const char* pszDest,
1431+
bool fCountFailure,
1432+
ConnectionType conn_type,
1433+
bool use_v2transport,
1434+
const std::optional<Proxy>& proxy_override)
1435+
EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
1436+
13981437
void AddWhitelistPermissionFlags(NetPermissionFlags& flags, std::optional<CNetAddr> addr, const std::vector<NetWhitelistPermissions>& ranges) const;
13991438

14001439
void DeleteNode(CNode* pnode);

src/test/fuzz/connman.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ FUZZ_TARGET(connman, .init = initialize_connman)
177177
/*addrConnect=*/random_address,
178178
/*fCountFailure=*/fuzzed_data_provider.ConsumeBool(),
179179
/*grant_outbound=*/{},
180-
/*strDest=*/fuzzed_data_provider.ConsumeBool() ? nullptr : random_string.c_str(),
180+
/*pszDest=*/fuzzed_data_provider.ConsumeBool() ? nullptr : random_string.c_str(),
181181
/*conn_type=*/conn_type,
182182
/*use_v2transport=*/fuzzed_data_provider.ConsumeBool());
183183
},

src/test/util/net.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ bool ConnmanTestMsg::ReceiveMsgFrom(CNode& node, CSerializedNetMsg&& ser_msg) co
116116

117117
CNode* ConnmanTestMsg::ConnectNodePublic(PeerManager& peerman, const char* pszDest, ConnectionType conn_type)
118118
{
119-
CNode* node = ConnectNode(CAddress{}, pszDest, /*fCountFailure=*/false, conn_type, /*use_v2transport=*/true);
119+
CNode* node = ConnectNode(CAddress{}, pszDest, /*fCountFailure=*/false, conn_type, /*use_v2transport=*/true, /*proxy_override=*/std::nullopt);
120120
if (!node) return nullptr;
121121
node->SetCommonVersion(PROTOCOL_VERSION);
122122
peerman.InitializeNode(*node, ServiceFlags(NODE_NETWORK | NODE_WITNESS));

0 commit comments

Comments
 (0)