From ea1845315a109eb105113cb5fbb6f869e1cf010c Mon Sep 17 00:00:00 2001 From: Vasil Dimov Date: Fri, 12 Feb 2021 14:05:53 +0100 Subject: net: extend Sock::Wait() to report a timeout Previously `Sock::Wait()` would not have signaled to the caller whether a timeout or one of the requested events occurred since that was not needed by any of the callers. Such functionality will be needed in the I2P implementation, thus extend the `Sock::Wait()` method. --- src/util/sock.cpp | 34 +++++++++++++++++++++++++++++++--- src/util/sock.h | 7 ++++++- 2 files changed, 37 insertions(+), 4 deletions(-) (limited to 'src/util') diff --git a/src/util/sock.cpp b/src/util/sock.cpp index 4c65b5b680..d8fd9d4138 100644 --- a/src/util/sock.cpp +++ b/src/util/sock.cpp @@ -59,7 +59,7 @@ ssize_t Sock::Recv(void* buf, size_t len, int flags) const return recv(m_socket, static_cast(buf), len, flags); } -bool Sock::Wait(std::chrono::milliseconds timeout, Event requested) const +bool Sock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occurred) const { #ifdef USE_POLL pollfd fd; @@ -72,7 +72,21 @@ bool Sock::Wait(std::chrono::milliseconds timeout, Event requested) const fd.events |= POLLOUT; } - return poll(&fd, 1, count_milliseconds(timeout)) != SOCKET_ERROR; + if (poll(&fd, 1, count_milliseconds(timeout)) == SOCKET_ERROR) { + return false; + } + + if (occurred != nullptr) { + *occurred = 0; + if (fd.revents & POLLIN) { + *occurred |= RECV; + } + if (fd.revents & POLLOUT) { + *occurred |= SEND; + } + } + + return true; #else if (!IsSelectableSocket(m_socket)) { return false; @@ -93,7 +107,21 @@ bool Sock::Wait(std::chrono::milliseconds timeout, Event requested) const timeval timeout_struct = MillisToTimeval(timeout); - return select(m_socket + 1, &fdset_recv, &fdset_send, nullptr, &timeout_struct) != SOCKET_ERROR; + if (select(m_socket + 1, &fdset_recv, &fdset_send, nullptr, &timeout_struct) == SOCKET_ERROR) { + return false; + } + + if (occurred != nullptr) { + *occurred = 0; + if (FD_ISSET(m_socket, &fdset_recv)) { + *occurred |= RECV; + } + if (FD_ISSET(m_socket, &fdset_send)) { + *occurred |= SEND; + } + } + + return true; #endif /* USE_POLL */ } diff --git a/src/util/sock.h b/src/util/sock.h index 23c3c35dad..2d9cac14af 100644 --- a/src/util/sock.h +++ b/src/util/sock.h @@ -105,9 +105,14 @@ public: * Wait for readiness for input (recv) or output (send). * @param[in] timeout Wait this much for at least one of the requested events to occur. * @param[in] requested Wait for those events, bitwise-or of `RECV` and `SEND`. + * @param[out] occurred If not nullptr and `true` is returned, then upon return this + * indicates which of the requested events occurred. A timeout is indicated by return + * value of `true` and `occurred` being set to 0. * @return true on success and false otherwise */ - virtual bool Wait(std::chrono::milliseconds timeout, Event requested) const; + virtual bool Wait(std::chrono::milliseconds timeout, + Event requested, + Event* occurred = nullptr) const; private: /** -- cgit v1.2.3