diff --git a/src/SFML/Network/SocketSelector.cpp b/src/SFML/Network/SocketSelector.cpp index 51896544..980e825c 100644 --- a/src/SFML/Network/SocketSelector.cpp +++ b/src/SFML/Network/SocketSelector.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifdef _MSC_VER @@ -41,9 +42,10 @@ namespace sf //////////////////////////////////////////////////////////// struct SocketSelector::SocketSelectorImpl { - fd_set AllSockets; ///< Set containing all the sockets handles - fd_set SocketsReady; ///< Set containing handles of the sockets that are ready - int MaxSocket; ///< Maximum socket handle + fd_set allSockets; ///< Set containing all the sockets handles + fd_set socketsReady; ///< Set containing handles of the sockets that are ready + int maxSocket; ///< Maximum socket handle + int socketCount; ///< Number of socket handles }; @@ -76,20 +78,38 @@ void SocketSelector::add(Socket& socket) SocketHandle handle = socket.getHandle(); if (handle != priv::SocketImpl::invalidSocket()) { - if (handle < FD_SETSIZE) - { - FD_SET(handle, &m_impl->AllSockets); - int size = static_cast(handle); - if (size > m_impl->MaxSocket) - m_impl->MaxSocket = size; +#if defined(SFML_SYSTEM_WINDOWS) + + if (m_impl->socketCount >= FD_SETSIZE) + { + err() << "The socket can't be added to the selector because the " + << "selector is full. This is a limitation of your operating " + << "system's FD_SETSIZE setting."; + return; } - else + + if (FD_ISSET(handle, &m_impl->allSockets)) + return; + + m_impl->socketCount++; + +#else + + if (handle >= FD_SETSIZE) { err() << "The socket can't be added to the selector because its " << "ID is too high. This is a limitation of your operating " << "system's FD_SETSIZE setting."; + return; } + + // SocketHandle is an int in POSIX + m_impl->maxSocket = std::max(m_impl->maxSocket, handle); + +#endif + + FD_SET(handle, &m_impl->allSockets); } } @@ -97,18 +117,38 @@ void SocketSelector::add(Socket& socket) //////////////////////////////////////////////////////////// void SocketSelector::remove(Socket& socket) { - FD_CLR(socket.getHandle(), &m_impl->AllSockets); - FD_CLR(socket.getHandle(), &m_impl->SocketsReady); + SocketHandle handle = socket.getHandle(); + if (handle != priv::SocketImpl::invalidSocket()) + { + +#if defined(SFML_SYSTEM_WINDOWS) + + if (!FD_ISSET(handle, &m_impl->allSockets)) + return; + + m_impl->socketCount--; + +#else + + if (handle >= FD_SETSIZE) + return; + +#endif + + FD_CLR(handle, &m_impl->allSockets); + FD_CLR(handle, &m_impl->socketsReady); + } } //////////////////////////////////////////////////////////// void SocketSelector::clear() { - FD_ZERO(&m_impl->AllSockets); - FD_ZERO(&m_impl->SocketsReady); + FD_ZERO(&m_impl->allSockets); + FD_ZERO(&m_impl->socketsReady); - m_impl->MaxSocket = 0; + m_impl->maxSocket = 0; + m_impl->socketCount = 0; } @@ -121,10 +161,11 @@ bool SocketSelector::wait(Time timeout) time.tv_usec = static_cast(timeout.asMicroseconds() % 1000000); // Initialize the set that will contain the sockets that are ready - m_impl->SocketsReady = m_impl->AllSockets; + m_impl->socketsReady = m_impl->allSockets; // Wait until one of the sockets is ready for reading, or timeout is reached - int count = select(m_impl->MaxSocket + 1, &m_impl->SocketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL); + // The first parameter is ignored on Windows + int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL); return count > 0; } @@ -133,7 +174,21 @@ bool SocketSelector::wait(Time timeout) //////////////////////////////////////////////////////////// bool SocketSelector::isReady(Socket& socket) const { - return FD_ISSET(socket.getHandle(), &m_impl->SocketsReady) != 0; + SocketHandle handle = socket.getHandle(); + if (handle != priv::SocketImpl::invalidSocket()) + { + +#if !defined(SFML_SYSTEM_WINDOWS) + + if (handle >= FD_SETSIZE) + return false; + +#endif + + return FD_ISSET(handle, &m_impl->socketsReady) != 0; + } + + return false; }