]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/sockunix.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/sockunix.cpp 
   3 // Purpose:     wxSocketImpl implementation for Unix systems 
   4 // Authors:     Guilhem Lavaux, Guillermo Rodriguez Garcia, David Elliott, 
   8 // Copyright:   (c) 1997 Guilhem Lavaux 
   9 //              (c) 2008 Vadim Zeitlin 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  14 #include "wx/wxprec.h" 
  18 #include "wx/private/fd.h" 
  19 #include "wx/private/socket.h" 
  20 #include "wx/unix/private/sockunix.h" 
  24 #if defined(__WATCOMC__) 
  28 #include <sys/types.h> 
  30 #ifdef HAVE_SYS_SELECT_H 
  31 #   include <sys/select.h> 
  35     #include <sys/select.h> 
  41 #  define WX_SOCKLEN_T unsigned int 
  45 #      define WX_SOCKLEN_T socklen_t 
  47 #  elif defined(__WXMAC__) 
  48 #    define WX_SOCKLEN_T socklen_t 
  50 #    define WX_SOCKLEN_T int 
  54 #endif /* SOCKLEN_T */ 
  57     #define SOCKOPTLEN_T WX_SOCKLEN_T 
  60 // UnixWare reportedly needs this for FIONBIO definition 
  62     #include <sys/filio.h> 
  65 // ============================================================================ 
  66 // wxSocketImpl implementation 
  67 // ============================================================================ 
  69 wxSocketError 
wxSocketImplUnix::GetLastError() const 
  74             return wxSOCKET_NOERROR
; 
  77             return wxSOCKET_INVSOCK
; 
  79         // unfortunately EAGAIN only has the "would block" meaning for read(), 
  80         // not for connect() for which it means something rather different but 
  81         // we can't distinguish between these two situations currently... 
  83         // also notice that EWOULDBLOCK can be different from EAGAIN on some 
  84         // systems (HP-UX being the only known example) while it's defined as 
  85         // EAGAIN on most others (e.g. Linux) 
  88     #if EWOULDBLOCK != EAGAIN 
  93             return wxSOCKET_WOULDBLOCK
; 
  96             return wxSOCKET_IOERR
; 
 100 void wxSocketImplUnix::DoEnableEvents(int flags
, bool enable
) 
 102     wxSocketManager 
* const manager 
= wxSocketManager::Get(); 
 108         if ( flags 
& wxSOCKET_INPUT_FLAG 
) 
 109             manager
->Install_Callback(this, wxSOCKET_INPUT
); 
 110         if ( flags 
& wxSOCKET_OUTPUT_FLAG 
) 
 111             manager
->Install_Callback(this, wxSOCKET_OUTPUT
); 
 115         if ( flags 
& wxSOCKET_INPUT_FLAG 
) 
 116             manager
->Uninstall_Callback(this, wxSOCKET_INPUT
); 
 117         if ( flags 
& wxSOCKET_OUTPUT_FLAG 
) 
 118             manager
->Uninstall_Callback(this, wxSOCKET_OUTPUT
); 
 122 int wxSocketImplUnix::CheckForInput() 
 128         rc 
= recv(m_fd
, &c
, 1, MSG_PEEK
); 
 129     } while ( rc 
== -1 && errno 
== EINTR 
); 
 134 void wxSocketImplUnix::OnStateChange(wxSocketNotify event
) 
 136     NotifyOnStateChange(event
); 
 138     if ( event 
== wxSOCKET_LOST 
) 
 142 void wxSocketImplUnix::OnReadWaiting() 
 144     wxASSERT_MSG( m_fd 
!= INVALID_SOCKET
, "invalid socket ready for reading?" ); 
 146     // we need to disable the read notifications until we read all the data 
 147     // already available for the socket, otherwise we're going to keep getting 
 148     // them continuously which is worse than inefficient: as IO notifications 
 149     // have higher priority than idle events in e.g. GTK+, our pending events 
 150     // whose handlers typically call Read() which would consume the data and so 
 151     // stop the notifications flood would never be dispatched at all if the 
 152     // notifications were not disabled 
 153     DisableEvents(wxSOCKET_INPUT_FLAG
); 
 156     // find out what are we going to notify about exactly 
 157     wxSocketNotify notify
; 
 159     // TCP listening sockets become ready for reading when there is a pending 
 161     if ( m_server 
&& m_stream 
) 
 163         notify 
= wxSOCKET_CONNECTION
; 
 165     else // check if there is really any input available 
 167         switch ( CheckForInput() ) 
 170                 notify 
= wxSOCKET_INPUT
; 
 174                 // reading 0 bytes for a TCP socket means that the connection 
 175                 // was closed by peer but for UDP it just means that we got an 
 177                 notify 
= m_stream 
? wxSOCKET_LOST 
: wxSOCKET_INPUT
; 
 181                 wxFAIL_MSG( "unexpected CheckForInput() return value" ); 
 185                 if ( GetLastError() == wxSOCKET_WOULDBLOCK 
) 
 187                     // just a spurious wake up 
 188                     EnableEvents(wxSOCKET_INPUT_FLAG
); 
 192                 notify 
= wxSOCKET_LOST
; 
 196     OnStateChange(notify
); 
 199 void wxSocketImplUnix::OnWriteWaiting() 
 201     wxASSERT_MSG( m_fd 
!= INVALID_SOCKET
, "invalid socket ready for writing?" ); 
 203     // see comment in the beginning of OnReadWaiting() above 
 204     DisableEvents(wxSOCKET_OUTPUT_FLAG
); 
 207     // check whether this is a notification for the completion of a 
 208     // non-blocking connect() 
 209     if ( m_establishing 
&& !m_server 
) 
 211         m_establishing 
= false; 
 213         // check whether we connected successfully 
 215         SOCKOPTLEN_T len 
= sizeof(error
); 
 217         getsockopt(m_fd
, SOL_SOCKET
, SO_ERROR
, (char*)&error
, &len
); 
 221             OnStateChange(wxSOCKET_LOST
); 
 225         OnStateChange(wxSOCKET_CONNECTION
); 
 228     OnStateChange(wxSOCKET_OUTPUT
); 
 231 void wxSocketImplUnix::OnExceptionWaiting() 
 233     // when using epoll() this is called when an error occurred on the socket 
 234     // so close it if it hadn't been done yet -- what else can we do? 
 236     // notice that we shouldn't be called at all when using select() as we 
 237     // don't use wxFDIO_EXCEPTION when registering the socket for monitoring 
 238     // and this is good because select() would call this for any OOB data which 
 239     // is not necessarily an error 
 240     if ( m_fd 
!= INVALID_SOCKET 
) 
 241         OnStateChange(wxSOCKET_LOST
); 
 244 #endif  /* wxUSE_SOCKETS */