| 272 | } |
| 273 | |
| 274 | static int waitForReadiness (std::atomic<int>& handle, CriticalSection& readLock, |
| 275 | bool forReading, int timeoutMsecs) noexcept |
| 276 | { |
| 277 | // avoid race-condition |
| 278 | CriticalSection::ScopedTryLockType lock (readLock); |
| 279 | |
| 280 | if (! lock.isLocked()) |
| 281 | return -1; |
| 282 | |
| 283 | auto hasErrorOccurred = [&handle]() -> bool |
| 284 | { |
| 285 | auto h = (SocketHandle) handle.load(); |
| 286 | |
| 287 | if (h == invalidSocket) |
| 288 | return true; |
| 289 | |
| 290 | int opt; |
| 291 | juce_socklen_t len = sizeof (opt); |
| 292 | |
| 293 | if (getsockopt (h, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 || opt != 0) |
| 294 | return true; |
| 295 | |
| 296 | return false; |
| 297 | }; |
| 298 | |
| 299 | auto h = handle.load(); |
| 300 | |
| 301 | #if JUCE_WINDOWS || JUCE_MINGW |
| 302 | struct timeval timeout; |
| 303 | struct timeval* timeoutp; |
| 304 | |
| 305 | if (timeoutMsecs >= 0) |
| 306 | { |
| 307 | timeout.tv_sec = timeoutMsecs / 1000; |
| 308 | timeout.tv_usec = (timeoutMsecs % 1000) * 1000; |
| 309 | timeoutp = &timeout; |
| 310 | } |
| 311 | else |
| 312 | { |
| 313 | timeoutp = nullptr; |
| 314 | } |
| 315 | |
| 316 | fd_set rset, wset; |
| 317 | FD_ZERO (&rset); |
| 318 | FD_SET ((SOCKET) h, &rset); |
| 319 | FD_ZERO (&wset); |
| 320 | FD_SET ((SOCKET) h, &wset); |
| 321 | |
| 322 | fd_set* prset = forReading ? &rset : nullptr; |
| 323 | fd_set* pwset = forReading ? nullptr : &wset; |
| 324 | |
| 325 | // NB - need to use select() here as WSAPoll is broken on Windows |
| 326 | if (select ((int) h + 1, prset, pwset, nullptr, timeoutp) < 0 || hasErrorOccurred()) |
| 327 | return -1; |
| 328 | |
| 329 | return FD_ISSET (h, forReading ? &rset : &wset) ? 1 : 0; |
| 330 | #else |
| 331 | short eventsFlag = (forReading ? POLLIN : POLLOUT); |
no test coverage detected