Skip to content

Commit

Permalink
Merge #19998: net: Add CNode::ConnectedThroughNetwork member function
Browse files Browse the repository at this point in the history
3984b78 test: Add tests for CNode::ConnectedThroughNetwork (Hennadii Stepanov)
49fba9c net: Add CNode::ConnectedThroughNetwork member function (Hennadii Stepanov)
d4dde24 net: Add CNode::m_inbound_onion data member (Hennadii Stepanov)

Pull request description:

  This PR:
  - adds `CNode::ConnectedThroughNetwork` member function
  - is based on #19991, and only last two commits belong to it
  - is required for bitcoin-core/gui#86 and #20002

ACKs for top commit:
  jonatack:
    re-ACK 3984b78 per `git diff 3989fcf 3984b78`
  laanwj:
    Code review ACK 3984b78

Tree-SHA512: 23a9c8bca8dca75113b5505fe443b294f2d42d03c98c7e34919da12d8396beb8d0ada3a58ae16e3da04b7044395f72cf9c216625afc078256cd6c897ac42bf3d
  • Loading branch information
laanwj committed Oct 12, 2020
2 parents af22322 + 3984b78 commit f79a4a8
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 10 deletions.
15 changes: 12 additions & 3 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed");
#endif

#include <algorithm>
#include <cstdint>
#include <unordered_map>

Expand Down Expand Up @@ -538,6 +539,11 @@ void CNode::SetAddrLocal(const CService& addrLocalIn) {
}
}

Network CNode::ConnectedThroughNetwork() const
{
return IsInboundConn() && m_inbound_onion ? NET_ONION : addr.GetNetClass();
}

#undef X
#define X(name) stats.name = name
void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
Expand Down Expand Up @@ -1118,7 +1124,9 @@ void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
if (NetPermissions::HasFlag(permissionFlags, PF_BLOOMFILTER)) {
nodeServices = static_cast<ServiceFlags>(nodeServices | NODE_BLOOM);
}
CNode* pnode = new CNode(id, nodeServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", ConnectionType::INBOUND);

const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
CNode* pnode = new CNode(id, nodeServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", ConnectionType::INBOUND, inbound_onion);
pnode->AddRef();
pnode->m_permissionFlags = permissionFlags;
// If this flag is present, the user probably expect that RPC and QT report it as whitelisted (backward compatibility)
Expand Down Expand Up @@ -2859,7 +2867,7 @@ int CConnman::GetBestHeight() const

unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }

CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in)
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
: nTimeConnected(GetSystemTimeInSeconds()),
addr(addrIn),
addrBind(addrBindIn),
Expand All @@ -2871,7 +2879,8 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn
nLocalHostNonce(nLocalHostNonceIn),
m_conn_type(conn_type_in),
nLocalServices(nLocalServicesIn),
nMyStartingHeight(nMyStartingHeightIn)
nMyStartingHeight(nMyStartingHeightIn),
m_inbound_onion(inbound_onion)
{
hSocket = hSocketIn;
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
Expand Down
25 changes: 24 additions & 1 deletion src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ class CConnman
LOCK(cs_vAddedNodes);
vAddedNodes = connOptions.m_added_nodes;
}
m_onion_binds = connOptions.onion_binds;
}

CConnman(uint64_t seed0, uint64_t seed1, bool network_active = true);
Expand Down Expand Up @@ -586,6 +587,12 @@ class CConnman

std::atomic<int64_t> m_next_send_inv_to_incoming{0};

/**
* A vector of -bind=<address>:<port>=onion arguments each of which is
* an address and port that are designated for incoming Tor connections.
*/
std::vector<CService> m_onion_binds;

friend struct CConnmanTest;
friend struct ConnmanTestMsg;
};
Expand Down Expand Up @@ -944,6 +951,18 @@ class CNode
assert(false);
}

/**
* Get network the peer connected through.
*
* Returns Network::NET_ONION for *inbound* onion connections,
* and CNetAddr::GetNetClass() otherwise. The latter cannot be used directly
* because it doesn't detect the former, and it's not the responsibility of
* the CNetAddr class to know the actual network a peer is connected through.
*
* @return network the peer connected through.
*/
Network ConnectedThroughNetwork() const;

protected:
mapMsgCmdSize mapSendBytesPerMsgCmd;
mapMsgCmdSize mapRecvBytesPerMsgCmd GUARDED_BY(cs_vRecv);
Expand Down Expand Up @@ -1025,7 +1044,7 @@ class CNode

std::set<uint256> orphan_work_set;

CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in);
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress &addrBindIn, const std::string &addrNameIn, ConnectionType conn_type_in, bool inbound_onion = false);
~CNode();
CNode(const CNode&) = delete;
CNode& operator=(const CNode&) = delete;
Expand Down Expand Up @@ -1063,6 +1082,10 @@ class CNode
// Our address, as reported by the peer
CService addrLocal GUARDED_BY(cs_addrLocal);
mutable RecursiveMutex cs_addrLocal;

//! Whether this peer connected via our Tor onion service.
const bool m_inbound_onion{false};

public:

NodeId GetId() const {
Expand Down
2 changes: 1 addition & 1 deletion src/netaddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ uint32_t CNetAddr::GetLinkedIPv4() const
assert(false);
}

uint32_t CNetAddr::GetNetClass() const
Network CNetAddr::GetNetClass() const
{
// Make sure that if we return NET_IPV6, then IsIPv6() is true. The callers expect that.

Expand Down
2 changes: 1 addition & 1 deletion src/netaddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class CNetAddr
std::string ToStringIP() const;
uint64_t GetHash() const;
bool GetInAddr(struct in_addr* pipv4Addr) const;
uint32_t GetNetClass() const;
Network GetNetClass() const;

//! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv4 address as a uint32.
uint32_t GetLinkedIPv4() const;
Expand Down
4 changes: 3 additions & 1 deletion src/test/fuzz/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ void test_one_input(const std::vector<uint8_t>& buffer)
fuzzed_data_provider.ConsumeIntegral<uint64_t>(),
*address_bind,
fuzzed_data_provider.ConsumeRandomLengthString(32),
fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH})};
fuzzed_data_provider.PickValueInArray({ConnectionType::INBOUND, ConnectionType::OUTBOUND_FULL_RELAY, ConnectionType::MANUAL, ConnectionType::FEELER, ConnectionType::BLOCK_RELAY, ConnectionType::ADDR_FETCH}),
fuzzed_data_provider.ConsumeBool()};
while (fuzzed_data_provider.ConsumeBool()) {
switch (fuzzed_data_provider.ConsumeIntegralInRange<int>(0, 11)) {
case 0: {
Expand Down Expand Up @@ -148,4 +149,5 @@ void test_one_input(const std::vector<uint8_t>& buffer)
fuzzed_data_provider.PickValueInArray<NetPermissionFlags>({NetPermissionFlags::PF_NONE, NetPermissionFlags::PF_BLOOMFILTER, NetPermissionFlags::PF_RELAY, NetPermissionFlags::PF_FORCERELAY, NetPermissionFlags::PF_NOBAN, NetPermissionFlags::PF_MEMPOOL, NetPermissionFlags::PF_ISIMPLICIT, NetPermissionFlags::PF_ALL}) :
static_cast<NetPermissionFlags>(fuzzed_data_provider.ConsumeIntegral<uint32_t>());
(void)node.HasPermission(net_permission_flags);
(void)node.ConnectedThroughNetwork();
}
45 changes: 42 additions & 3 deletions src/test/net_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,21 +185,60 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
std::string pszDest;

std::unique_ptr<CNode> pnode1 = MakeUnique<CNode>(id++, NODE_NETWORK, height, hSocket, addr, 0, 0, CAddress(), pszDest, ConnectionType::OUTBOUND_FULL_RELAY);
std::unique_ptr<CNode> pnode1 = MakeUnique<CNode>(
id++, NODE_NETWORK, height, hSocket, addr,
/* nKeyedNetGroupIn = */ 0,
/* nLocalHostNonceIn = */ 0,
CAddress(), pszDest, ConnectionType::OUTBOUND_FULL_RELAY);
BOOST_CHECK(pnode1->IsFullOutboundConn() == true);
BOOST_CHECK(pnode1->IsManualConn() == false);
BOOST_CHECK(pnode1->IsBlockOnlyConn() == false);
BOOST_CHECK(pnode1->IsFeelerConn() == false);
BOOST_CHECK(pnode1->IsAddrFetchConn() == false);
BOOST_CHECK(pnode1->IsInboundConn() == false);

std::unique_ptr<CNode> pnode2 = MakeUnique<CNode>(id++, NODE_NETWORK, height, hSocket, addr, 1, 1, CAddress(), pszDest, ConnectionType::INBOUND);
BOOST_CHECK_EQUAL(pnode1->ConnectedThroughNetwork(), Network::NET_IPV4);

std::unique_ptr<CNode> pnode2 = MakeUnique<CNode>(
id++, NODE_NETWORK, height, hSocket, addr,
/* nKeyedNetGroupIn = */ 1,
/* nLocalHostNonceIn = */ 1,
CAddress(), pszDest, ConnectionType::INBOUND,
/* inbound_onion = */ false);
BOOST_CHECK(pnode2->IsFullOutboundConn() == false);
BOOST_CHECK(pnode2->IsManualConn() == false);
BOOST_CHECK(pnode2->IsBlockOnlyConn() == false);
BOOST_CHECK(pnode2->IsFeelerConn() == false);
BOOST_CHECK(pnode2->IsAddrFetchConn() == false);
BOOST_CHECK(pnode2->IsInboundConn() == true);
BOOST_CHECK_EQUAL(pnode2->ConnectedThroughNetwork(), Network::NET_IPV4);

std::unique_ptr<CNode> pnode3 = MakeUnique<CNode>(
id++, NODE_NETWORK, height, hSocket, addr,
/* nKeyedNetGroupIn = */ 0,
/* nLocalHostNonceIn = */ 0,
CAddress(), pszDest, ConnectionType::OUTBOUND_FULL_RELAY,
/* inbound_onion = */ true);
BOOST_CHECK(pnode3->IsFullOutboundConn() == true);
BOOST_CHECK(pnode3->IsManualConn() == false);
BOOST_CHECK(pnode3->IsBlockOnlyConn() == false);
BOOST_CHECK(pnode3->IsFeelerConn() == false);
BOOST_CHECK(pnode3->IsAddrFetchConn() == false);
BOOST_CHECK(pnode3->IsInboundConn() == false);
BOOST_CHECK_EQUAL(pnode3->ConnectedThroughNetwork(), Network::NET_IPV4);

std::unique_ptr<CNode> pnode4 = MakeUnique<CNode>(
id++, NODE_NETWORK, height, hSocket, addr,
/* nKeyedNetGroupIn = */ 1,
/* nLocalHostNonceIn = */ 1,
CAddress(), pszDest, ConnectionType::INBOUND,
/* inbound_onion = */ true);
BOOST_CHECK(pnode4->IsFullOutboundConn() == false);
BOOST_CHECK(pnode4->IsManualConn() == false);
BOOST_CHECK(pnode4->IsBlockOnlyConn() == false);
BOOST_CHECK(pnode4->IsFeelerConn() == false);
BOOST_CHECK(pnode4->IsAddrFetchConn() == false);
BOOST_CHECK(pnode4->IsInboundConn() == true);
BOOST_CHECK_EQUAL(pnode4->ConnectedThroughNetwork(), Network::NET_ONION);
}

BOOST_AUTO_TEST_CASE(cnetaddr_basic)
Expand Down

0 comments on commit f79a4a8

Please sign in to comment.