diff options
author | Fabio Alessandrelli <fabio.alessandrelli@gmail.com> | 2018-09-21 21:49:50 +0200 |
---|---|---|
committer | Fabio Alessandrelli <fabio.alessandrelli@gmail.com> | 2018-09-22 01:40:58 +0200 |
commit | a15db2d2b6e8fd799c0f021f7f6c99ede0e9677b (patch) | |
tree | 6051d8a148c941edcaf8e5e52050ec3ed30172f3 | |
parent | ef7b384861d59e566badf1adf28c8b56255c912e (diff) |
Use select instead of WSAPoll on Windows.
WSAPoll is broken by design.
It was announced as the new way to introduce compatibility to posix
sockets, their implementation was broken, and they decided not to fix it.
You can read the full story here:
https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
-rw-r--r-- | drivers/unix/net_socket_posix.cpp | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index 9dcc6038ab..1d82442d58 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -68,7 +68,6 @@ #define SOCK_BUF(x) x #define SOCK_CBUF(x) x #define SOCK_IOCTL ioctl -#define SOCK_POLL ::poll #define SOCK_CLOSE ::close /* Windows */ @@ -80,7 +79,6 @@ #define SOCK_BUF(x) (char *)(x) #define SOCK_CBUF(x) (const char *)(x) #define SOCK_IOCTL ioctlsocket -#define SOCK_POLL WSAPoll #define SOCK_CLOSE closesocket // Windows doesn't have this flag @@ -331,10 +329,58 @@ Error NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port) { return OK; } -Error NetSocketPosix::poll(PollType p_type, int timeout) const { +Error NetSocketPosix::poll(PollType p_type, int p_timeout) const { ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED); +#if defined(WINDOWS_ENABLED) + bool ready = false; + fd_set rd, wr, ex; + fd_set *rdp = NULL; + fd_set *wrp = NULL; + FD_ZERO(&rd); + FD_ZERO(&wr); + FD_ZERO(&ex); + FD_SET(_sock, &ex); + struct timeval timeout = { p_timeout, 0 }; + // For blocking operation, pass NULL timeout pointer to select. + struct timeval *tp = NULL; + if (p_timeout >= 0) { + // If timeout is non-negative, we want to specify the timeout instead. + tp = &timeout; + } + + switch (p_type) { + case POLL_TYPE_IN: + FD_SET(_sock, &rd); + rdp = &rd; + break; + case POLL_TYPE_OUT: + FD_SET(_sock, &wr); + wrp = ≀ + break; + case POLL_TYPE_IN_OUT: + FD_SET(_sock, &rd); + FD_SET(_sock, &wr); + rdp = &rd; + wrp = ≀ + } + int ret = select(1, rdp, wrp, &ex, tp); + + ERR_FAIL_COND_V(ret == SOCKET_ERROR, FAILED); + + if (ret == 0) + return ERR_BUSY; + + ERR_FAIL_COND_V(FD_ISSET(_sock, &ex), FAILED); + + if (rdp && FD_ISSET(_sock, rdp)) + ready = true; + if (wrp && FD_ISSET(_sock, wrp)) + ready = true; + + return ready ? OK : ERR_BUSY; +#else struct pollfd pfd; pfd.fd = _sock; pfd.events = POLLIN; @@ -351,7 +397,7 @@ Error NetSocketPosix::poll(PollType p_type, int timeout) const { pfd.events = POLLOUT || POLLIN; } - int ret = SOCK_POLL(&pfd, 1, timeout); + int ret = ::poll(&pfd, 1, p_timeout); ERR_FAIL_COND_V(ret < 0, FAILED); @@ -359,6 +405,7 @@ Error NetSocketPosix::poll(PollType p_type, int timeout) const { return ERR_BUSY; return OK; +#endif } Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) { |