diff --git a/src/common/sockman.cpp b/src/common/sockman.cpp index bd661789aff..2b9dac0b059 100644 --- a/src/common/sockman.cpp +++ b/src/common/sockman.cpp @@ -91,6 +91,27 @@ bool SockMan::BindAndStartListening(const CService& to, bilingual_str& err_msg) return true; } +std::unique_ptr SockMan::AcceptConnection(const Sock& listen_sock, CService& addr) +{ + struct sockaddr_storage sockaddr; + socklen_t len = sizeof(sockaddr); + auto sock = listen_sock.Accept((struct sockaddr*)&sockaddr, &len); + + if (!sock) { + const int nErr = WSAGetLastError(); + if (nErr != WSAEWOULDBLOCK) { + LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr)); + } + return {}; + } + + if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr, len)) { + LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Unknown socket family\n"); + } + + return sock; +} + void SockMan::StopListening() { m_listen.clear(); diff --git a/src/common/sockman.h b/src/common/sockman.h index b977d49f42b..580e5b189e0 100644 --- a/src/common/sockman.h +++ b/src/common/sockman.h @@ -17,6 +17,7 @@ * To use this class, inherit from it and implement the pure virtual methods. * Handled operations: * - binding and listening on sockets + * - accepting incoming connections */ class SockMan { @@ -30,6 +31,14 @@ public: */ bool BindAndStartListening(const CService& to, bilingual_str& err_msg); + /** + * Accept a connection. + * @param[in] listen_sock Socket on which to accept the connection. + * @param[out] addr Address of the peer that was accepted. + * @return Newly created socket for the accepted connection. + */ + std::unique_ptr AcceptConnection(const Sock& listen_sock, CService& addr); + /** * Stop listening by closing all listening sockets. */ diff --git a/src/net.cpp b/src/net.cpp index 1181f4a6555..e38b75f283b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1732,27 +1732,11 @@ bool CConnman::AttemptToEvictConnection() return false; } -void CConnman::AcceptConnection(const Sock& listen_sock) { - struct sockaddr_storage sockaddr; - socklen_t len = sizeof(sockaddr); - auto sock = listen_sock.Accept((struct sockaddr*)&sockaddr, &len); - - if (!sock) { - const int nErr = WSAGetLastError(); - if (nErr != WSAEWOULDBLOCK) { - LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr)); - } - return; - } - - CService addr; - if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr, len)) { - LogPrintLevel(BCLog::NET, BCLog::Level::Warning, "Unknown socket family\n"); - } else { - addr = MaybeFlipIPv6toCJDNS(addr); - } - - const CService addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock))}; +void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr&& sock, + const CService& addr_bind, + const CService& addr) +{ + int nInbound = 0; NetPermissionFlags permission_flags = NetPermissionFlags::None; auto it{m_listen_permissions.find(addr_bind)}; @@ -1760,16 +1744,6 @@ void CConnman::AcceptConnection(const Sock& listen_sock) { NetPermissions::AddFlag(permission_flags, it->second); } - CreateNodeFromAcceptedSocket(std::move(sock), permission_flags, addr_bind, addr); -} - -void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr&& sock, - NetPermissionFlags permission_flags, - const CService& addr_bind, - const CService& addr) -{ - int nInbound = 0; - AddWhitelistPermissionFlags(permission_flags, addr, vWhitelistedRangeIncoming); { @@ -2219,7 +2193,16 @@ void CConnman::SocketHandlerListening(const Sock::EventsPerSock& events_per_sock } const auto it = events_per_sock.find(sock); if (it != events_per_sock.end() && it->second.occurred & Sock::RECV) { - AcceptConnection(*sock); + CService addr_accepted; + + auto sock_accepted{AcceptConnection(*sock, addr_accepted)}; + + if (sock_accepted) { + addr_accepted = MaybeFlipIPv6toCJDNS(addr_accepted); + const CService addr_bind{MaybeFlipIPv6toCJDNS(GetBindAddress(*sock))}; + + CreateNodeFromAcceptedSocket(std::move(sock_accepted), addr_bind, addr_accepted); + } } } } @@ -3108,7 +3091,7 @@ void CConnman::ThreadI2PAcceptIncoming() continue; } - CreateNodeFromAcceptedSocket(std::move(conn.sock), NetPermissionFlags::None, conn.me, conn.peer); + CreateNodeFromAcceptedSocket(std::move(conn.sock), conn.me, conn.peer); err_wait = err_wait_begin; } diff --git a/src/net.h b/src/net.h index cc9b82421ef..01fc644e40c 100644 --- a/src/net.h +++ b/src/net.h @@ -1287,18 +1287,15 @@ private: void ThreadOpenConnections(std::vector connect, Span seed_nodes) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex, !m_unused_i2p_sessions_mutex, !m_reconnections_mutex); void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc); void ThreadI2PAcceptIncoming(); - void AcceptConnection(const Sock& listen_sock); /** * Create a `CNode` object from a socket that has just been accepted and add the node to * the `m_nodes` member. * @param[in] sock Connected socket to communicate with the peer. - * @param[in] permission_flags The peer's permissions. * @param[in] addr_bind The address and port at our side of the connection. * @param[in] addr The address and port at the peer's side of the connection. */ void CreateNodeFromAcceptedSocket(std::unique_ptr&& sock, - NetPermissionFlags permission_flags, const CService& addr_bind, const CService& addr);