X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2b036c4b2365723b4c52890bd4c2f6bde20bbc00..41d0b41d6873cb50b7b025beb0cf9476d680004c:/src/unix/sockunix.cpp diff --git a/src/unix/sockunix.cpp b/src/unix/sockunix.cpp index 60143e73a1..d0020dfbdb 100644 --- a/src/unix/sockunix.cpp +++ b/src/unix/sockunix.cpp @@ -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,6 +400,10 @@ struct servent *wxGetservbyname_r(const char *port, const char *protocol, return se; } +// ============================================================================ +// wxSocketImpl implementation +// ============================================================================ + /* static */ wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket) { @@ -431,18 +411,6 @@ 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(); -} - wxSocketError wxSocketImplUnix::GetLastError() const { switch ( errno ) @@ -453,6 +421,19 @@ wxSocketError wxSocketImplUnix::GetLastError() const 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; @@ -476,220 +457,9 @@ 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; - } - - /* Disable events during query of socket status */ - DisableEvent(wxSOCKET_INPUT); - - /* 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 */ - 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; - - 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; - } - - /* 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; - } - - return ret; -} - -/* Flags */ - -void wxSocketImplUnix::EnableEvent(wxSocketNotify event) -{ - m_detected &= ~(1 << event); - wxSocketManager::Get()->Install_Callback(this, event); -} - -void wxSocketImplUnix::DisableEvent(wxSocketNotify event) -{ - 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 ) @@ -705,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) { @@ -758,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;