+ wxSocketEventFlags detected = 0;
+ if ( preadfds && wxFD_ISSET(m_fd, preadfds) )
+ detected |= wxSOCKET_INPUT_FLAG;
+
+ if ( pwritefds && wxFD_ISSET(m_fd, pwritefds) )
+ {
+ // check for the case of non-blocking connect()
+ if ( m_establishing && !m_server )
+ {
+ int error;
+ SOCKOPTLEN_T len = sizeof(error);
+ m_establishing = false;
+ getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
+
+ if ( error )
+ detected = wxSOCKET_LOST_FLAG;
+ else
+ detected |= wxSOCKET_CONNECTION_FLAG;
+ }
+ else // not called to get non-blocking connect() status
+ {
+ detected |= wxSOCKET_OUTPUT_FLAG;
+ }
+ }
+
+ return detected & flags;
+}
+
+bool
+wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
+{
+ wxCHECK_MSG( m_impl, false, "can't wait on invalid socket" );
+
+ // This can be set to true from Interrupt() to exit this function a.s.a.p.
+ m_interrupt = false;
+
+
+ // Use either the provided timeout or the default timeout value associated
+ // with this socket.
+ //
+ // TODO: allow waiting forever, see #9443
+ const long timeout = seconds == -1 ? m_timeout * 1000
+ : seconds * 1000 + milliseconds;
+ const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
+
+ // Get the active event loop which we'll use for the message dispatching
+ // when running in the main thread unless this was explicitly disabled by
+ // setting wxSOCKET_BLOCK flag
+ wxEventLoopBase *eventLoop;
+ if ( !(m_flags & wxSOCKET_BLOCK) && wxIsMainThread() )
+ {
+ eventLoop = wxEventLoop::GetActive();
+ }
+ else // in worker thread
+ {
+ // We never dispatch messages from threads other than the main one.
+ eventLoop = NULL;
+ }
+
+ // Wait until we receive the event we're waiting for or the timeout expires
+ // (but note that we always execute the loop at least once, even if timeout
+ // is 0 as this is used for polling)
+ bool gotEvent = false;
+ for ( bool firstTime = true; !m_interrupt ; firstTime = false )
+ {
+ long timeLeft = wxMilliClockToLong(timeEnd - wxGetLocalTimeMillis());
+ if ( timeLeft < 0 )
+ {
+ if ( !firstTime )
+ break; // timed out
+
+ timeLeft = 0;
+ }
+
+ // This function is only called if wxSOCKET_BLOCK flag was not used and
+ // so we should dispatch the events if there is an event loop capable
+ // of doing it.
+ wxSocketEventFlags events;
+ if ( eventLoop )
+ {
+ // reset them before starting to wait
+ m_eventsgot = 0;
+
+ eventLoop->DispatchTimeout(timeLeft);
+
+ events = m_eventsgot;
+ }
+ else // no event loop or waiting in another thread
+ {
+ // as explained below, we should always check for wxSOCKET_LOST_FLAG
+ timeval tv;
+ SetTimeValFromMS(tv, timeLeft);
+ events = m_impl->Select(flags | wxSOCKET_LOST_FLAG, &tv);
+ }
+
+ // always check for wxSOCKET_LOST_FLAG, even if flags doesn't include
+ // it, as continuing to wait for anything else after getting it is
+ // pointless
+ if ( events & wxSOCKET_LOST_FLAG )
+ {
+ m_connected = false;
+ m_establishing = false;
+ if ( flags & wxSOCKET_LOST_FLAG )
+ gotEvent = true;
+ break;
+ }
+
+ // otherwise mask out the bits we're not interested in
+ events &= flags;
+
+ // Incoming connection (server) or connection established (client)?
+ if ( events & wxSOCKET_CONNECTION_FLAG )
+ {
+ m_connected = true;
+ m_establishing = false;
+ gotEvent = true;
+ break;
+ }
+
+ // Data available or output buffer ready?
+ if ( (events & wxSOCKET_INPUT_FLAG) || (events & wxSOCKET_OUTPUT_FLAG) )
+ {
+ gotEvent = true;
+ break;
+ }
+ }
+
+ return gotEvent;