X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8907154c1a8a6882c6797d1f16393ddfb23e7f3a..c56ae04274fda26269c6d06be34cf59a45eb70ce:/src/common/socket.cpp diff --git a/src/common/socket.cpp b/src/common/socket.cpp index 43704880e8..05f337bfc3 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -36,7 +36,7 @@ #include "wx/sckaddr.h" #include "wx/socket.h" -#include "wx/stopwatch.h" +#include "wx/datetime.h" // DLL options compatibility check: #include "wx/build.h" @@ -95,7 +95,7 @@ public: public: wxSocketState() : wxObject() {} - DECLARE_NO_COPY_CLASS(wxSocketState) + DECLARE_NO_COPY_CLASS(wxSocketState) }; // ========================================================================== @@ -159,7 +159,7 @@ void wxSocketBase::Shutdown() { // we should be initialized wxASSERT_MSG( m_countInit, _T("extra call to Shutdown()") ); - if ( !--m_countInit ) + if ( --m_countInit == 0 ) { GSocket_Cleanup(); } @@ -694,9 +694,7 @@ bool wxSocketBase::_Wait(long seconds, else timeout = m_timeout * 1000; -#if !defined(wxUSE_GUI) || !wxUSE_GUI - m_socket->SetTimeout(timeout); -#endif + bool has_event_loop = wxTheApp ? (wxTheApp->GetTraits() ? true : false) : false; // Wait in an active polling loop. // @@ -708,8 +706,20 @@ bool wxSocketBase::_Wait(long seconds, // Do this at least once (important if timeout == 0, when // we are just polling). Also, if just polling, do not yield. - wxStopWatch chrono; + wxDateTime current_time = wxDateTime::UNow(); + unsigned int time_limit = (current_time.GetTicks() * 1000) + current_time.GetMillisecond() + timeout; bool done = false; + bool valid_result = false; + + if (!has_event_loop) + { + // This is used to avoid a busy loop on wxBase - having a select + // timeout of 50 ms per iteration should be enough. + if (timeout > 50) + m_socket->SetTimeout(50); + else + m_socket->SetTimeout(timeout); + } while (!done) { @@ -720,13 +730,15 @@ bool wxSocketBase::_Wait(long seconds, { m_connected = true; m_establishing = false; - return true; + valid_result = true; + break; } // Data available or output buffer ready if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG)) { - return true; + valid_result = true; + break; } // Connection lost @@ -734,17 +746,35 @@ bool wxSocketBase::_Wait(long seconds, { m_connected = false; m_establishing = false; - return (flags & GSOCK_LOST_FLAG) != 0; + valid_result = ((flags & GSOCK_LOST_FLAG) != 0); + break; } // Wait more? - if ((!timeout) || (chrono.Time() > timeout) || (m_interrupt)) + current_time = wxDateTime::UNow(); + int time_left = time_limit - ((current_time.GetTicks() * 1000) + current_time.GetMillisecond()); + if ((!timeout) || (time_left <= 0) || (m_interrupt)) done = true; else - PROCESS_EVENTS(); + { + if (has_event_loop) + { + PROCESS_EVENTS(); + } + else + { + // If there's less than 50 ms left, just call select with that timeout. + if (time_left < 50) + m_socket->SetTimeout(time_left); + } + } } - return false; + // Set timeout back to original value (we overwrote it for polling) + if (!has_event_loop) + m_socket->SetTimeout(m_timeout*1000); + + return valid_result; } bool wxSocketBase::Wait(long seconds, long milliseconds) @@ -762,7 +792,7 @@ bool wxSocketBase::WaitForRead(long seconds, long milliseconds) return true; // Note that GSOCK_INPUT_LOST has to be explicitly passed to - // _Wait becuase of the semantics of WaitForRead: a return + // _Wait because of the semantics of WaitForRead: a return // value of true means that a GSocket_Read call will return // immediately, not that there is actually data to read. @@ -1053,7 +1083,7 @@ wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek) // Ctor // -------------------------------------------------------------------------- -wxSocketServer::wxSocketServer(wxSockAddress& addr_man, +wxSocketServer::wxSocketServer(const wxSockAddress& addr_man, wxSocketFlags flags) : wxSocketBase(flags, wxSOCKET_SERVER) { @@ -1173,6 +1203,21 @@ bool wxSocketBase::SetOption(int level, int optname, const void *optval, return true; } +bool wxSocketBase::SetLocal(wxIPV4address& local) +{ + GAddress* la = local.GetAddress(); + + // If the address is valid, save it for use when we call Connect + if (la && la->m_addr) + { + m_localAddress = local; + + return true; + } + + return false; +} + // ========================================================================== // wxSocketClient // ========================================================================== @@ -1194,7 +1239,7 @@ wxSocketClient::~wxSocketClient() // Connect // -------------------------------------------------------------------------- -bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait) +bool wxSocketClient::DoConnect(wxSockAddress& addr_man, wxSockAddress* local, bool wait) { GSocketError err; @@ -1224,6 +1269,27 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait) if (!wait) m_socket->SetNonBlocking(1); + // Reuse makes sense for clients too, if we are trying to rebind to the same port + if (GetFlags() & wxSOCKET_REUSEADDR) + { + m_socket->SetReusable(); + } + + // If no local address was passed and one has been set, use the one that was Set + if (!local && m_localAddress.GetAddress()) + { + local = &m_localAddress; + } + + // Bind to the local IP address and port, when provided + if (local) + { + GAddress* la = local->GetAddress(); + + if (la && la->m_addr) + m_socket->SetLocal(la); + } + m_socket->SetPeer(addr_man.GetAddress()); err = m_socket->Connect(GSOCK_STREAMED); @@ -1242,6 +1308,16 @@ bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait) return true; } +bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait) +{ + return (DoConnect(addr_man, NULL, wait)); +} + +bool wxSocketClient::Connect(wxSockAddress& addr_man, wxSockAddress& local, bool wait) +{ + return (DoConnect(addr_man, &local, wait)); +} + bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds) { if (m_connected) // Already connected @@ -1260,7 +1336,7 @@ bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds) /* NOTE: experimental stuff - might change */ -wxDatagramSocket::wxDatagramSocket( wxSockAddress& addr, +wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr, wxSocketFlags flags ) : wxSocketBase( flags, wxSOCKET_DATAGRAM ) { @@ -1300,7 +1376,7 @@ wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr, return (*this); } -wxDatagramSocket& wxDatagramSocket::SendTo( wxSockAddress& addr, +wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr, const void* buf, wxUint32 nBytes ) {