Commit aa44443a authored by jan.koester's avatar jan.koester
Browse files

wait added

parent db65b526
Loading
Loading
Loading
Loading
+25 −0
Changes for src/posix/socket.cpp: 25 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <poll.h>

namespace netplus {
@@ -69,6 +70,30 @@ void netplus::socket::close() {
    } while (rc < 0 && errno == EINTR);
}

bool netplus::socket::waitReadable(int timeoutMs) {
    if (_Socket < 0) return false;
    struct pollfd pfd;
    pfd.fd = _Socket;
    pfd.events = POLLIN;
    pfd.revents = 0;
    int r;
    do {
        r = ::poll(&pfd, 1, timeoutMs);
    } while (r < 0 && errno == EINTR);
    if (r <= 0)
        return false;                       /* timeout or poll() error */
    if (pfd.revents & POLLIN)
        return true;                        /* real data waiting */
    if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
        /* Error-only wakeup (e.g. a latched ICMP error on an unconnected UDP
         * socket): drain it so poll() blocks again instead of spinning. */
        int err = 0;
        socklen_t el = sizeof(err);
        ::getsockopt(_Socket, SOL_SOCKET, SO_ERROR, &err, &el);
    }
    return false;
}

void socket::setFlag(int flag, int value) {
    int sockopts;
    do {
+17 −0
Changes for src/socket.h: 17 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -261,6 +261,23 @@ namespace netplus {

		SOCKET fd();

		// Block until this socket has data to read (POLLIN) or timeoutMs
		// elapses; timeoutMs < 0 blocks indefinitely. Returns true ONLY when
		// there is data to read. Non-blocking batch receivers (udp
		// recvBatchAddr, non-blocking accept) never wait themselves, so a
		// receive loop must gate on this or it spins a core at 100%.
		//
		// poll()/WSAPoll() report POLLERR/POLLHUP/POLLNVAL in revents even
		// though we only ask for POLLIN. A latched socket error — e.g. an
		// ICMP port-unreachable on an unconnected UDP socket after a sendto —
		// makes poll() return immediately with POLLERR forever while a
		// non-blocking recv keeps yielding EAGAIN without clearing it; a
		// naive "poll() > 0" readiness test then busy-loops. So this gates on
		// POLLIN and, on an error-only wakeup, drains the pending error via
		// SO_ERROR (which resets sk_err) so the next call blocks again.
		// Platform-neutral: poll() on POSIX, WSAPoll() on Windows.
		bool waitReadable(int timeoutMs);

		virtual socket& operator=(SOCKET sock) = 0;
		virtual void close();
		virtual void flush_out() = 0;
+26 −0
Changes for src/windows/socket.cpp: 26 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -121,6 +121,32 @@ namespace netplus {
        return _Socket;
    }

    // -------------------------------------------------------------------------
    // socket::waitReadable  (see socket.h for the full contract / rationale)
    // Platform-neutral readiness gate; Windows uses WSAPoll().
    // -------------------------------------------------------------------------
    bool socket::waitReadable(int timeoutMs) {
        if (_Socket == INVALID_SOCKET) return false;
        WSAPOLLFD pfd;
        pfd.fd = _Socket;
        pfd.events = POLLRDNORM;
        pfd.revents = 0;
        int r = ::WSAPoll(&pfd, 1, timeoutMs);
        if (r <= 0)
            return false;                       // timeout or WSAPoll() error
        if (pfd.revents & POLLRDNORM)
            return true;                        // real data waiting
        if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
            // Error-only wakeup: drain the latched error so the next call
            // blocks again instead of spinning.
            int err = 0;
            int el = sizeof(err);
            ::getsockopt(_Socket, SOL_SOCKET, SO_ERROR,
                         reinterpret_cast<char*>(&err), &el);
        }
        return false;
    }

    // -------------------------------------------------------------------------
    // socket::setFlag
    // Windows: only useful flag is nonblocking (FIONBIO)