]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/sockunix.cpp
no change, just add comment about wxTheColourDatabase deletion
[wxWidgets.git] / src / unix / sockunix.cpp
index c56accdc7acf736c56c982bdfea279a8f366d50a..d0020dfbdb31c2611b4ddfb60ef1d330339db554 100644 (file)
@@ -146,33 +146,9 @@ 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
+// ----------------------------------------------------------------------------
 
 #if wxUSE_THREADS && (defined(HAVE_GETHOSTBYNAME) || defined(HAVE_GETSERVBYNAME))
 #  include "wx/thread.h"
@@ -424,12 +400,9 @@ struct servent *wxGetservbyname_r(const char *port, const char *protocol,
   return se;
 }
 
-/* debugging helpers */
-#ifdef __GSOCKET_DEBUG__
-#  define SOCKET_DEBUG(args) printf args
-#else
-#  define SOCKET_DEBUG(args)
-#endif /* __GSOCKET_DEBUG__ */
+// ============================================================================
+// wxSocketImpl implementation
+// ============================================================================
 
 /* static */
 wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
@@ -438,115 +411,35 @@ wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
 }
 
 
-/*
- *  Disallow further read/write operations on this socket, close
- *  the fd and disable all callbacks.
- */
-void wxSocketImplUnix::Shutdown()
-{
-    /* Don't allow events to fire after socket has been closed */
-    DisableEvents();
-
-    wxSocketImpl::Shutdown();
-}
-
-/*
- *  Waits for an incoming client connection. Returns a pointer to
- *  a wxSocketImplUnix object, or NULL if there was an error, in which case
- *  the last error field will be updated for the calling wxSocketImplUnix.
- *
- *  Error codes (set in the calling wxSocketImplUnix)
- *    wxSOCKET_INVSOCK    - the socket is not valid or not a server.
- *    wxSOCKET_TIMEDOUT   - timeout, no incoming connections.
- *    wxSOCKET_WOULDBLOCK - the call would block and the socket is nonblocking.
- *    wxSOCKET_MEMERR     - couldn't allocate memory.
- *    wxSOCKET_IOERR      - low-level error.
- */
-wxSocketImpl *wxSocketImplUnix::WaitConnection(wxSocketBase& wxsocket)
-{
-  wxSockAddr from;
-  WX_SOCKLEN_T fromlen = sizeof(from);
-  wxSocketImpl *connection;
-  wxSocketError err;
-  int arg = 1;
-
-  /* If the socket has already been created, we exit immediately */
-  if (m_fd == INVALID_SOCKET || !m_server)
-  {
-    m_error = wxSOCKET_INVSOCK;
-    return NULL;
-  }
-
-  /* Create a wxSocketImplUnix object for the new connection */
-  connection = wxSocketImplUnix::Create(wxsocket);
-
-  if (!connection)
-  {
-    m_error = wxSOCKET_MEMERR;
-    return NULL;
-  }
-
-  /* Wait for a connection (with timeout) */
-  if ( !BlockForInputWithTimeout() )
-  {
-    delete connection;
-    return NULL;
-  }
-
-  connection->m_fd = accept(m_fd, (sockaddr*)&from, (WX_SOCKLEN_T *) &fromlen);
-
-  /* Reenable CONNECTION events */
-  EnableEvent(wxSOCKET_CONNECTION);
-
-  if (connection->m_fd == INVALID_SOCKET)
-  {
-    if (errno == EWOULDBLOCK)
-      m_error = wxSOCKET_WOULDBLOCK;
-    else
-      m_error = wxSOCKET_IOERR;
-
-    delete connection;
-    return NULL;
-  }
-
-  /* Initialize all fields */
-  connection->m_server   = false;
-  connection->m_stream   = true;
-
-  /* Setup the peer address field */
-  connection->m_peer = GAddress_new();
-  if (!connection->m_peer)
-  {
-    delete connection;
-    m_error = wxSOCKET_MEMERR;
-    return NULL;
-  }
-
-  err = _GAddress_translate_from(connection->m_peer, (sockaddr*)&from, fromlen);
-  if (err != wxSOCKET_NOERROR)
-  {
-    delete connection;
-    m_error = err;
-    return NULL;
-  }
-
-#if defined(__EMX__) || defined(__VISAGECPP__)
-  ioctl(connection->m_fd, FIONBIO, (char*)&arg, sizeof(arg));
-#else
-  ioctl(connection->m_fd, FIONBIO, &arg);
-#endif
-  if (m_use_events)
-    connection->Notify(true);
-
-  return connection;
-}
-
-void wxSocketImplUnix::Notify(bool flag)
+wxSocketError wxSocketImplUnix::GetLastError() const
 {
-    if (flag == m_use_events)
-        return;
-    m_use_events = flag;
-    DoEnableEvents(flag);
+    switch ( errno )
+    {
+        case 0:
+            return wxSOCKET_NOERROR;
+
+        case ENOTSOCK:
+            return wxSOCKET_INVSOCK;
+
+        // 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;
+
+        default:
+            return wxSOCKET_IOERR;
+    }
 }
 
 void wxSocketImplUnix::DoEnableEvents(bool flag)
@@ -564,320 +457,9 @@ void wxSocketImplUnix::DoEnableEvents(bool flag)
     }
 }
 
-wxSocketError wxSocketImplUnix::DoHandleConnect(int ret)
-{
-  /* We only call EnableEvents() if we know we aren't shutting down the socket.
-   * NB: EnableEvents() needs to be called whether the socket is blocking or
-   * non-blocking, it just shouldn't be called prior to knowing there is a
-   * connection _if_ blocking sockets are being used.
-   * If connect above returns 0, we are already connected and need to make the
-   * call to EnableEvents() now.
-   */
-  if ( m_non_blocking || (ret == 0) )
-    EnableEvents();
-
-  if (ret == -1)
-  {
-    const int err = errno;
-
-    /* If connect failed with EINPROGRESS and the wxSocketImplUnix object
-     * is in blocking mode, we select() for the specified timeout
-     * checking for writability to see if the connection request
-     * completes.
-     */
-    if ((err == EINPROGRESS) && (!m_non_blocking))
-    {
-      if ( !BlockForOutputWithTimeout() )
-      {
-        Close();
-        return wxSOCKET_TIMEDOUT;
-      }
-
-      int error;
-      SOCKOPTLEN_T len = sizeof(error);
-
-      getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*) &error, &len);
-      EnableEvents();
-
-      if (!error)
-        return wxSOCKET_NOERROR;
-    }
-
-    /* If connect failed with EINPROGRESS and the wxSocketImplUnix object
-     * is set to nonblocking, we set m_error to wxSOCKET_WOULDBLOCK
-     * (and return wxSOCKET_WOULDBLOCK) but we don't close the socket;
-     * this way if the connection completes, a wxSOCKET_CONNECTION
-     * event will be generated, if enabled.
-     */
-    if ((err == EINPROGRESS) && (m_non_blocking))
-    {
-      m_establishing = true;
-      m_error = wxSOCKET_WOULDBLOCK;
-      return wxSOCKET_WOULDBLOCK;
-    }
-
-    /* If connect failed with an error other than EINPROGRESS,
-     * then the call to Connect has failed.
-     */
-    Close();
-    m_error = wxSOCKET_IOERR;
-
-    return wxSOCKET_IOERR;
-  }
-
-  return wxSOCKET_NOERROR;
-}
-
-/* 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;
-  }
-
-  /* Disable events during query of socket status */
-  DisableEvent(wxSOCKET_INPUT);
-
-  /* If the socket is blocking, wait for data (with a timeout) */
-  if ( !BlockForInputWithTimeout() )
-  {
-    m_error = wxSOCKET_TIMEDOUT;
-    /* Don't return here immediately, otherwise socket events would not be
-     * re-enabled! */
-    ret = -1;
-  }
-  else
-  {
-    /* 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)
-    {
-      /* Make sure wxSOCKET_LOST event gets sent and shut down the socket */
-      if (m_use_events)
-      {
-        m_detected = wxSOCKET_LOST_FLAG;
-        OnReadWaiting();
-        return 0;
-      }
-    }
-    else if (ret == -1)
-    {
-      if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
-        m_error = wxSOCKET_WOULDBLOCK;
-      else
-        m_error = wxSOCKET_IOERR;
-    }
-  }
-
-  /* Enable events again now that we are done processing */
-  EnableEvent(wxSOCKET_INPUT);
-
-  return ret;
-}
-
-int wxSocketImplUnix::Write(const void *buffer, int size)
-{
-  int ret;
-
-  SOCKET_DEBUG(( "Write #1, size %d\n", size ));
-
-  if (m_fd == INVALID_SOCKET || m_server)
-  {
-    m_error = wxSOCKET_INVSOCK;
-    return -1;
-  }
-
-  SOCKET_DEBUG(( "Write #2, size %d\n", size ));
-
-  /* If the socket is blocking, wait for writability (with a timeout) */
-  if ( !BlockForOutputWithTimeout() )
-    return -1;
-
-  SOCKET_DEBUG(( "Write #3, size %d\n", size ));
-
-  /* Write the data */
-  if (m_stream)
-    ret = Send_Stream(buffer, size);
-  else
-    ret = Send_Dgram(buffer, size);
-
-  SOCKET_DEBUG(( "Write #4, size %d\n", size ));
-
-  if (ret == -1)
-  {
-    if ((errno == EWOULDBLOCK) || (errno == EAGAIN))
-    {
-      m_error = wxSOCKET_WOULDBLOCK;
-      SOCKET_DEBUG(( "Write error WOULDBLOCK\n" ));
-    }
-    else
-    {
-      m_error = wxSOCKET_IOERR;
-      SOCKET_DEBUG(( "Write error IOERR\n" ));
-    }
-
-    /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
-     * in MSW). Once the first OUTPUT event is received, users can assume
-     * that the socket is writable until a read operation fails. Only then
-     * will further OUTPUT events be posted.
-     */
-    EnableEvent(wxSOCKET_OUTPUT);
-
-    return -1;
-  }
-
-  SOCKET_DEBUG(( "Write #5, size %d ret %d\n", size, ret ));
-
-  return ret;
-}
-
-/* Flags */
-
-void wxSocketImplUnix::EnableEvent(wxSocketNotify event)
-{
-    if (m_use_events)
-    {
-        m_detected &= ~(1 << event);
-        wxSocketManager::Get()->Install_Callback(this, event);
-    }
-}
-
-void wxSocketImplUnix::DisableEvent(wxSocketNotify event)
-{
-    if (m_use_events)
-    {
-        m_detected |= (1 << event);
-        wxSocketManager::Get()->Uninstall_Callback(this, event);
-    }
-}
-
-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)
 {
-    DisableEvent(event);
     NotifyOnStateChange(event);
 
     if ( event == wxSOCKET_LOST )
@@ -893,18 +475,7 @@ void wxSocketImplUnix::OnReadWaiting()
     return;
   }
 
-  /* If we have already detected a LOST event, then don't try
-   * to do any further processing.
-   */
-  if ((m_detected & wxSOCKET_LOST_FLAG) != 0)
-  {
-    m_establishing = false;
-
-    OnStateChange(wxSOCKET_LOST);
-    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)
   {
@@ -946,17 +517,6 @@ void wxSocketImplUnix::OnReadWaiting()
 
 void wxSocketImplUnix::OnWriteWaiting()
 {
-  /* If we have already detected a LOST event, then don't try
-   * to do any further processing.
-   */
-  if ((m_detected & wxSOCKET_LOST_FLAG) != 0)
-  {
-    m_establishing = false;
-
-    OnStateChange(wxSOCKET_LOST);
-    return;
-  }
-
   if (m_establishing && !m_server)
   {
     int error;