Skip to content

Commit

Permalink
net: split CConnman::SocketHandler()
Browse files Browse the repository at this point in the history
`CConnman::SocketHandler()` does 3 things:
1. Check sockets for readiness
2. Process ready listening sockets
3. Process ready connected sockets

Split the processing (2. and 3.) into separate methods to make the code
easier to grasp.

Also, move the processing of listening sockets after the processing of
connected sockets to make it obvious that there is no dependency and
also explicitly release the snapshot before dealing with listening
sockets - it is only necessary for the connected sockets part.
vasild committed Nov 18, 2021
1 parent c7eb19e commit f52b6b2
Showing 2 changed files with 57 additions and 17 deletions.
51 changes: 34 additions & 17 deletions src/net.cpp
Original file line number Diff line number Diff line change
@@ -1502,28 +1502,33 @@ void CConnman::SocketEvents(const std::vector<CNode*>& nodes,

void CConnman::SocketHandler()
{
const NodesSnapshot snap{*this, /*shuffle=*/false};
std::set<SOCKET> recv_set;
std::set<SOCKET> send_set;
std::set<SOCKET> error_set;

std::set<SOCKET> recv_set, send_set, error_set;
SocketEvents(snap.Nodes(), recv_set, send_set, error_set);
{
const NodesSnapshot snap{*this, /*shuffle=*/false};

if (interruptNet) return;
// Check for the readiness of the already connected sockets and the
// listening sockets in one call ("readiness" as in poll(2) or
// select(2)). If none are ready, wait for a short while and return
// empty sets.
SocketEvents(snap.Nodes(), recv_set, send_set, error_set);

//
// Accept new connections
//
for (const ListenSocket& hListenSocket : vhListenSocket)
{
if (hListenSocket.socket != INVALID_SOCKET && recv_set.count(hListenSocket.socket) > 0)
{
AcceptConnection(hListenSocket);
}
// Service (send/receive) each of the already connected nodes.
SocketHandlerConnected(snap.Nodes(), recv_set, send_set, error_set);
}

//
// Service each socket
//
for (CNode* pnode : snap.Nodes()) {
// Accept new connections from listening sockets.
SocketHandlerListening(recv_set);
}

void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
const std::set<SOCKET>& recv_set,
const std::set<SOCKET>& send_set,
const std::set<SOCKET>& error_set)
{
for (CNode* pnode : nodes) {
if (interruptNet)
return;

@@ -1607,6 +1612,18 @@ void CConnman::SocketHandler()
}
}

void CConnman::SocketHandlerListening(const std::set<SOCKET>& recv_set)
{
for (const ListenSocket& listen_socket : vhListenSocket) {
if (interruptNet) {
return;
}
if (listen_socket.socket != INVALID_SOCKET && recv_set.count(listen_socket.socket) > 0) {
AcceptConnection(listen_socket);
}
}
}

void CConnman::ThreadSocketHandler()
{
SetSyscallSandboxPolicy(SyscallSandboxPolicy::NET);
23 changes: 23 additions & 0 deletions src/net.h
Original file line number Diff line number Diff line change
@@ -1010,7 +1010,30 @@ class CConnman
std::set<SOCKET>& send_set,
std::set<SOCKET>& error_set);

/**
* Check connected and listening sockets for IO readiness and process them accordingly.
*/
void SocketHandler();

/**
* Do the read/write for connected sockets that are ready for IO.
* @param[in] nodes Nodes to process. The socket of each node is checked against
* `recv_set`, `send_set` and `error_set`.
* @param[in] recv_set Sockets that are ready for read.
* @param[in] send_set Sockets that are ready for send.
* @param[in] error_set Sockets that have an exceptional condition (error).
*/
void SocketHandlerConnected(const std::vector<CNode*>& nodes,
const std::set<SOCKET>& recv_set,
const std::set<SOCKET>& send_set,
const std::set<SOCKET>& error_set);

/**
* Accept incoming connections, one from each read-ready listening socket.
* @param[in] recv_set Sockets that are ready for read.
*/
void SocketHandlerListening(const std::set<SOCKET>& recv_set);

void ThreadSocketHandler();
void ThreadDNSAddressSeed();

0 comments on commit f52b6b2

Please sign in to comment.