]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/socket.cpp
call event.Enable(true) in OnUpdateFileOpen and OnUpdateFileNew only if there are...
[wxWidgets.git] / src / common / socket.cpp
index 18de1040e6c13bd8454bc4ed0834821f9c2f1fae..aba83174a42654305ee3cb51f8655c1cc7fa37a4 100644 (file)
@@ -42,6 +42,7 @@
 #include "wx/stopwatch.h"
 #include "wx/thread.h"
 #include "wx/evtloop.h"
+#include "wx/link.h"
 
 #include "wx/private/fd.h"
 #include "wx/private/socket.h"
 // this should cover all the current Unix systems (Windows never sends any
 // signals anyhow) but if we find one that has neither we should explicitly
 // ignore SIGPIPE for it
+// OpenVMS has neither MSG_NOSIGNAL nor SO_NOSIGPIPE. However the socket sample
+// seems to work. Not sure if problems will show up on OpenVMS using sockets.
 #ifdef MSG_NOSIGNAL
     #define wxSOCKET_MSG_NOSIGNAL MSG_NOSIGNAL
 #else // MSG_NOSIGNAL not available (BSD including OS X)
-    #if defined(__UNIX__) && !defined(SO_NOSIGPIPE)
+    #if defined(__UNIX__) && !defined(SO_NOSIGPIPE) && !defined( __VMS )
         #error "Writing to socket could generate unhandled SIGPIPE."
         #error "Please post information about your system to wx-dev."
     #endif
@@ -76,6 +79,9 @@ WX_CHECK_BUILD_OPTIONS("wxNet")
 // macros and constants
 // --------------------------------------------------------------------------
 
+// event
+wxDEFINE_EVENT(wxEVT_SOCKET, wxSocketEvent);
+
 // discard buffer
 #define MAX_DISCARD_SIZE (10 * 1024)
 
@@ -176,6 +182,8 @@ public:
     ~wxSocketReadGuard()
     {
         m_socket->m_reading = false;
+
+        m_socket->m_impl->ReenableEvents(wxSOCKET_INPUT_FLAG);
     }
 
 private:
@@ -193,6 +201,8 @@ public:
         wxASSERT_MSG( !m_socket->m_writing, "write reentrancy?" );
 
         m_socket->m_writing = true;
+
+        m_socket->m_impl->ReenableEvents(wxSOCKET_OUTPUT_FLAG);
     }
 
     ~wxSocketWriteGuard()
@@ -472,6 +482,10 @@ wxSocketImpl *wxSocketImpl::Accept(wxSocketBase& wxsocket)
     WX_SOCKLEN_T fromlen = sizeof(from);
     const SOCKET fd = accept(m_fd, &from.addr, &fromlen);
 
+    // accepting is similar to reading in the sense that it resets "ready for
+    // read" flag on the socket
+    ReenableEvents(wxSOCKET_INPUT_FLAG);
+
     if ( fd == INVALID_SOCKET )
         return NULL;
 
@@ -494,10 +508,6 @@ void wxSocketImpl::Close()
     }
 }
 
-/*
- *  Disallow further read/write operations on this socket, close
- *  the fd and disable all callbacks.
- */
 void wxSocketImpl::Shutdown()
 {
     if ( m_fd != INVALID_SOCKET )
@@ -760,7 +770,8 @@ void wxSocketBase::Init()
     {
         // this Initialize() will be undone by wxSocketModule::OnExit(), all
         // the other calls to it should be matched by a call to Shutdown()
-        Initialize();
+        if (!Initialize())
+            wxLogError("Cannot initialize wxSocketBase");
     }
 }
 
@@ -908,8 +919,7 @@ wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)
 
                 // otherwise wait until the socket becomes ready for reading or
                 // an error occurs on it
-                if ( !DoWaitWithTimeout(wxSOCKET_INPUT_FLAG |
-                                        wxSOCKET_LOST_FLAG) )
+                if ( !DoWaitWithTimeout(wxSOCKET_INPUT_FLAG) )
                 {
                     // and exit if the timeout elapsed before it did
                     SetError(wxSOCKET_TIMEDOUT);
@@ -1078,8 +1088,7 @@ wxUint32 wxSocketBase::DoWrite(const void *buffer_, wxUint32 nbytes)
                 if ( m_flags & wxSOCKET_NOWAIT )
                     break;
 
-                if ( !DoWaitWithTimeout(wxSOCKET_OUTPUT_FLAG |
-                                        wxSOCKET_LOST_FLAG) )
+                if ( !DoWaitWithTimeout(wxSOCKET_OUTPUT_FLAG) )
                 {
                     SetError(wxSOCKET_TIMEDOUT);
                     break;
@@ -1277,7 +1286,7 @@ wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags,
     return detected & flags;
 }
 
-bool
+int
 wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
 {
     // Use either the provided timeout or the default timeout value associated
@@ -1290,14 +1299,14 @@ wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
     return DoWait(timeout, flags);
 }
 
-bool
+int
 wxSocketBase::DoWait(long timeout, wxSocketEventFlags flags)
 {
-    wxCHECK_MSG( m_impl, false, "can't wait on invalid socket" );
+    wxCHECK_MSG( m_impl, -1, "can't wait on invalid socket" );
 
     // we're never going to become ready if we're not connected (any more)
     if ( !m_connected && !m_establishing )
-        return (flags & wxSOCKET_LOST_FLAG) != 0;
+        return -1;
 
     // This can be set to true from Interrupt() to exit this function a.s.a.p.
     m_interrupt = false;
@@ -1322,8 +1331,8 @@ wxSocketBase::DoWait(long timeout, wxSocketEventFlags flags)
     // 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 )
+    int rc = 0;
+    for ( bool firstTime = true; !m_interrupt; firstTime = false )
     {
         long timeLeft = wxMilliClockToLong(timeEnd - wxGetLocalTimeMillis());
         if ( timeLeft < 0 )
@@ -1359,8 +1368,7 @@ wxSocketBase::DoWait(long timeout, wxSocketEventFlags flags)
         {
             m_connected = false;
             m_establishing = false;
-            if ( flags & wxSOCKET_LOST_FLAG )
-                gotEvent = true;
+            rc = -1;
             break;
         }
 
@@ -1372,29 +1380,27 @@ wxSocketBase::DoWait(long timeout, wxSocketEventFlags flags)
         {
             m_connected = true;
             m_establishing = false;
-            gotEvent = true;
+            rc = true;
             break;
         }
 
         // Data available or output buffer ready?
         if ( (events & wxSOCKET_INPUT_FLAG) || (events & wxSOCKET_OUTPUT_FLAG) )
         {
-            gotEvent = true;
+            rc = true;
             break;
         }
     }
 
-    return gotEvent;
+    return rc;
 }
 
 bool wxSocketBase::Wait(long seconds, long milliseconds)
 {
     return DoWait(seconds, milliseconds,
-            wxSOCKET_INPUT_FLAG |
-            wxSOCKET_OUTPUT_FLAG |
-            wxSOCKET_CONNECTION_FLAG |
-            wxSOCKET_LOST_FLAG
-        );
+                  wxSOCKET_INPUT_FLAG |
+                  wxSOCKET_OUTPUT_FLAG |
+                  wxSOCKET_CONNECTION_FLAG) != 0;
 }
 
 bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
@@ -1410,11 +1416,7 @@ bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
     if ( m_impl->Select(wxSOCKET_INPUT_FLAG) )
         return true;
 
-    // Note that wxSOCKET_LOST_FLAG has to be explicitly passed to DoWait
-    // because of the semantics of WaitForRead: a return value of true means
-    // that a Read call will return immediately, not that there is
-    // actually data to read.
-    return DoWait(seconds, milliseconds, wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
+    return DoWait(seconds, milliseconds, wxSOCKET_INPUT_FLAG) != 0;
 }
 
 
@@ -1423,12 +1425,12 @@ bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
     if ( m_impl->Select(wxSOCKET_OUTPUT_FLAG) )
         return true;
 
-    return DoWait(seconds, milliseconds, wxSOCKET_OUTPUT_FLAG | wxSOCKET_LOST_FLAG);
+    return DoWait(seconds, milliseconds, wxSOCKET_OUTPUT_FLAG) != 0;
 }
 
 bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
 {
-    return DoWait(seconds, milliseconds, wxSOCKET_LOST_FLAG);
+    return DoWait(seconds, milliseconds, wxSOCKET_LOST_FLAG) == -1;
 }
 
 // --------------------------------------------------------------------------
@@ -1568,17 +1570,13 @@ void wxSocketBase::OnRequest(wxSocketNotify notification)
     // send the wx event if enabled and we're interested in it
     if ( m_notify && (m_eventmask & flag) && m_handler )
     {
-        // If we are in the middle of a R/W operation, do not propagate events
-        // to users. Also, filter 'late' events which are no longer valid.
-        if ( notification == wxSOCKET_INPUT )
+        // don't generate the events when we're inside DoWait() called from our
+        // own code as we are going to consume the data that has just become
+        // available ourselves and the user code won't see it at all
+        if ( (notification == wxSOCKET_INPUT && m_reading) ||
+                (notification == wxSOCKET_OUTPUT && m_writing) )
         {
-            if ( m_reading || !m_impl->Select(wxSOCKET_INPUT_FLAG) )
-                return;
-        }
-        else if ( notification == wxSOCKET_OUTPUT )
-        {
-            if ( m_writing || !m_impl->Select(wxSOCKET_OUTPUT_FLAG) )
-                return;
+            return;
         }
 
         wxSocketEvent event(m_id);
@@ -1765,7 +1763,7 @@ wxSocketBase *wxSocketServer::Accept(bool wait)
 
 bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
 {
-    return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG);
+    return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG) == 1;
 }
 
 bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
@@ -1813,10 +1811,6 @@ wxSocketClient::wxSocketClient(wxSocketFlags flags)
     m_initialSendBufferSize = -1;
 }
 
-wxSocketClient::~wxSocketClient()
-{
-}
-
 // --------------------------------------------------------------------------
 // Connect
 // --------------------------------------------------------------------------
@@ -1903,12 +1897,10 @@ bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
     wxCHECK_MSG( m_establishing && m_impl, false,
                  "No connection establishment attempt in progress" );
 
-    // we must specify wxSOCKET_LOST_FLAG here explicitly because we must return
-    // true if the connection establishment process is finished, whether it is
-    // over because we successfully connected or because we were not able to
-    // connect
-    return DoWait(seconds, milliseconds,
-        wxSOCKET_CONNECTION_FLAG | wxSOCKET_LOST_FLAG);
+    // notice that we return true even if DoWait() returned -1, i.e. if an
+    // error occurred and connection was lost: this is intentional as we should
+    // return false only if timeout expired without anything happening
+    return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG) != 0;
 }
 
 // ==========================================================================
@@ -1998,4 +1990,11 @@ private:
 
 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
 
+#if defined(wxUSE_SELECT_DISPATCHER) && wxUSE_SELECT_DISPATCHER
+// NOTE: we need to force linking against socketiohandler.cpp otherwise in
+//       static builds of wxWidgets the ManagerSetter::ManagerSetter ctor
+//       contained there wouldn't be ever called
+wxFORCE_LINK_MODULE( socketiohandler )
+#endif
+
 #endif // wxUSE_SOCKETS