diff --git a/ChangeLog.md b/ChangeLog.md index 8f7b68007..a09c07788 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -112,6 +112,8 @@ Nazara Engine: - Fixed Model copy constructor not copying materials - ⚠️ Added InstancedRenderable::Clone() method - Fixed a lot of classes not having their move constructor/assignation operator marked noexcept +- ⚠️ SocketPoller::Wait now returns the number of socket marked as ready, and takes an additional optional parameter allowing to query the last error. +- SocketPoller will now silently ignore "interrupt errors" Nazara Development Kit: - Added ImageWidget (#139) diff --git a/SDK/src/NDK/Lua/LuaBinding_Network.cpp b/SDK/src/NDK/Lua/LuaBinding_Network.cpp index c54ef89a0..f3f82264a 100644 --- a/SDK/src/NDK/Lua/LuaBinding_Network.cpp +++ b/SDK/src/NDK/Lua/LuaBinding_Network.cpp @@ -266,14 +266,15 @@ namespace Ndk state.SetGlobal("ResolveError"); // Nz::SocketError - static_assert(Nz::SocketError_Max + 1 == 15, "Nz::ResolveError has been updated but change was not reflected to Lua binding"); - state.PushTable(0, 15); + static_assert(Nz::SocketError_Max + 1 == 16, "Nz::SocketError has been updated but change was not reflected to Lua binding"); + state.PushTable(0, 16); { state.PushField("AddressNotAvailable", Nz::SocketError_AddressNotAvailable); state.PushField("ConnectionClosed", Nz::SocketError_ConnectionClosed); state.PushField("ConnectionRefused", Nz::SocketError_ConnectionRefused); state.PushField("DatagramSize", Nz::SocketError_DatagramSize); state.PushField("Internal", Nz::SocketError_Internal); + state.PushField("Interrupted", Nz::SocketError_Interrupted); state.PushField("Packet", Nz::SocketError_Packet); state.PushField("NetworkError", Nz::SocketError_NetworkError); state.PushField("NoError", Nz::SocketError_NoError); diff --git a/include/Nazara/Network/Enums.hpp b/include/Nazara/Network/Enums.hpp index 42089b6a4..dc082deba 100644 --- a/include/Nazara/Network/Enums.hpp +++ b/include/Nazara/Network/Enums.hpp @@ -78,6 +78,7 @@ namespace Nz SocketError_ConnectionRefused, //< The connection attempt was refused SocketError_DatagramSize, //< The datagram size is over the system limit SocketError_Internal, //< The error is coming from the engine + SocketError_Interrupted, //< The operation was interrupted by a signal SocketError_Packet, //< The packet encoding/decoding failed, probably because of corrupted data SocketError_NetworkError, //< The network system has failed (maybe network is down) SocketError_NotInitialized, //< Nazara network has not been initialized diff --git a/include/Nazara/Network/SocketPoller.hpp b/include/Nazara/Network/SocketPoller.hpp index 9a5af5452..bbe446c08 100644 --- a/include/Nazara/Network/SocketPoller.hpp +++ b/include/Nazara/Network/SocketPoller.hpp @@ -31,7 +31,7 @@ namespace Nz bool RegisterSocket(AbstractSocket& socket, SocketPollEventFlags eventFlags); void UnregisterSocket(AbstractSocket& socket); - bool Wait(int msTimeout); + unsigned int Wait(int msTimeout, SocketError* error = nullptr); SocketPoller& operator=(SocketPoller&&) noexcept = default; diff --git a/src/Nazara/Network/AlgorithmNetwork.cpp b/src/Nazara/Network/AlgorithmNetwork.cpp index 9a593db39..55d6a5569 100644 --- a/src/Nazara/Network/AlgorithmNetwork.cpp +++ b/src/Nazara/Network/AlgorithmNetwork.cpp @@ -84,35 +84,35 @@ namespace Nz * * \param resolveError Error enumeration */ - const char* ErrorToString(Nz::ResolveError resolveError) + const char* ErrorToString(ResolveError resolveError) { switch (resolveError) { - case Nz::ResolveError_NoError: + case ResolveError_NoError: return "No error"; - case Nz::ResolveError_Internal: + case ResolveError_Internal: return "An internal error occurred"; - case Nz::ResolveError_ResourceError: + case ResolveError_ResourceError: return "The operating system lacks the resources to proceed"; - case Nz::ResolveError_NonRecoverable: + case ResolveError_NonRecoverable: return "A nonrecoverable error occurred"; - case Nz::ResolveError_NotFound: + case ResolveError_NotFound: return "No such host is known"; - case Nz::ResolveError_NotInitialized: + case ResolveError_NotInitialized: return "Nazara Network has not been initialized"; - case Nz::ResolveError_ProtocolNotSupported: + case ResolveError_ProtocolNotSupported: return "A specified protocol is not supported by the server"; - case Nz::ResolveError_TemporaryFailure: + case ResolveError_TemporaryFailure: return "A temporary failure occurred, try again"; - case Nz::ResolveError_Unknown: + case ResolveError_Unknown: return "An unknown error occurred"; default: @@ -127,53 +127,56 @@ namespace Nz * * \param socketError Error enumeration */ - const char* ErrorToString(Nz::SocketError socketError) + const char* ErrorToString(SocketError socketError) { switch (socketError) { - case Nz::SocketError_NoError: + case SocketError_NoError: return "No error"; - case Nz::SocketError_AddressNotAvailable: + case SocketError_AddressNotAvailable: return "The address is already in use"; - case Nz::SocketError_ConnectionClosed: + case SocketError_ConnectionClosed: return "The connection has been closed"; - case Nz::SocketError_ConnectionRefused: + case SocketError_ConnectionRefused: return "The connection attempt was refused"; - case Nz::SocketError_DatagramSize: + case SocketError_DatagramSize: return "The datagram size is over the system limit"; - case Nz::SocketError_Internal: + case SocketError_Internal: return "An internal error occurred"; - case Nz::SocketError_Packet: + case SocketError_Interrupted: + return "The operation was interrupted by a signal"; + + case SocketError_Packet: return "Packet encoding or decoding failed"; - case Nz::SocketError_NetworkError: + case SocketError_NetworkError: return "Networking subsystem failed"; - case Nz::SocketError_NotInitialized: + case SocketError_NotInitialized: return "Network module has not been initialized"; - case Nz::SocketError_NotSupported: + case SocketError_NotSupported: return "This operation is not supported"; - case Nz::SocketError_ResolveError: + case SocketError_ResolveError: return "The hostname couldn't be resolved"; - case Nz::SocketError_ResourceError: + case SocketError_ResourceError: return "The operating system lacks the resources to proceed"; - case Nz::SocketError_TimedOut: + case SocketError_TimedOut: return "The operation timed out"; - case Nz::SocketError_Unknown: + case SocketError_Unknown: return "An unknown error occurred"; - case Nz::SocketError_UnreachableHost: + case SocketError_UnreachableHost: return "The host is not reachable"; default: diff --git a/src/Nazara/Network/Linux/SocketPollerImpl.cpp b/src/Nazara/Network/Linux/SocketPollerImpl.cpp index b35a37ca5..53de22a70 100644 --- a/src/Nazara/Network/Linux/SocketPollerImpl.cpp +++ b/src/Nazara/Network/Linux/SocketPollerImpl.cpp @@ -81,7 +81,7 @@ namespace Nz NazaraWarning("An error occured while removing socket from epoll structure (errno " + String::Number(errno) + ": " + Error::GetLastSystemError() + ')'); } - int SocketPollerImpl::Wait(int msTimeout, SocketError* error) + unsigned int SocketPollerImpl::Wait(int msTimeout, SocketError* error) { int activeSockets; @@ -93,7 +93,7 @@ namespace Nz if (activeSockets == -1) { if (error) - *error = SocketImpl::TranslateErrnoToResolveError(errno); + *error = SocketImpl::TranslateErrnoToSocketError(errno); return 0; } diff --git a/src/Nazara/Network/Linux/SocketPollerImpl.hpp b/src/Nazara/Network/Linux/SocketPollerImpl.hpp index 882141d38..4200dff79 100644 --- a/src/Nazara/Network/Linux/SocketPollerImpl.hpp +++ b/src/Nazara/Network/Linux/SocketPollerImpl.hpp @@ -30,7 +30,7 @@ namespace Nz bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags); void UnregisterSocket(SocketHandle socket); - int Wait(int msTimeout, SocketError* error); + unsigned int Wait(int msTimeout, SocketError* error); private: std::unordered_set m_readyToReadSockets; diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index d372d6fff..c8140f019 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -41,7 +41,7 @@ namespace Nz else { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); } return newClient; @@ -58,7 +58,7 @@ namespace Nz if (bind(handle, reinterpret_cast(&nameBuffer), bufferLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return SocketState_NotConnected; } @@ -76,7 +76,7 @@ namespace Nz SocketHandle handle = socket(TranslateNetProtocolToAF(protocol), TranslateSocketTypeToSock(type), 0); if (handle == InvalidHandle && error != nullptr) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return handle; } @@ -129,7 +129,7 @@ namespace Nz if (errorCode == EADDRNOTAVAIL) *error = SocketError_ConnectionRefused; //< ConnectionRefused seems more legit than AddressNotAvailable in connect case else - *error = TranslateErrnoToResolveError(errorCode); + *error = TranslateErrnoToSocketError(errorCode); } return SocketState_NotConnected; @@ -162,7 +162,7 @@ namespace Nz if (code) { if (error) - *error = TranslateErrnoToResolveError(code); + *error = TranslateErrnoToSocketError(code); return SocketState_NotConnected; } @@ -177,7 +177,7 @@ namespace Nz else { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return SocketState_NotConnected; } @@ -202,7 +202,7 @@ namespace Nz if (code < 0) return SocketError_Internal; - return TranslateErrnoToResolveError(code); + return TranslateErrnoToSocketError(code); } int SocketImpl::GetLastErrorCode() @@ -218,7 +218,7 @@ namespace Nz if (getsockopt(handle, SOL_SOCKET, SO_ERROR, &code, &codeLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return -1; } @@ -240,7 +240,7 @@ namespace Nz if (bind(handle, reinterpret_cast(&nameBuffer), bufferLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return SocketState_NotConnected; } @@ -248,7 +248,7 @@ namespace Nz if (listen(handle, queueSize) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return SocketState_NotConnected; } @@ -267,7 +267,7 @@ namespace Nz if (ioctl(handle, FIONREAD, &availableBytes) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return 0; } @@ -286,7 +286,7 @@ namespace Nz if (getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &code, &codeLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; } @@ -305,7 +305,7 @@ namespace Nz if (getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &code, &codeLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; } @@ -324,7 +324,7 @@ namespace Nz if (getsockopt(handle, IPPROTO_IP, IP_MTU, &code, &codeLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return 0; } @@ -343,7 +343,7 @@ namespace Nz if (getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &code, &codeLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; } @@ -362,7 +362,7 @@ namespace Nz if (getsockopt(handle, SOL_SOCKET, SO_RCVBUF, reinterpret_cast(&code), &codeLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return 0; } @@ -385,7 +385,7 @@ namespace Nz if (getpeername(handle, reinterpret_cast(nameBuffer.data()), &bufferLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return IpAddress(); } @@ -404,7 +404,7 @@ namespace Nz if (getsockopt(handle, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&code), &codeLength) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return 0; } @@ -432,7 +432,7 @@ namespace Nz if (errorCode == EINVAL) *error = SocketError_NoError; else - *error = TranslateErrnoToResolveError(errorCode); + *error = TranslateErrnoToSocketError(errorCode); } return IpAddress(); @@ -444,7 +444,7 @@ namespace Nz return IpAddressImpl::FromSockAddr(reinterpret_cast(nameBuffer.data())); } - int SocketImpl::Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error) + unsigned int SocketImpl::Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error) { NazaraAssert(fdarray && nfds > 0, "Invalid fdarray"); @@ -454,12 +454,12 @@ namespace Nz if (result < 0) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return 0; } - return result; + return static_cast(result); } bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error) @@ -486,7 +486,7 @@ namespace Nz default: { if (error) - *error = TranslateErrnoToResolveError(errorCode); + *error = TranslateErrnoToSocketError(errorCode); return false; //< Error } @@ -541,7 +541,7 @@ namespace Nz default: { if (error) - *error = TranslateErrnoToResolveError(errorCode); + *error = TranslateErrnoToSocketError(errorCode); return false; //< Error } @@ -618,7 +618,7 @@ namespace Nz default: { if (error) - *error = TranslateErrnoToResolveError(errorCode); + *error = TranslateErrnoToSocketError(errorCode); return false; //< Error } @@ -677,7 +677,7 @@ namespace Nz default: { if (error) - *error = TranslateErrnoToResolveError(errorCode); + *error = TranslateErrnoToSocketError(errorCode); return false; //< Error } @@ -730,7 +730,7 @@ namespace Nz default: { if (error) - *error = TranslateErrnoToResolveError(errorCode); + *error = TranslateErrnoToSocketError(errorCode); return false; //< Error } @@ -770,7 +770,7 @@ namespace Nz default: { if (error) - *error = TranslateErrnoToResolveError(errorCode); + *error = TranslateErrnoToSocketError(errorCode); return false; //< Error } @@ -794,7 +794,7 @@ namespace Nz if (ioctl(handle, FIONBIO, &block) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -813,7 +813,7 @@ namespace Nz if (setsockopt(handle, SOL_SOCKET, SO_BROADCAST, reinterpret_cast(&option), sizeof(option)) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -832,7 +832,7 @@ namespace Nz if (setsockopt(handle, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&option), sizeof(option)) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -854,7 +854,7 @@ namespace Nz if (setsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &keepAlive , sizeof(keepAlive)) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -862,7 +862,7 @@ namespace Nz if (setsockopt(handle, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(keepIdle)) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -870,7 +870,7 @@ namespace Nz if (setsockopt(handle, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(keepInterval)) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -889,7 +889,7 @@ namespace Nz if (setsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &option, sizeof(option)) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -908,7 +908,7 @@ namespace Nz if (setsockopt(handle, SOL_SOCKET, SO_RCVBUF, reinterpret_cast(&option), sizeof(option)) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -927,7 +927,7 @@ namespace Nz if (setsockopt(handle, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&option), sizeof(option)) == SOCKET_ERROR) { if (error) - *error = TranslateErrnoToResolveError(GetLastErrorCode()); + *error = TranslateErrnoToSocketError(GetLastErrorCode()); return false; //< Error } @@ -938,7 +938,7 @@ namespace Nz return true; } - SocketError SocketImpl::TranslateErrnoToResolveError(int error) + SocketError SocketImpl::TranslateErrnoToSocketError(int error) { switch (error) { @@ -974,6 +974,9 @@ namespace Nz case ECONNREFUSED: return SocketError_ConnectionRefused; + case EINTR: + return SocketError_Interrupted; + case EMSGSIZE: return SocketError_DatagramSize; diff --git a/src/Nazara/Network/Posix/SocketImpl.hpp b/src/Nazara/Network/Posix/SocketImpl.hpp index 4bd38380d..af22eb8dd 100644 --- a/src/Nazara/Network/Posix/SocketImpl.hpp +++ b/src/Nazara/Network/Posix/SocketImpl.hpp @@ -60,7 +60,7 @@ namespace Nz static std::size_t QueryReceiveBufferSize(SocketHandle handle, SocketError* error = nullptr); static std::size_t QuerySendBufferSize(SocketHandle handle, SocketError* error = nullptr); - static int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error); + static unsigned int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error); static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error); static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error); @@ -78,7 +78,7 @@ namespace Nz static bool SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr); static bool SetSendBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr); - static SocketError TranslateErrnoToResolveError(int error); + static SocketError TranslateErrnoToSocketError(int error); static int TranslateNetProtocolToAF(NetProtocol protocol); static int TranslateSocketTypeToSock(SocketType type); diff --git a/src/Nazara/Network/Posix/SocketPollerImpl.cpp b/src/Nazara/Network/Posix/SocketPollerImpl.cpp index 01cc9ffa9..fc100d8eb 100644 --- a/src/Nazara/Network/Posix/SocketPollerImpl.cpp +++ b/src/Nazara/Network/Posix/SocketPollerImpl.cpp @@ -76,9 +76,9 @@ namespace Nz m_readyToWriteSockets.erase(socket); } - int SocketPollerImpl::Wait(int msTimeout, SocketError* error) + unsigned int SocketPollerImpl::Wait(int msTimeout, SocketError* error) { - int activeSockets; + unsigned int activeSockets; // Reset status of sockets activeSockets = SocketImpl::Poll(m_sockets.data(), m_sockets.size(), static_cast(msTimeout), error); @@ -87,7 +87,7 @@ namespace Nz m_readyToWriteSockets.clear(); if (activeSockets > 0U) { - int socketRemaining = activeSockets; + unsigned int socketRemaining = activeSockets; for (PollSocket& entry : m_sockets) { if (!entry.revents) @@ -103,7 +103,7 @@ namespace Nz } else { - NazaraWarning("Socket " + String::Number(entry.fd) + " was returned by WSAPoll without POLLRDNORM nor POLLWRNORM events (events: 0x" + String::Number(entry.revents, 16) + ')'); + NazaraWarning("Socket " + String::Number(entry.fd) + " was returned by poll without POLLRDNORM nor POLLWRNORM events (events: 0x" + String::Number(entry.revents, 16) + ')'); activeSockets--; } diff --git a/src/Nazara/Network/Posix/SocketPollerImpl.hpp b/src/Nazara/Network/Posix/SocketPollerImpl.hpp index 5c4ad1743..294f462a6 100644 --- a/src/Nazara/Network/Posix/SocketPollerImpl.hpp +++ b/src/Nazara/Network/Posix/SocketPollerImpl.hpp @@ -23,13 +23,14 @@ namespace Nz void Clear(); - bool IsReady(SocketHandle socket) const; + bool IsReadyToRead(SocketHandle socket) const; + bool IsReadyToWrite(SocketHandle socket) const; bool IsRegistered(SocketHandle socket) const; bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags); void UnregisterSocket(SocketHandle socket); - int Wait(int msTimeout, SocketError* error); + unsigned int Wait(int msTimeout, SocketError* error); private: std::unordered_set m_readyToReadSockets; diff --git a/src/Nazara/Network/SocketPoller.cpp b/src/Nazara/Network/SocketPoller.cpp index 50eeb5cdf..20b575b62 100644 --- a/src/Nazara/Network/SocketPoller.cpp +++ b/src/Nazara/Network/SocketPoller.cpp @@ -3,6 +3,7 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include #if defined(NAZARA_PLATFORM_WINDOWS) #include @@ -170,24 +171,33 @@ namespace Nz * Waits a specific/undetermined amount of time until at least one socket part of the SocketPoller becomes ready. * To query the ready state of the registered socket, use the IsReadyToRead or IsReadyToWrite functions. * + * If error is a valid pointer, it will be used to report the last error occurred (if no error occurred, a value of NoError will be reported) + * * \param msTimeout Maximum time to wait in milliseconds, 0 will returns immediately and -1 will block indefinitely + * \param error If valid, this will be used to report the error status from the poller (if no error occurred, a value of NoError will be reported). * - * \return True if at least one socket registered to the poller is ready. + * \return The number of socket reported ready (may be zero if no socket is ready or if an error occurred) * - * \remark It is an error to try to unregister a non-registered socket from a SocketPoller. + * \remark In case of error, a NazaraError is triggered (except for interrupted errors) * * \see IsReady * \see RegisterSocket */ - bool SocketPoller::Wait(int msTimeout) + unsigned int SocketPoller::Wait(int msTimeout, SocketError* error) { - SocketError error; + SocketError waitError; - int readySockets = m_impl->Wait(msTimeout, &error); - if (error != SocketError_NoError) + unsigned int readySockets = m_impl->Wait(msTimeout, &waitError); + + if (error) + *error = waitError; + + if (waitError != SocketError_NoError) { - NazaraError("SocketPoller encountered an error (code: 0x" + String::Number(error, 16) + ')'); - return false; + if (waitError != SocketError_Interrupted) //< Do not log interrupted error + NazaraError("SocketPoller encountered an error (code: 0x" + String::Number(waitError, 16) + "): " + ErrorToString(waitError)); + + return 0; } return readySockets > 0; diff --git a/src/Nazara/Network/Win32/SocketImpl.cpp b/src/Nazara/Network/Win32/SocketImpl.cpp index a0ebe5948..6d2e33f7f 100644 --- a/src/Nazara/Network/Win32/SocketImpl.cpp +++ b/src/Nazara/Network/Win32/SocketImpl.cpp @@ -467,7 +467,7 @@ namespace Nz return code; } - int SocketImpl::Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error) + unsigned int SocketImpl::Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error) { NazaraAssert(fdarray && nfds > 0, "Invalid fdarray"); @@ -484,10 +484,12 @@ namespace Nz return 0; } + assert(result >= 0); + if (error) *error = SocketError_NoError; - return result; + return static_cast(result); #else NazaraUnused(fdarray); NazaraUnused(nfds); diff --git a/src/Nazara/Network/Win32/SocketImpl.hpp b/src/Nazara/Network/Win32/SocketImpl.hpp index 1aa4a0495..ef49cd14d 100644 --- a/src/Nazara/Network/Win32/SocketImpl.hpp +++ b/src/Nazara/Network/Win32/SocketImpl.hpp @@ -60,7 +60,7 @@ namespace Nz static IpAddress QuerySocketAddress(SocketHandle handle, SocketError* error = nullptr); static std::size_t QuerySendBufferSize(SocketHandle handle, SocketError* error = nullptr); - static int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error); + static unsigned int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error); static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error); static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error); diff --git a/src/Nazara/Network/Win32/SocketPollerImpl.cpp b/src/Nazara/Network/Win32/SocketPollerImpl.cpp index 5fa5ac5a2..f6272b246 100644 --- a/src/Nazara/Network/Win32/SocketPollerImpl.cpp +++ b/src/Nazara/Network/Win32/SocketPollerImpl.cpp @@ -130,9 +130,9 @@ namespace Nz #endif } - int SocketPollerImpl::Wait(int msTimeout, SocketError* error) + unsigned int SocketPollerImpl::Wait(int msTimeout, SocketError* error) { - int activeSockets; + unsigned int activeSockets; #if NAZARA_NETWORK_POLL_SUPPORT activeSockets = SocketImpl::Poll(m_sockets.data(), m_sockets.size(), static_cast(msTimeout), error); @@ -187,8 +187,8 @@ namespace Nz tv.tv_sec = static_cast(msTimeout / 1000ULL); tv.tv_usec = static_cast((msTimeout % 1000ULL) * 1000ULL); - activeSockets = ::select(0xDEADBEEF, readSet, writeSet, nullptr, (msTimeout >= 0) ? &tv : nullptr); //< The first argument is ignored on Windows - if (activeSockets == SOCKET_ERROR) + int selectValue = ::select(0xDEADBEEF, readSet, writeSet, nullptr, (msTimeout >= 0) ? &tv : nullptr); //< The first argument is ignored on Windows + if (selectValue == SOCKET_ERROR) { if (error) *error = SocketImpl::TranslateWSAErrorToSocketError(WSAGetLastError()); @@ -196,6 +196,9 @@ namespace Nz return 0; } + assert(selectValue >= 0); + activeSockets = static_cast(selectValue); + if (error) *error = SocketError_NoError; #endif diff --git a/src/Nazara/Network/Win32/SocketPollerImpl.hpp b/src/Nazara/Network/Win32/SocketPollerImpl.hpp index 2dfb32070..611548591 100644 --- a/src/Nazara/Network/Win32/SocketPollerImpl.hpp +++ b/src/Nazara/Network/Win32/SocketPollerImpl.hpp @@ -32,7 +32,7 @@ namespace Nz bool RegisterSocket(SocketHandle socket, SocketPollEventFlags eventFlags); void UnregisterSocket(SocketHandle socket); - int Wait(int msTimeout, SocketError* error); + unsigned int Wait(int msTimeout, SocketError* error); private: #if NAZARA_NETWORK_POLL_SUPPORT