]> git.saurik.com Git - wxWidgets.git/commitdiff
move Read/Write() to common code, there was almost nothing platform-specific in it
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 27 Dec 2008 22:49:46 +0000 (22:49 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 27 Dec 2008 22:49:46 +0000 (22:49 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57613 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/private/sockmsw.h
include/wx/private/socket.h
include/wx/unix/private/sockunix.h
src/common/socket.cpp
src/msw/sockmsw.cpp
src/unix/sockunix.cpp

index 5f722c50832d914c981dbf64dd61708d16333fcd..1c0a6fe6275592a5a84cd02af835170d8dfcf892 100644 (file)
@@ -39,9 +39,6 @@ public:
 
     virtual wxSocketError GetLastError() const;
 
-    virtual int Read(void *buffer, int size);
-    virtual int Write(const void *buffer, int size);
-
 private:
     virtual void DoClose();
 
@@ -52,11 +49,6 @@ private:
         wxSocketManager::Get()->Install_Callback(this);
     }
 
-    int Recv_Stream(void *buffer, int size);
-    int Recv_Dgram(void *buffer, int size);
-    int Send_Stream(const void *buffer, int size);
-    int Send_Dgram(const void *buffer, int size);
-
     int m_msgnumber;
 
     friend class wxSocketMSWManager;
index d546a91acc76f98c7cb6194836d4225e360e3881..d25f8d0481f3eab7c7853d40966bcd2e7ddcbbf0 100644 (file)
@@ -260,8 +260,11 @@ public:
     // IO operations
     // -------------
 
-    virtual int Read(void *buffer, int size) = 0;
-    virtual int Write(const void *buffer, int size) = 0;
+    // basic IO, work for both TCP and UDP sockets
+    //
+    // return the number of bytes read/written (possibly 0) or -1 on error
+    int Read(void *buffer, int size);
+    int Write(const void *buffer, int size);
 
     // basically a wrapper for select(): returns the condition of the socket,
     // blocking for not longer than timeout if it is specified (otherwise just
@@ -355,6 +358,12 @@ private:
     // update local address after binding/connecting
     wxSocketError UpdateLocalAddress();
 
+    // functions used to implement Read/Write()
+    int RecvStream(void *buffer, int size);
+    int RecvDgram(void *buffer, int size);
+    int SendStream(const void *buffer, int size);
+    int SendDgram(const void *buffer, int size);
+
 
     // set in ctor and never changed except that it's reset to NULL when the
     // socket is shut down
index d51d75f1303e8985e241e3c1f00855324d64bcbc..4ff2164b44912c16241d3093635d084b133d141d 100644 (file)
@@ -31,9 +31,6 @@ public:
 
     virtual wxSocketError GetLastError() const;
 
-    virtual int Read(void *buffer, int size);
-    virtual int Write(const void *buffer, int size);
-
     // wxFDIOHandler methods
     virtual void OnReadWaiting();
     virtual void OnWriteWaiting();
@@ -70,13 +67,6 @@ private:
     // really enable or disable socket input/output events
     void DoEnableEvents(bool enable);
 
-
-    int Recv_Stream(void *buffer, int size);
-    int Recv_Dgram(void *buffer, int size);
-    int Send_Stream(const void *buffer, int size);
-    int Send_Dgram(const void *buffer, int size);
-
-
 protected:
     // descriptors for input and output event notification channels associated
     // with the socket
index dd9cd502c046bda15bfa3ed66327c5b6589c5cd0..ccfb23438c8e0a7eaca52d6416c33440a1fa14b3 100644 (file)
 #include "wx/private/fd.h"
 #include "wx/private/socket.h"
 
+#ifdef __UNIX__
+    #include <errno.h>
+#endif
+
+// we use MSG_NOSIGNAL to avoid getting SIGPIPE when sending data to a remote
+// host which closed the connection if it is available, otherwise we rely on
+// SO_NOSIGPIPE existency
+//
+// 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
+#ifdef MSG_NOSIGNAL
+    #define wxSOCKET_MSG_NOSIGNAL MSG_NOSIGNAL
+#else // MSG_NOSIGNAL not available (BSD including OS X)
+    #if defined(__UNIX__) && !defined(SO_NOSIGPIPE)
+        #error "Writing to socket could generate unhandled SIGPIPE."
+        #error "Please post information about your system to wx-dev."
+    #endif
+
+    #define wxSOCKET_MSG_NOSIGNAL 0
+#endif
+
 // DLL options compatibility check:
 #include "wx/build.h"
 WX_CHECK_BUILD_OPTIONS("wxNet")
@@ -533,6 +555,136 @@ GAddress *wxSocketImpl::GetPeer()
   return NULL;
 }
 
+// ----------------------------------------------------------------------------
+// wxSocketImpl IO
+// ----------------------------------------------------------------------------
+
+// this macro wraps the given expression (normally a syscall) in a loop which
+// ignores any interruptions, i.e. reevaluates it again if it failed and errno
+// is EINTR
+#ifdef __UNIX__
+    #define DO_WHILE_EINTR( rc, syscall ) \
+        do { \
+            rc = (syscall); \
+        } \
+        while ( rc == -1 && errno == EINTR )
+#else
+    #define DO_WHILE_EINTR( rc, syscall ) rc = (syscall)
+#endif
+
+int wxSocketImpl::RecvStream(void *buffer, int size)
+{
+    int ret;
+    DO_WHILE_EINTR( ret, recv(m_fd, static_cast<char *>(buffer), size, 0) );
+
+    if ( !ret )
+    {
+        // receiving 0 bytes for a TCP socket indicates that the connection was
+        // closed by peer so shut down our end as well (for UDP sockets empty
+        // datagrams are also possible)
+        m_establishing = false;
+        NotifyOnStateChange(wxSOCKET_LOST);
+
+        Shutdown();
+
+        // do not return an error in this case however
+    }
+
+    return ret;
+}
+
+int wxSocketImpl::SendStream(const void *buffer, int size)
+{
+    int ret;
+    DO_WHILE_EINTR( ret, send(m_fd, static_cast<const char *>(buffer), size,
+                              wxSOCKET_MSG_NOSIGNAL) );
+
+    return ret;
+}
+
+int wxSocketImpl::RecvDgram(void *buffer, int size)
+{
+    wxSockAddr from;
+    WX_SOCKLEN_T fromlen = sizeof(from);
+
+    int ret;
+    DO_WHILE_EINTR( ret, recvfrom(m_fd, static_cast<char *>(buffer), size,
+                                  0, &from, &fromlen) );
+
+    if ( ret == SOCKET_ERROR )
+        return SOCKET_ERROR;
+
+    /* Translate a system address into a wxSocketImpl address */
+    if ( !m_peer )
+        m_peer = GAddress_new();
+
+    m_error = _GAddress_translate_from(m_peer, &from, fromlen);
+    if ( m_error != wxSOCKET_NOERROR )
+    {
+        GAddress_destroy(m_peer);
+        m_peer  = NULL;
+        return -1;
+    }
+
+    return ret;
+}
+
+int wxSocketImpl::SendDgram(const void *buffer, int size)
+{
+    if ( !m_peer )
+    {
+        m_error = wxSOCKET_INVADDR;
+        return -1;
+    }
+
+    struct sockaddr *addr;
+    int len;
+    m_error = _GAddress_translate_to(m_peer, &addr, &len);
+    if ( m_error != wxSOCKET_NOERROR )
+        return -1;
+
+    int ret;
+    DO_WHILE_EINTR( ret, sendto(m_fd, static_cast<const char *>(buffer), size,
+                                0, addr, len) );
+
+    free(addr);
+
+    return ret;
+}
+
+int wxSocketImpl::Read(void *buffer, int size)
+{
+    // server sockets can't be used for IO, only to accept new connections
+    if ( m_fd == INVALID_SOCKET || m_server )
+    {
+        m_error = wxSOCKET_INVSOCK;
+        return -1;
+    }
+
+    int ret = m_stream ? RecvStream(buffer, size)
+                       : RecvDgram(buffer, size);
+
+    m_error = ret == SOCKET_ERROR ? GetLastError() : wxSOCKET_NOERROR;
+
+    return ret;
+}
+
+int wxSocketImpl::Write(const void *buffer, int size)
+{
+    if ( m_fd == INVALID_SOCKET || m_server )
+    {
+        m_error = wxSOCKET_INVSOCK;
+        return -1;
+    }
+
+    int ret = m_stream ? SendStream(buffer, size)
+                       : SendDgram(buffer, size);
+
+    m_error = ret == SOCKET_ERROR ? GetLastError() : wxSOCKET_NOERROR;
+
+    return ret;
+}
+
 // ==========================================================================
 // wxSocketBase
 // ==========================================================================
index e0336fee603b86318a56444b43795c912ec088d3..dc20dcf9bad964c4c9d53dc562b6f3bcd206fcbd 100644 (file)
@@ -466,140 +466,6 @@ wxSocketError wxSocketImplMSW::GetLastError() const
     }
 }
 
-/* Generic IO */
-
-/* Like recv(), send(), ... */
-int wxSocketImplMSW::Read(void *buffer, int size)
-{
-  int ret;
-
-  if (m_fd == INVALID_SOCKET || m_server)
-  {
-    m_error = wxSOCKET_INVSOCK;
-    return -1;
-  }
-
-  /* Read the data */
-  if (m_stream)
-    ret = Recv_Stream(buffer, size);
-  else
-    ret = Recv_Dgram(buffer, size);
-
-  if (ret == SOCKET_ERROR)
-  {
-    if (WSAGetLastError() != WSAEWOULDBLOCK)
-      m_error = wxSOCKET_IOERR;
-    else
-      m_error = wxSOCKET_WOULDBLOCK;
-    return -1;
-  }
-
-  return ret;
-}
-
-int wxSocketImplMSW::Write(const void *buffer, int size)
-{
-  int ret;
-
-  if (m_fd == INVALID_SOCKET || m_server)
-  {
-    m_error = wxSOCKET_INVSOCK;
-    return -1;
-  }
-
-  /* Write the data */
-  if (m_stream)
-    ret = Send_Stream(buffer, size);
-  else
-    ret = Send_Dgram(buffer, size);
-
-  if (ret == SOCKET_ERROR)
-  {
-    if (WSAGetLastError() != WSAEWOULDBLOCK)
-      m_error = wxSOCKET_IOERR;
-    else
-      m_error = wxSOCKET_WOULDBLOCK;
-
-    return -1;
-  }
-
-  return ret;
-}
-
-/* Internals (IO) */
-
-int wxSocketImplMSW::Recv_Stream(void *buffer, int size)
-{
-    return recv(m_fd, static_cast<char *>(buffer), size, 0);
-}
-
-int wxSocketImplMSW::Recv_Dgram(void *buffer, int size)
-{
-  wxSockAddr from;
-  WX_SOCKLEN_T fromlen = sizeof(from);
-  int ret;
-  wxSocketError err;
-
-  ret = recvfrom(m_fd, static_cast<char *>(buffer),
-                 size, 0, &from, &fromlen);
-
-  if (ret == SOCKET_ERROR)
-    return SOCKET_ERROR;
-
-  /* Translate a system address into a wxSocketImpl address */
-  if (!m_peer)
-  {
-    m_peer = GAddress_new();
-    if (!m_peer)
-    {
-      m_error = wxSOCKET_MEMERR;
-      return -1;
-    }
-  }
-  err = _GAddress_translate_from(m_peer, (sockaddr*)&from, fromlen);
-  if (err != wxSOCKET_NOERROR)
-  {
-    GAddress_destroy(m_peer);
-    m_peer  = NULL;
-    m_error = err;
-    return -1;
-  }
-
-  return ret;
-}
-
-int wxSocketImplMSW::Send_Stream(const void *buffer, int size)
-{
-  return send(m_fd, static_cast<const char *>(buffer), size, 0);
-}
-
-int wxSocketImplMSW::Send_Dgram(const void *buffer, int size)
-{
-  struct sockaddr *addr;
-  int len, ret;
-  wxSocketError err;
-
-  if (!m_peer)
-  {
-    m_error = wxSOCKET_INVADDR;
-    return -1;
-  }
-
-  err = _GAddress_translate_to(m_peer, &addr, &len);
-  if (err != wxSOCKET_NOERROR)
-  {
-    m_error = err;
-    return -1;
-  }
-
-  ret = sendto(m_fd, static_cast<const char *>(buffer), size, 0, addr, len);
-
-  /* Frees memory allocated by _GAddress_translate_to */
-  free(addr);
-
-  return ret;
-}
-
 /*
  * -------------------------------------------------------------------------
  * GAddress
index 30a417ecc3537fd530806695e7c9b13f85dd1dac..d0020dfbdb31c2611b4ddfb60ef1d330339db554 100644 (file)
@@ -146,34 +146,6 @@ int _System soclose(int);
 #define INADDR_NONE INADDR_BROADCAST
 #endif
 
-#if defined(__VISAGECPP__) || defined(__WATCOMC__)
-
-    #define MASK_SIGNAL() {
-    #define UNMASK_SIGNAL() }
-
-#else
-    extern "C" { typedef void (*wxSigHandler)(int); }
-
-    #define MASK_SIGNAL()                       \
-    {                                           \
-        wxSigHandler old_handler = signal(SIGPIPE, SIG_IGN);
-
-    #define UNMASK_SIGNAL()                     \
-        signal(SIGPIPE, old_handler);           \
-    }
-
-#endif
-
-/* If a SIGPIPE is issued by a socket call on a remotely closed socket,
-   the program will "crash" unless it explicitly handles the SIGPIPE.
-   By using MSG_NOSIGNAL, the SIGPIPE is suppressed. Later, we will
-   use SO_NOSIGPIPE (if available), the BSD equivalent. */
-#ifdef MSG_NOSIGNAL
-#  define GSOCKET_MSG_NOSIGNAL MSG_NOSIGNAL
-#else /* MSG_NOSIGNAL not available (FreeBSD including OS X) */
-#  define GSOCKET_MSG_NOSIGNAL 0
-#endif /* MSG_NOSIGNAL */
-
 // ----------------------------------------------------------------------------
 // implementation of thread-safe/reentrant functions if they're missing
 // ----------------------------------------------------------------------------
@@ -452,7 +424,16 @@ wxSocketError wxSocketImplUnix::GetLastError() const
         // unfortunately EAGAIN only has the "would block" meaning for read(),
         // not for connect() for which it means something rather different but
         // we can't distinguish between these two situations currently...
+        //
+        // also notice that EWOULDBLOCK can be different from EAGAIN on some
+        // systems (HP-UX being the only known example) while it's defined as
+        // EAGAIN on most others (e.g. Linux)
         case EAGAIN:
+#ifdef EWOULDBLOCK
+    #if EWOULDBLOCK != EAGAIN
+        case EWOULDBLOCK:
+    #endif
+#endif // EWOULDBLOCK
         case EINPROGRESS:
             return wxSOCKET_WOULDBLOCK;
 
@@ -476,188 +457,6 @@ void wxSocketImplUnix::DoEnableEvents(bool flag)
     }
 }
 
-/* Generic IO */
-
-/* Like recv(), send(), ... */
-int wxSocketImplUnix::Read(void *buffer, int size)
-{
-  int ret;
-
-  if (m_fd == INVALID_SOCKET || m_server)
-  {
-    m_error = wxSOCKET_INVSOCK;
-    return -1;
-  }
-
-  /* Read the data */
-  if (m_stream)
-      ret = Recv_Stream(buffer, size);
-  else
-      ret = Recv_Dgram(buffer, size);
-
-  /*
-   * If recv returned zero for a TCP socket (if m_stream == NULL, it's an UDP
-   * socket and empty datagrams are possible), then the connection has been
-   * gracefully closed.
-   *
-   * Otherwise, recv has returned an error (-1), in which case we have lost
-   * the socket only if errno does _not_ indicate that there may be more data
-   * to read.
-   */
-  if ((ret == 0) && m_stream)
-  {
-      m_establishing = false;
-      OnStateChange(wxSOCKET_LOST);
-      return 0;
-  }
-  else if (ret == -1)
-  {
-      if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
-          m_error = wxSOCKET_WOULDBLOCK;
-      else
-          m_error = wxSOCKET_IOERR;
-  }
-
-  return ret;
-}
-
-int wxSocketImplUnix::Write(const void *buffer, int size)
-{
-  int ret;
-
-  if (m_fd == INVALID_SOCKET || m_server)
-  {
-    m_error = wxSOCKET_INVSOCK;
-    return -1;
-  }
-
-  /* Write the data */
-  if (m_stream)
-    ret = Send_Stream(buffer, size);
-  else
-    ret = Send_Dgram(buffer, size);
-
-  if (ret == -1)
-  {
-    if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
-    {
-      m_error = wxSOCKET_WOULDBLOCK;
-    }
-    else
-    {
-      m_error = wxSOCKET_IOERR;
-    }
-  }
-
-  return ret;
-}
-
-/* Flags */
-
-int wxSocketImplUnix::Recv_Stream(void *buffer, int size)
-{
-  int ret;
-  do
-  {
-    ret = recv(m_fd, buffer, size, GSOCKET_MSG_NOSIGNAL);
-  }
-  while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
-
-  return ret;
-}
-
-int wxSocketImplUnix::Recv_Dgram(void *buffer, int size)
-{
-  wxSockAddr from;
-  WX_SOCKLEN_T fromlen = sizeof(from);
-  int ret;
-  wxSocketError err;
-
-  fromlen = sizeof(from);
-
-  do
-  {
-    ret = recvfrom(m_fd, buffer, size, 0, (sockaddr*)&from, (WX_SOCKLEN_T *) &fromlen);
-  }
-  while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
-
-  if (ret == -1)
-    return -1;
-
-  /* Translate a system address into a wxSocketImplUnix address */
-  if (!m_peer)
-  {
-    m_peer = GAddress_new();
-    if (!m_peer)
-    {
-      m_error = wxSOCKET_MEMERR;
-      return -1;
-    }
-  }
-
-  err = _GAddress_translate_from(m_peer, (sockaddr*)&from, fromlen);
-  if (err != wxSOCKET_NOERROR)
-  {
-    GAddress_destroy(m_peer);
-    m_peer  = NULL;
-    m_error = err;
-    return -1;
-  }
-
-  return ret;
-}
-
-int wxSocketImplUnix::Send_Stream(const void *buffer, int size)
-{
-  int ret;
-
-  MASK_SIGNAL();
-
-  do
-  {
-    ret = send(m_fd, buffer, size, GSOCKET_MSG_NOSIGNAL);
-  }
-  while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
-
-  UNMASK_SIGNAL();
-
-  return ret;
-}
-
-int wxSocketImplUnix::Send_Dgram(const void *buffer, int size)
-{
-  struct sockaddr *addr;
-  int len, ret;
-  wxSocketError err;
-
-  if (!m_peer)
-  {
-    m_error = wxSOCKET_INVADDR;
-    return -1;
-  }
-
-  err = _GAddress_translate_to(m_peer, &addr, &len);
-  if (err != wxSOCKET_NOERROR)
-  {
-    m_error = err;
-    return -1;
-  }
-
-  MASK_SIGNAL();
-
-  do
-  {
-    ret = sendto(m_fd, buffer, size, 0, addr, len);
-  }
-  while (ret == -1 && errno == EINTR); /* Loop until not interrupted */
-
-  UNMASK_SIGNAL();
-
-  /* Frees memory allocated from _GAddress_translate_to */
-  free(addr);
-
-  return ret;
-}
 
 void wxSocketImplUnix::OnStateChange(wxSocketNotify event)
 {
@@ -676,7 +475,7 @@ void wxSocketImplUnix::OnReadWaiting()
     return;
   }
 
-  int num =  recv(m_fd, &c, 1, MSG_PEEK | GSOCKET_MSG_NOSIGNAL);
+  int num =  recv(m_fd, &c, 1, MSG_PEEK);
 
   if (num > 0)
   {