mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 15:04:44 +01:00
Merge bitcoin/bitcoin#23604: Use Sock in CNode
ef5014d256
style: wrap long lines in CNode creation and add some comments (Vasil Dimov)b683491648
scripted-diff: rename CNode::cs_hSocket to CNode::m_sock_mutex (Vasil Dimov)c41a1162ac
net: use Sock in CNode (Vasil Dimov)c5dd72e146
fuzz: move FuzzedSock earlier in src/test/fuzz/util.h (Vasil Dimov) Pull request description: _This is a piece of #21878, chopped off to ease review._ Change `CNode` to use a pointer to `Sock` instead of a bare `SOCKET`. This will help mocking / testing / fuzzing more code. ACKs for top commit: jonatack: re-ACKef5014d256
changes since last review are the removal of an unneeded dtor and the addition of a style commit w0xlt: reACKef5014d
PastaPastaPasta: utACKef5014d256
, I have reviewed the code, and believe it makes sense to merge theStack: Cod-review ACKef5014d256
Tree-SHA512: 7f5414dd339cd2f16f7cbdc5fcec238d68b6d50072934aea10b901f409da28ff1ece6db6e899196616aa8127b8b25ab5b86d000bdcee58b4cadd7a3c1cf560c5
This commit is contained in:
commit
e8a3882e20
5 changed files with 230 additions and 115 deletions
76
src/net.cpp
76
src/net.cpp
|
@ -506,7 +506,16 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
||||||
if (!addr_bind.IsValid()) {
|
if (!addr_bind.IsValid()) {
|
||||||
addr_bind = GetBindAddress(sock->Get());
|
addr_bind = GetBindAddress(sock->Get());
|
||||||
}
|
}
|
||||||
CNode* pnode = new CNode(id, nLocalServices, sock->Release(), addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type, /* inbound_onion */ false);
|
CNode* pnode = new CNode(id,
|
||||||
|
nLocalServices,
|
||||||
|
std::move(sock),
|
||||||
|
addrConnect,
|
||||||
|
CalculateKeyedNetGroup(addrConnect),
|
||||||
|
nonce,
|
||||||
|
addr_bind,
|
||||||
|
pszDest ? pszDest : "",
|
||||||
|
conn_type,
|
||||||
|
/*inbound_onion=*/false);
|
||||||
pnode->AddRef();
|
pnode->AddRef();
|
||||||
|
|
||||||
// We're making a new connection, harvest entropy from the time (and our peer count)
|
// We're making a new connection, harvest entropy from the time (and our peer count)
|
||||||
|
@ -518,11 +527,10 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
||||||
void CNode::CloseSocketDisconnect()
|
void CNode::CloseSocketDisconnect()
|
||||||
{
|
{
|
||||||
fDisconnect = true;
|
fDisconnect = true;
|
||||||
LOCK(cs_hSocket);
|
LOCK(m_sock_mutex);
|
||||||
if (hSocket != INVALID_SOCKET)
|
if (m_sock) {
|
||||||
{
|
|
||||||
LogPrint(BCLog::NET, "disconnecting peer=%d\n", id);
|
LogPrint(BCLog::NET, "disconnecting peer=%d\n", id);
|
||||||
CloseSocket(hSocket);
|
m_sock.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,10 +810,11 @@ size_t CConnman::SocketSendData(CNode& node) const
|
||||||
assert(data.size() > node.nSendOffset);
|
assert(data.size() > node.nSendOffset);
|
||||||
int nBytes = 0;
|
int nBytes = 0;
|
||||||
{
|
{
|
||||||
LOCK(node.cs_hSocket);
|
LOCK(node.m_sock_mutex);
|
||||||
if (node.hSocket == INVALID_SOCKET)
|
if (!node.m_sock) {
|
||||||
break;
|
break;
|
||||||
nBytes = send(node.hSocket, reinterpret_cast<const char*>(data.data()) + node.nSendOffset, data.size() - node.nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
|
}
|
||||||
|
nBytes = node.m_sock->Send(reinterpret_cast<const char*>(data.data()) + node.nSendOffset, data.size() - node.nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
|
||||||
}
|
}
|
||||||
if (nBytes > 0) {
|
if (nBytes > 0) {
|
||||||
node.m_last_send = GetTime<std::chrono::seconds>();
|
node.m_last_send = GetTime<std::chrono::seconds>();
|
||||||
|
@ -1200,7 +1209,16 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
|
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, sock->Release(), addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", ConnectionType::INBOUND, inbound_onion);
|
CNode* pnode = new CNode(id,
|
||||||
|
nodeServices,
|
||||||
|
std::move(sock),
|
||||||
|
addr,
|
||||||
|
CalculateKeyedNetGroup(addr),
|
||||||
|
nonce,
|
||||||
|
addr_bind,
|
||||||
|
/*addrNameIn=*/"",
|
||||||
|
ConnectionType::INBOUND,
|
||||||
|
inbound_onion);
|
||||||
pnode->AddRef();
|
pnode->AddRef();
|
||||||
pnode->m_permissionFlags = permissionFlags;
|
pnode->m_permissionFlags = permissionFlags;
|
||||||
pnode->m_prefer_evict = discouraged;
|
pnode->m_prefer_evict = discouraged;
|
||||||
|
@ -1384,17 +1402,18 @@ bool CConnman::GenerateSelectSet(const std::vector<CNode*>& nodes,
|
||||||
select_send = !pnode->vSendMsg.empty();
|
select_send = !pnode->vSendMsg.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK(pnode->cs_hSocket);
|
LOCK(pnode->m_sock_mutex);
|
||||||
if (pnode->hSocket == INVALID_SOCKET)
|
if (!pnode->m_sock) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
error_set.insert(pnode->hSocket);
|
error_set.insert(pnode->m_sock->Get());
|
||||||
if (select_send) {
|
if (select_send) {
|
||||||
send_set.insert(pnode->hSocket);
|
send_set.insert(pnode->m_sock->Get());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (select_recv) {
|
if (select_recv) {
|
||||||
recv_set.insert(pnode->hSocket);
|
recv_set.insert(pnode->m_sock->Get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1564,12 +1583,13 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
|
||||||
bool sendSet = false;
|
bool sendSet = false;
|
||||||
bool errorSet = false;
|
bool errorSet = false;
|
||||||
{
|
{
|
||||||
LOCK(pnode->cs_hSocket);
|
LOCK(pnode->m_sock_mutex);
|
||||||
if (pnode->hSocket == INVALID_SOCKET)
|
if (!pnode->m_sock) {
|
||||||
continue;
|
continue;
|
||||||
recvSet = recv_set.count(pnode->hSocket) > 0;
|
}
|
||||||
sendSet = send_set.count(pnode->hSocket) > 0;
|
recvSet = recv_set.count(pnode->m_sock->Get()) > 0;
|
||||||
errorSet = error_set.count(pnode->hSocket) > 0;
|
sendSet = send_set.count(pnode->m_sock->Get()) > 0;
|
||||||
|
errorSet = error_set.count(pnode->m_sock->Get()) > 0;
|
||||||
}
|
}
|
||||||
if (recvSet || errorSet)
|
if (recvSet || errorSet)
|
||||||
{
|
{
|
||||||
|
@ -1577,10 +1597,11 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
|
||||||
uint8_t pchBuf[0x10000];
|
uint8_t pchBuf[0x10000];
|
||||||
int nBytes = 0;
|
int nBytes = 0;
|
||||||
{
|
{
|
||||||
LOCK(pnode->cs_hSocket);
|
LOCK(pnode->m_sock_mutex);
|
||||||
if (pnode->hSocket == INVALID_SOCKET)
|
if (!pnode->m_sock) {
|
||||||
continue;
|
continue;
|
||||||
nBytes = recv(pnode->hSocket, (char*)pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
|
}
|
||||||
|
nBytes = pnode->m_sock->Recv(pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
|
||||||
}
|
}
|
||||||
if (nBytes > 0)
|
if (nBytes > 0)
|
||||||
{
|
{
|
||||||
|
@ -2965,8 +2986,9 @@ ServiceFlags CConnman::GetLocalServices() const
|
||||||
|
|
||||||
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
|
unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
|
||||||
|
|
||||||
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, 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)
|
CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, std::shared_ptr<Sock> sock, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion)
|
||||||
: m_connected{GetTime<std::chrono::seconds>()},
|
: m_sock{sock},
|
||||||
|
m_connected{GetTime<std::chrono::seconds>()},
|
||||||
addr(addrIn),
|
addr(addrIn),
|
||||||
addrBind(addrBindIn),
|
addrBind(addrBindIn),
|
||||||
m_addr_name{addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn},
|
m_addr_name{addrNameIn.empty() ? addr.ToStringIPPort() : addrNameIn},
|
||||||
|
@ -2978,7 +3000,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const
|
||||||
nLocalServices(nLocalServicesIn)
|
nLocalServices(nLocalServicesIn)
|
||||||
{
|
{
|
||||||
if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND);
|
if (inbound_onion) assert(conn_type_in == ConnectionType::INBOUND);
|
||||||
hSocket = hSocketIn;
|
|
||||||
if (conn_type_in != ConnectionType::BLOCK_RELAY) {
|
if (conn_type_in != ConnectionType::BLOCK_RELAY) {
|
||||||
m_tx_relay = std::make_unique<TxRelay>();
|
m_tx_relay = std::make_unique<TxRelay>();
|
||||||
}
|
}
|
||||||
|
@ -2997,11 +3018,6 @@ CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, SOCKET hSocketIn, const
|
||||||
m_serializer = std::make_unique<V1TransportSerializer>(V1TransportSerializer());
|
m_serializer = std::make_unique<V1TransportSerializer>(V1TransportSerializer());
|
||||||
}
|
}
|
||||||
|
|
||||||
CNode::~CNode()
|
|
||||||
{
|
|
||||||
CloseSocket(hSocket);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CConnman::NodeFullyConnected(const CNode* pnode)
|
bool CConnman::NodeFullyConnected(const CNode* pnode)
|
||||||
{
|
{
|
||||||
return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect;
|
return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect;
|
||||||
|
|
17
src/net.h
17
src/net.h
|
@ -402,7 +402,17 @@ public:
|
||||||
|
|
||||||
NetPermissionFlags m_permissionFlags{NetPermissionFlags::None};
|
NetPermissionFlags m_permissionFlags{NetPermissionFlags::None};
|
||||||
std::atomic<ServiceFlags> nServices{NODE_NONE};
|
std::atomic<ServiceFlags> nServices{NODE_NONE};
|
||||||
SOCKET hSocket GUARDED_BY(cs_hSocket);
|
|
||||||
|
/**
|
||||||
|
* Socket used for communication with the node.
|
||||||
|
* May not own a Sock object (after `CloseSocketDisconnect()` or during tests).
|
||||||
|
* `shared_ptr` (instead of `unique_ptr`) is used to avoid premature close of
|
||||||
|
* the underlying file descriptor by one thread while another thread is
|
||||||
|
* poll(2)-ing it for activity.
|
||||||
|
* @see https://github.com/bitcoin/bitcoin/issues/21744 for details.
|
||||||
|
*/
|
||||||
|
std::shared_ptr<Sock> m_sock GUARDED_BY(m_sock_mutex);
|
||||||
|
|
||||||
/** Total size of all vSendMsg entries */
|
/** Total size of all vSendMsg entries */
|
||||||
size_t nSendSize GUARDED_BY(cs_vSend){0};
|
size_t nSendSize GUARDED_BY(cs_vSend){0};
|
||||||
/** Offset inside the first vSendMsg already sent */
|
/** Offset inside the first vSendMsg already sent */
|
||||||
|
@ -410,7 +420,7 @@ public:
|
||||||
uint64_t nSendBytes GUARDED_BY(cs_vSend){0};
|
uint64_t nSendBytes GUARDED_BY(cs_vSend){0};
|
||||||
std::deque<std::vector<unsigned char>> vSendMsg GUARDED_BY(cs_vSend);
|
std::deque<std::vector<unsigned char>> vSendMsg GUARDED_BY(cs_vSend);
|
||||||
Mutex cs_vSend;
|
Mutex cs_vSend;
|
||||||
Mutex cs_hSocket;
|
Mutex m_sock_mutex;
|
||||||
Mutex cs_vRecv;
|
Mutex cs_vRecv;
|
||||||
|
|
||||||
RecursiveMutex cs_vProcessMsg;
|
RecursiveMutex cs_vProcessMsg;
|
||||||
|
@ -578,8 +588,7 @@ public:
|
||||||
* criterium in CConnman::AttemptToEvictConnection. */
|
* criterium in CConnman::AttemptToEvictConnection. */
|
||||||
std::atomic<std::chrono::microseconds> m_min_ping_time{std::chrono::microseconds::max()};
|
std::atomic<std::chrono::microseconds> m_min_ping_time{std::chrono::microseconds::max()};
|
||||||
|
|
||||||
CNode(NodeId id, ServiceFlags nLocalServicesIn, 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);
|
CNode(NodeId id, ServiceFlags nLocalServicesIn, std::shared_ptr<Sock> sock, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in, bool inbound_onion);
|
||||||
~CNode();
|
|
||||||
CNode(const CNode&) = delete;
|
CNode(const CNode&) = delete;
|
||||||
CNode& operator=(const CNode&) = delete;
|
CNode& operator=(const CNode&) = delete;
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,16 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
|
||||||
|
|
||||||
// Mock an outbound peer
|
// Mock an outbound peer
|
||||||
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
|
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
|
||||||
CNode dummyNode1(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr1, /*nKeyedNetGroupIn=*/0, /*nLocalHostNonceIn=*/0, CAddress(), /*addrNameIn=*/"", ConnectionType::OUTBOUND_FULL_RELAY, /*inbound_onion=*/false);
|
CNode dummyNode1{id++,
|
||||||
|
ServiceFlags(NODE_NETWORK | NODE_WITNESS),
|
||||||
|
/*sock=*/nullptr,
|
||||||
|
addr1,
|
||||||
|
/*nKeyedNetGroupIn=*/0,
|
||||||
|
/*nLocalHostNonceIn=*/0,
|
||||||
|
CAddress(),
|
||||||
|
/*addrNameIn=*/"",
|
||||||
|
ConnectionType::OUTBOUND_FULL_RELAY,
|
||||||
|
/*inbound_onion=*/false};
|
||||||
dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
|
dummyNode1.SetCommonVersion(PROTOCOL_VERSION);
|
||||||
|
|
||||||
peerLogic->InitializeNode(&dummyNode1);
|
peerLogic->InitializeNode(&dummyNode1);
|
||||||
|
@ -108,7 +117,16 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
|
||||||
static void AddRandomOutboundPeer(std::vector<CNode*>& vNodes, PeerManager& peerLogic, ConnmanTestMsg& connman, ConnectionType connType)
|
static void AddRandomOutboundPeer(std::vector<CNode*>& vNodes, PeerManager& peerLogic, ConnmanTestMsg& connman, ConnectionType connType)
|
||||||
{
|
{
|
||||||
CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
|
CAddress addr(ip(g_insecure_rand_ctx.randbits(32)), NODE_NONE);
|
||||||
vNodes.emplace_back(new CNode(id++, ServiceFlags(NODE_NETWORK | NODE_WITNESS), INVALID_SOCKET, addr, /*nKeyedNetGroupIn=*/0, /*nLocalHostNonceIn=*/0, CAddress(), /*addrNameIn=*/"", connType, /*inbound_onion=*/false));
|
vNodes.emplace_back(new CNode{id++,
|
||||||
|
ServiceFlags(NODE_NETWORK | NODE_WITNESS),
|
||||||
|
/*sock=*/nullptr,
|
||||||
|
addr,
|
||||||
|
/*nKeyedNetGroupIn=*/0,
|
||||||
|
/*nLocalHostNonceIn=*/0,
|
||||||
|
CAddress(),
|
||||||
|
/*addrNameIn=*/"",
|
||||||
|
connType,
|
||||||
|
/*inbound_onion=*/false});
|
||||||
CNode &node = *vNodes.back();
|
CNode &node = *vNodes.back();
|
||||||
node.SetCommonVersion(PROTOCOL_VERSION);
|
node.SetCommonVersion(PROTOCOL_VERSION);
|
||||||
|
|
||||||
|
@ -279,9 +297,16 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
|
||||||
std::array<CNode*, 3> nodes;
|
std::array<CNode*, 3> nodes;
|
||||||
|
|
||||||
banman->ClearBanned();
|
banman->ClearBanned();
|
||||||
nodes[0] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[0], /*nKeyedNetGroupIn=*/0,
|
nodes[0] = new CNode{id++,
|
||||||
/*nLocalHostNonceIn=*/0, CAddress(), /*addrNameIn=*/"",
|
NODE_NETWORK,
|
||||||
ConnectionType::INBOUND, /*inbound_onion=*/false};
|
/*sock=*/nullptr,
|
||||||
|
addr[0],
|
||||||
|
/*nKeyedNetGroupIn=*/0,
|
||||||
|
/*nLocalHostNonceIn=*/0,
|
||||||
|
CAddress(),
|
||||||
|
/*addrNameIn=*/"",
|
||||||
|
ConnectionType::INBOUND,
|
||||||
|
/*inbound_onion=*/false};
|
||||||
nodes[0]->SetCommonVersion(PROTOCOL_VERSION);
|
nodes[0]->SetCommonVersion(PROTOCOL_VERSION);
|
||||||
peerLogic->InitializeNode(nodes[0]);
|
peerLogic->InitializeNode(nodes[0]);
|
||||||
nodes[0]->fSuccessfullyConnected = true;
|
nodes[0]->fSuccessfullyConnected = true;
|
||||||
|
@ -295,9 +320,16 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
|
||||||
BOOST_CHECK(nodes[0]->fDisconnect);
|
BOOST_CHECK(nodes[0]->fDisconnect);
|
||||||
BOOST_CHECK(!banman->IsDiscouraged(other_addr)); // Different address, not discouraged
|
BOOST_CHECK(!banman->IsDiscouraged(other_addr)); // Different address, not discouraged
|
||||||
|
|
||||||
nodes[1] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[1], /*nKeyedNetGroupIn=*/1,
|
nodes[1] = new CNode{id++,
|
||||||
/*nLocalHostNonceIn=*/1, CAddress(), /*addrNameIn=*/"",
|
NODE_NETWORK,
|
||||||
ConnectionType::INBOUND, /*inbound_onion=*/false};
|
/*sock=*/nullptr,
|
||||||
|
addr[1],
|
||||||
|
/*nKeyedNetGroupIn=*/1,
|
||||||
|
/*nLocalHostNonceIn=*/1,
|
||||||
|
CAddress(),
|
||||||
|
/*addrNameIn=*/"",
|
||||||
|
ConnectionType::INBOUND,
|
||||||
|
/*inbound_onion=*/false};
|
||||||
nodes[1]->SetCommonVersion(PROTOCOL_VERSION);
|
nodes[1]->SetCommonVersion(PROTOCOL_VERSION);
|
||||||
peerLogic->InitializeNode(nodes[1]);
|
peerLogic->InitializeNode(nodes[1]);
|
||||||
nodes[1]->fSuccessfullyConnected = true;
|
nodes[1]->fSuccessfullyConnected = true;
|
||||||
|
@ -326,9 +358,16 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
|
||||||
|
|
||||||
// Make sure non-IP peers are discouraged and disconnected properly.
|
// Make sure non-IP peers are discouraged and disconnected properly.
|
||||||
|
|
||||||
nodes[2] = new CNode{id++, NODE_NETWORK, INVALID_SOCKET, addr[2], /*nKeyedNetGroupIn=*/1,
|
nodes[2] = new CNode{id++,
|
||||||
/*nLocalHostNonceIn=*/1, CAddress(), /*addrNameIn=*/"",
|
NODE_NETWORK,
|
||||||
ConnectionType::OUTBOUND_FULL_RELAY, /*inbound_onion=*/false};
|
/*sock=*/nullptr,
|
||||||
|
addr[2],
|
||||||
|
/*nKeyedNetGroupIn=*/1,
|
||||||
|
/*nLocalHostNonceIn=*/1,
|
||||||
|
CAddress(),
|
||||||
|
/*addrNameIn=*/"",
|
||||||
|
ConnectionType::OUTBOUND_FULL_RELAY,
|
||||||
|
/*inbound_onion=*/false};
|
||||||
nodes[2]->SetCommonVersion(PROTOCOL_VERSION);
|
nodes[2]->SetCommonVersion(PROTOCOL_VERSION);
|
||||||
peerLogic->InitializeNode(nodes[2]);
|
peerLogic->InitializeNode(nodes[2]);
|
||||||
nodes[2]->fSuccessfullyConnected = true;
|
nodes[2]->fSuccessfullyConnected = true;
|
||||||
|
@ -364,7 +403,16 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
|
||||||
SetMockTime(nStartTime); // Overrides future calls to GetTime()
|
SetMockTime(nStartTime); // Overrides future calls to GetTime()
|
||||||
|
|
||||||
CAddress addr(ip(0xa0b0c001), NODE_NONE);
|
CAddress addr(ip(0xa0b0c001), NODE_NONE);
|
||||||
CNode dummyNode(id++, NODE_NETWORK, INVALID_SOCKET, addr, /*nKeyedNetGroupIn=*/4, /*nLocalHostNonceIn=*/4, CAddress(), /*addrNameIn=*/"", ConnectionType::INBOUND, /*inbound_onion=*/false);
|
CNode dummyNode{id++,
|
||||||
|
NODE_NETWORK,
|
||||||
|
/*sock=*/nullptr,
|
||||||
|
addr,
|
||||||
|
/*nKeyedNetGroupIn=*/4,
|
||||||
|
/*nLocalHostNonceIn=*/4,
|
||||||
|
CAddress(),
|
||||||
|
/*addrNameIn=*/"",
|
||||||
|
ConnectionType::INBOUND,
|
||||||
|
/*inbound_onion=*/false};
|
||||||
dummyNode.SetCommonVersion(PROTOCOL_VERSION);
|
dummyNode.SetCommonVersion(PROTOCOL_VERSION);
|
||||||
peerLogic->InitializeNode(&dummyNode);
|
peerLogic->InitializeNode(&dummyNode);
|
||||||
dummyNode.fSuccessfullyConnected = true;
|
dummyNode.fSuccessfullyConnected = true;
|
||||||
|
|
|
@ -38,6 +38,46 @@
|
||||||
|
|
||||||
class PeerManager;
|
class PeerManager;
|
||||||
|
|
||||||
|
class FuzzedSock : public Sock
|
||||||
|
{
|
||||||
|
FuzzedDataProvider& m_fuzzed_data_provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data to return when `MSG_PEEK` is used as a `Recv()` flag.
|
||||||
|
* If `MSG_PEEK` is used, then our `Recv()` returns some random data as usual, but on the next
|
||||||
|
* `Recv()` call we must return the same data, thus we remember it here.
|
||||||
|
*/
|
||||||
|
mutable std::optional<uint8_t> m_peek_data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FuzzedSock(FuzzedDataProvider& fuzzed_data_provider);
|
||||||
|
|
||||||
|
~FuzzedSock() override;
|
||||||
|
|
||||||
|
FuzzedSock& operator=(Sock&& other) override;
|
||||||
|
|
||||||
|
void Reset() override;
|
||||||
|
|
||||||
|
ssize_t Send(const void* data, size_t len, int flags) const override;
|
||||||
|
|
||||||
|
ssize_t Recv(void* buf, size_t len, int flags) const override;
|
||||||
|
|
||||||
|
int Connect(const sockaddr*, socklen_t) const override;
|
||||||
|
|
||||||
|
std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
|
||||||
|
|
||||||
|
int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override;
|
||||||
|
|
||||||
|
bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override;
|
||||||
|
|
||||||
|
bool IsConnected(std::string& errmsg) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] inline FuzzedSock ConsumeSock(FuzzedDataProvider& fuzzed_data_provider)
|
||||||
|
{
|
||||||
|
return FuzzedSock{fuzzed_data_provider};
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... Callables>
|
template <typename... Callables>
|
||||||
size_t CallOneOf(FuzzedDataProvider& fuzzed_data_provider, Callables... callables)
|
size_t CallOneOf(FuzzedDataProvider& fuzzed_data_provider, Callables... callables)
|
||||||
{
|
{
|
||||||
|
@ -250,7 +290,7 @@ auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<N
|
||||||
{
|
{
|
||||||
const NodeId node_id = node_id_in.value_or(fuzzed_data_provider.ConsumeIntegralInRange<NodeId>(0, std::numeric_limits<NodeId>::max()));
|
const NodeId node_id = node_id_in.value_or(fuzzed_data_provider.ConsumeIntegralInRange<NodeId>(0, std::numeric_limits<NodeId>::max()));
|
||||||
const ServiceFlags local_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS);
|
const ServiceFlags local_services = ConsumeWeakEnum(fuzzed_data_provider, ALL_SERVICE_FLAGS);
|
||||||
const SOCKET socket = INVALID_SOCKET;
|
const auto sock = std::make_shared<FuzzedSock>(fuzzed_data_provider);
|
||||||
const CAddress address = ConsumeAddress(fuzzed_data_provider);
|
const CAddress address = ConsumeAddress(fuzzed_data_provider);
|
||||||
const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
|
const uint64_t keyed_net_group = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
|
||||||
const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
|
const uint64_t local_host_nonce = fuzzed_data_provider.ConsumeIntegral<uint64_t>();
|
||||||
|
@ -259,9 +299,27 @@ auto ConsumeNode(FuzzedDataProvider& fuzzed_data_provider, const std::optional<N
|
||||||
const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES);
|
const ConnectionType conn_type = fuzzed_data_provider.PickValueInArray(ALL_CONNECTION_TYPES);
|
||||||
const bool inbound_onion{conn_type == ConnectionType::INBOUND ? fuzzed_data_provider.ConsumeBool() : false};
|
const bool inbound_onion{conn_type == ConnectionType::INBOUND ? fuzzed_data_provider.ConsumeBool() : false};
|
||||||
if constexpr (ReturnUniquePtr) {
|
if constexpr (ReturnUniquePtr) {
|
||||||
return std::make_unique<CNode>(node_id, local_services, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion);
|
return std::make_unique<CNode>(node_id,
|
||||||
|
local_services,
|
||||||
|
sock,
|
||||||
|
address,
|
||||||
|
keyed_net_group,
|
||||||
|
local_host_nonce,
|
||||||
|
addr_bind,
|
||||||
|
addr_name,
|
||||||
|
conn_type,
|
||||||
|
inbound_onion);
|
||||||
} else {
|
} else {
|
||||||
return CNode{node_id, local_services, socket, address, keyed_net_group, local_host_nonce, addr_bind, addr_name, conn_type, inbound_onion};
|
return CNode{node_id,
|
||||||
|
local_services,
|
||||||
|
sock,
|
||||||
|
address,
|
||||||
|
keyed_net_group,
|
||||||
|
local_host_nonce,
|
||||||
|
addr_bind,
|
||||||
|
addr_name,
|
||||||
|
conn_type,
|
||||||
|
inbound_onion};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, const std::optional<NodeId>& node_id_in = std::nullopt) { return ConsumeNode<true>(fdp, node_id_in); }
|
inline std::unique_ptr<CNode> ConsumeNodeAsUniquePtr(FuzzedDataProvider& fdp, const std::optional<NodeId>& node_id_in = std::nullopt) { return ConsumeNode<true>(fdp, node_id_in); }
|
||||||
|
@ -373,44 +431,4 @@ void ReadFromStream(FuzzedDataProvider& fuzzed_data_provider, Stream& stream) no
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FuzzedSock : public Sock
|
|
||||||
{
|
|
||||||
FuzzedDataProvider& m_fuzzed_data_provider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data to return when `MSG_PEEK` is used as a `Recv()` flag.
|
|
||||||
* If `MSG_PEEK` is used, then our `Recv()` returns some random data as usual, but on the next
|
|
||||||
* `Recv()` call we must return the same data, thus we remember it here.
|
|
||||||
*/
|
|
||||||
mutable std::optional<uint8_t> m_peek_data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FuzzedSock(FuzzedDataProvider& fuzzed_data_provider);
|
|
||||||
|
|
||||||
~FuzzedSock() override;
|
|
||||||
|
|
||||||
FuzzedSock& operator=(Sock&& other) override;
|
|
||||||
|
|
||||||
void Reset() override;
|
|
||||||
|
|
||||||
ssize_t Send(const void* data, size_t len, int flags) const override;
|
|
||||||
|
|
||||||
ssize_t Recv(void* buf, size_t len, int flags) const override;
|
|
||||||
|
|
||||||
int Connect(const sockaddr*, socklen_t) const override;
|
|
||||||
|
|
||||||
std::unique_ptr<Sock> Accept(sockaddr* addr, socklen_t* addr_len) const override;
|
|
||||||
|
|
||||||
int GetSockOpt(int level, int opt_name, void* opt_val, socklen_t* opt_len) const override;
|
|
||||||
|
|
||||||
bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override;
|
|
||||||
|
|
||||||
bool IsConnected(std::string& errmsg) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
[[nodiscard]] inline FuzzedSock ConsumeSock(FuzzedDataProvider& fuzzed_data_provider)
|
|
||||||
{
|
|
||||||
return FuzzedSock{fuzzed_data_provider};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // BITCOIN_TEST_FUZZ_UTIL_H
|
#endif // BITCOIN_TEST_FUZZ_UTIL_H
|
||||||
|
|
|
@ -43,7 +43,6 @@ BOOST_AUTO_TEST_CASE(cnode_listen_port)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
||||||
{
|
{
|
||||||
SOCKET hSocket = INVALID_SOCKET;
|
|
||||||
NodeId id = 0;
|
NodeId id = 0;
|
||||||
|
|
||||||
in_addr ipv4Addr;
|
in_addr ipv4Addr;
|
||||||
|
@ -52,12 +51,16 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
||||||
CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
|
CAddress addr = CAddress(CService(ipv4Addr, 7777), NODE_NETWORK);
|
||||||
std::string pszDest;
|
std::string pszDest;
|
||||||
|
|
||||||
std::unique_ptr<CNode> pnode1 = std::make_unique<CNode>(
|
std::unique_ptr<CNode> pnode1 = std::make_unique<CNode>(id++,
|
||||||
id++, NODE_NETWORK, hSocket, addr,
|
NODE_NETWORK,
|
||||||
/* nKeyedNetGroupIn = */ 0,
|
/*sock=*/nullptr,
|
||||||
/* nLocalHostNonceIn = */ 0,
|
addr,
|
||||||
CAddress(), pszDest, ConnectionType::OUTBOUND_FULL_RELAY,
|
/*nKeyedNetGroupIn=*/0,
|
||||||
/* inbound_onion = */ false);
|
/*nLocalHostNonceIn=*/0,
|
||||||
|
CAddress(),
|
||||||
|
pszDest,
|
||||||
|
ConnectionType::OUTBOUND_FULL_RELAY,
|
||||||
|
/*inbound_onion=*/false);
|
||||||
BOOST_CHECK(pnode1->IsFullOutboundConn() == true);
|
BOOST_CHECK(pnode1->IsFullOutboundConn() == true);
|
||||||
BOOST_CHECK(pnode1->IsManualConn() == false);
|
BOOST_CHECK(pnode1->IsManualConn() == false);
|
||||||
BOOST_CHECK(pnode1->IsBlockOnlyConn() == false);
|
BOOST_CHECK(pnode1->IsBlockOnlyConn() == false);
|
||||||
|
@ -67,12 +70,16 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
||||||
BOOST_CHECK(pnode1->m_inbound_onion == false);
|
BOOST_CHECK(pnode1->m_inbound_onion == false);
|
||||||
BOOST_CHECK_EQUAL(pnode1->ConnectedThroughNetwork(), Network::NET_IPV4);
|
BOOST_CHECK_EQUAL(pnode1->ConnectedThroughNetwork(), Network::NET_IPV4);
|
||||||
|
|
||||||
std::unique_ptr<CNode> pnode2 = std::make_unique<CNode>(
|
std::unique_ptr<CNode> pnode2 = std::make_unique<CNode>(id++,
|
||||||
id++, NODE_NETWORK, hSocket, addr,
|
NODE_NETWORK,
|
||||||
/* nKeyedNetGroupIn = */ 1,
|
/*sock=*/nullptr,
|
||||||
/* nLocalHostNonceIn = */ 1,
|
addr,
|
||||||
CAddress(), pszDest, ConnectionType::INBOUND,
|
/*nKeyedNetGroupIn=*/1,
|
||||||
/* inbound_onion = */ false);
|
/*nLocalHostNonceIn=*/1,
|
||||||
|
CAddress(),
|
||||||
|
pszDest,
|
||||||
|
ConnectionType::INBOUND,
|
||||||
|
/*inbound_onion=*/false);
|
||||||
BOOST_CHECK(pnode2->IsFullOutboundConn() == false);
|
BOOST_CHECK(pnode2->IsFullOutboundConn() == false);
|
||||||
BOOST_CHECK(pnode2->IsManualConn() == false);
|
BOOST_CHECK(pnode2->IsManualConn() == false);
|
||||||
BOOST_CHECK(pnode2->IsBlockOnlyConn() == false);
|
BOOST_CHECK(pnode2->IsBlockOnlyConn() == false);
|
||||||
|
@ -82,12 +89,16 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
||||||
BOOST_CHECK(pnode2->m_inbound_onion == false);
|
BOOST_CHECK(pnode2->m_inbound_onion == false);
|
||||||
BOOST_CHECK_EQUAL(pnode2->ConnectedThroughNetwork(), Network::NET_IPV4);
|
BOOST_CHECK_EQUAL(pnode2->ConnectedThroughNetwork(), Network::NET_IPV4);
|
||||||
|
|
||||||
std::unique_ptr<CNode> pnode3 = std::make_unique<CNode>(
|
std::unique_ptr<CNode> pnode3 = std::make_unique<CNode>(id++,
|
||||||
id++, NODE_NETWORK, hSocket, addr,
|
NODE_NETWORK,
|
||||||
/* nKeyedNetGroupIn = */ 0,
|
/*sock=*/nullptr,
|
||||||
/* nLocalHostNonceIn = */ 0,
|
addr,
|
||||||
CAddress(), pszDest, ConnectionType::OUTBOUND_FULL_RELAY,
|
/*nKeyedNetGroupIn=*/0,
|
||||||
/* inbound_onion = */ false);
|
/*nLocalHostNonceIn=*/0,
|
||||||
|
CAddress(),
|
||||||
|
pszDest,
|
||||||
|
ConnectionType::OUTBOUND_FULL_RELAY,
|
||||||
|
/*inbound_onion=*/false);
|
||||||
BOOST_CHECK(pnode3->IsFullOutboundConn() == true);
|
BOOST_CHECK(pnode3->IsFullOutboundConn() == true);
|
||||||
BOOST_CHECK(pnode3->IsManualConn() == false);
|
BOOST_CHECK(pnode3->IsManualConn() == false);
|
||||||
BOOST_CHECK(pnode3->IsBlockOnlyConn() == false);
|
BOOST_CHECK(pnode3->IsBlockOnlyConn() == false);
|
||||||
|
@ -97,12 +108,16 @@ BOOST_AUTO_TEST_CASE(cnode_simple_test)
|
||||||
BOOST_CHECK(pnode3->m_inbound_onion == false);
|
BOOST_CHECK(pnode3->m_inbound_onion == false);
|
||||||
BOOST_CHECK_EQUAL(pnode3->ConnectedThroughNetwork(), Network::NET_IPV4);
|
BOOST_CHECK_EQUAL(pnode3->ConnectedThroughNetwork(), Network::NET_IPV4);
|
||||||
|
|
||||||
std::unique_ptr<CNode> pnode4 = std::make_unique<CNode>(
|
std::unique_ptr<CNode> pnode4 = std::make_unique<CNode>(id++,
|
||||||
id++, NODE_NETWORK, hSocket, addr,
|
NODE_NETWORK,
|
||||||
/* nKeyedNetGroupIn = */ 1,
|
/*sock=*/nullptr,
|
||||||
/* nLocalHostNonceIn = */ 1,
|
addr,
|
||||||
CAddress(), pszDest, ConnectionType::INBOUND,
|
/*nKeyedNetGroupIn=*/1,
|
||||||
/* inbound_onion = */ true);
|
/*nLocalHostNonceIn=*/1,
|
||||||
|
CAddress(),
|
||||||
|
pszDest,
|
||||||
|
ConnectionType::INBOUND,
|
||||||
|
/*inbound_onion=*/true);
|
||||||
BOOST_CHECK(pnode4->IsFullOutboundConn() == false);
|
BOOST_CHECK(pnode4->IsFullOutboundConn() == false);
|
||||||
BOOST_CHECK(pnode4->IsManualConn() == false);
|
BOOST_CHECK(pnode4->IsManualConn() == false);
|
||||||
BOOST_CHECK(pnode4->IsBlockOnlyConn() == false);
|
BOOST_CHECK(pnode4->IsBlockOnlyConn() == false);
|
||||||
|
@ -607,7 +622,16 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
|
||||||
in_addr ipv4AddrPeer;
|
in_addr ipv4AddrPeer;
|
||||||
ipv4AddrPeer.s_addr = 0xa0b0c001;
|
ipv4AddrPeer.s_addr = 0xa0b0c001;
|
||||||
CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
|
CAddress addr = CAddress(CService(ipv4AddrPeer, 7777), NODE_NETWORK);
|
||||||
std::unique_ptr<CNode> pnode = std::make_unique<CNode>(0, NODE_NETWORK, INVALID_SOCKET, addr, /*nKeyedNetGroupIn=*/0, /*nLocalHostNonceIn=*/0, CAddress{}, /*pszDest=*/std::string{}, ConnectionType::OUTBOUND_FULL_RELAY, /*inbound_onion=*/false);
|
std::unique_ptr<CNode> pnode = std::make_unique<CNode>(/*id=*/0,
|
||||||
|
NODE_NETWORK,
|
||||||
|
/*sock=*/nullptr,
|
||||||
|
addr,
|
||||||
|
/*nKeyedNetGroupIn=*/0,
|
||||||
|
/*nLocalHostNonceIn=*/0,
|
||||||
|
CAddress{},
|
||||||
|
/*pszDest=*/std::string{},
|
||||||
|
ConnectionType::OUTBOUND_FULL_RELAY,
|
||||||
|
/*inbound_onion=*/false);
|
||||||
pnode->fSuccessfullyConnected.store(true);
|
pnode->fSuccessfullyConnected.store(true);
|
||||||
|
|
||||||
// the peer claims to be reaching us via IPv6
|
// the peer claims to be reaching us via IPv6
|
||||||
|
|
Loading…
Add table
Reference in a new issue