1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Windows: Dynamically load WSAPoll method from Ws2_32.dll to restore compatibility with older Windows versions

This commit is contained in:
ed 2019-12-05 14:48:02 +00:00
parent 978faaca83
commit eb780b56b8

View file

@ -55,6 +55,24 @@ namespace juce
//==============================================================================
namespace SocketHelpers
{
#if JUCE_WINDOWS
using WSAPollFunc = int (WSAAPI*) (LPWSAPOLLFD, ULONG, INT);
static WSAPollFunc wsaPollFunc = nullptr;
static void checkForWSAPoll()
{
static bool hasChecked = false;
if (! hasChecked)
{
hasChecked = true;
if (auto* moduleHandle = GetModuleHandleW (L"Ws2_32.dll"))
wsaPollFunc = (WSAPollFunc) GetProcAddress (moduleHandle, "WSAPoll");
}
}
#endif
static void initSockets()
{
#if JUCE_WINDOWS
@ -67,6 +85,8 @@ namespace SocketHelpers
WSADATA wsaData;
const WORD wVersionRequested = MAKEWORD (1, 1);
WSAStartup (wVersionRequested, &wsaData);
checkForWSAPoll();
}
#endif
}
@ -286,9 +306,61 @@ namespace SocketHelpers
if (! lock.isLocked())
return -1;
auto hasErrorOccured = [&handle] () -> bool
{
auto h = handle.load();
if (h == invalidSocket)
return true;
int opt;
juce_socklen_t len = sizeof (opt);
if (getsockopt (h, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 || opt != 0)
return true;
return false;
};
auto h = handle.load();
#if JUCE_MINGW
#if ! JUCE_MINGW
#if JUCE_WINDOWS
if (wsaPollFunc != nullptr)
#endif
{
short eventsFlag = (forReading ? POLLIN : POLLOUT);
pollfd pfd { (SocketHandle) h, eventsFlag, 0 };
int result = 0;
for (;;)
{
#if JUCE_WINDOWS
result = SocketHelpers::wsaPollFunc (&pfd, 1, timeoutMsecs);
#else
result = poll (&pfd, 1, timeoutMsecs);
#endif
if (result >= 0
#if JUCE_WINDOWS
|| result == SOCKET_ERROR
#else
|| errno != EINTR
#endif
)
{
break;
}
}
if (result < 0 || hasErrorOccured())
return -1;
return (pfd.revents & eventsFlag) != 0;
}
#endif
struct timeval timeout;
struct timeval* timeoutp;
@ -309,59 +381,13 @@ namespace SocketHelpers
FD_ZERO (&wset);
FD_SET (h, &wset);
fd_set* const prset = forReading ? &rset : nullptr;
fd_set* const pwset = forReading ? nullptr : &wset;
fd_set* prset = forReading ? &rset : nullptr;
fd_set* pwset = forReading ? nullptr : &wset;
if (select ((int) h + 1, prset, pwset, 0, timeoutp) < 0)
return -1;
#else
short eventsFlag = (forReading ? POLLIN : POLLOUT);
pollfd pfd { (SocketHandle) h, eventsFlag, 0 };
int result = 0;
for (;;)
{
#if JUCE_WINDOWS
result = WSAPoll (&pfd, 1, timeoutMsecs);
#else
result = poll (&pfd, 1, timeoutMsecs);
#endif
if (result >= 0
#if JUCE_WINDOWS
|| result == SOCKET_ERROR
#else
|| errno != EINTR
#endif
)
{
break;
}
}
if (result < 0)
return -1;
#endif
// we are closing
if (handle.load() < 0)
if (select ((int) h + 1, prset, pwset, nullptr, timeoutp) < 0 || hasErrorOccured())
return -1;
{
int opt;
juce_socklen_t len = sizeof (opt);
if (getsockopt (h, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0
|| opt != 0)
return -1;
}
#if JUCE_MINGW
return FD_ISSET (h, forReading ? &rset : &wset) ? 1 : 0;
#else
return (pfd.revents & eventsFlag) != 0;
#endif
}
static addrinfo* getAddressInfo (bool isDatagram, const String& hostName, int portNumber)