diff --git a/src/net.cpp b/src/net.cpp index e9aa7ee43b3..85bd0b529ec 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -961,8 +961,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr&& sock, return; } - if (!IsSelectableSocket(sock->Get())) - { + if (!sock->IsSelectable()) { LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString()); return; } diff --git a/src/netbase.cpp b/src/netbase.cpp index 4b8d2f8d0c8..22cf4415c80 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -503,7 +503,7 @@ std::unique_ptr CreateSockTCP(const CService& address_family) // Ensure that waiting for I/O on this socket won't result in undefined // behavior. - if (!IsSelectableSocket(sock->Get())) { + if (!sock->IsSelectable()) { LogPrintf("Cannot create connection: non-selectable socket created (fd >= FD_SETSIZE ?)\n"); return nullptr; } diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp index fabcea22c34..1d198566712 100644 --- a/src/test/fuzz/util.cpp +++ b/src/test/fuzz/util.cpp @@ -16,7 +16,7 @@ #include FuzzedSock::FuzzedSock(FuzzedDataProvider& fuzzed_data_provider) - : m_fuzzed_data_provider{fuzzed_data_provider} + : m_fuzzed_data_provider{fuzzed_data_provider}, m_selectable{fuzzed_data_provider.ConsumeBool()} { m_socket = fuzzed_data_provider.ConsumeIntegralInRange(INVALID_SOCKET - 1, INVALID_SOCKET); } @@ -254,6 +254,11 @@ int FuzzedSock::GetSockName(sockaddr* name, socklen_t* name_len) const return 0; } +bool FuzzedSock::IsSelectable() const +{ + return m_selectable; +} + bool FuzzedSock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const { constexpr std::array wait_errnos{ diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index 60e2875953f..92ad08ec59a 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -48,6 +48,13 @@ class FuzzedSock : public Sock */ mutable std::optional m_peek_data; + /** + * Whether to pretend that the socket is select(2)-able. This is randomly set in the + * constructor. It should remain constant so that repeated calls to `IsSelectable()` + * return the same value. + */ + const bool m_selectable; + public: explicit FuzzedSock(FuzzedDataProvider& fuzzed_data_provider); @@ -73,6 +80,8 @@ public: int GetSockName(sockaddr* name, socklen_t* name_len) const override; + bool IsSelectable() const override; + bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override; bool WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per_sock) const override; diff --git a/src/test/util/net.h b/src/test/util/net.h index ec6b4e6e883..749b5b33644 100644 --- a/src/test/util/net.h +++ b/src/test/util/net.h @@ -166,6 +166,8 @@ public: return 0; } + bool IsSelectable() const override { return true; } + bool Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred = nullptr) const override diff --git a/src/util/sock.cpp b/src/util/sock.cpp index fed50444a97..c312a88276c 100644 --- a/src/util/sock.cpp +++ b/src/util/sock.cpp @@ -117,11 +117,12 @@ int Sock::GetSockName(sockaddr* name, socklen_t* name_len) const return getsockname(m_socket, name, name_len); } -bool IsSelectableSocket(const SOCKET& s) { +bool Sock::IsSelectable() const +{ #if defined(USE_POLL) || defined(WIN32) return true; #else - return (s < FD_SETSIZE); + return m_socket < FD_SETSIZE; #endif } @@ -193,10 +194,10 @@ bool Sock::WaitMany(std::chrono::milliseconds timeout, EventsPerSock& events_per SOCKET socket_max{0}; for (const auto& [sock, events] : events_per_sock) { - const auto& s = sock->m_socket; - if (!IsSelectableSocket(s)) { + if (!sock->IsSelectable()) { return false; } + const auto& s = sock->m_socket; if (events.requested & RECV) { FD_SET(s, &recv); } diff --git a/src/util/sock.h b/src/util/sock.h index 9ec53ec91d1..ab9c6737c65 100644 --- a/src/util/sock.h +++ b/src/util/sock.h @@ -133,6 +133,12 @@ public: */ [[nodiscard]] virtual int GetSockName(sockaddr* name, socklen_t* name_len) const; + /** + * Check if the underlying socket can be used for `select(2)` (or the `Wait()` method). + * @return true if selectable + */ + [[nodiscard]] virtual bool IsSelectable() const; + using Event = uint8_t; /** @@ -267,8 +273,6 @@ private: void Close(); }; -bool IsSelectableSocket(const SOCKET& s); - /** Return readable error string for a network error code */ std::string NetworkErrorString(int err);