]>
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,
7 // Copyright: (c) 1997 Guilhem Lavaux
8 // (c) 2008 Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #include "wx/wxprec.h"
17 #include "wx/private/fd.h"
18 #include "wx/private/socket.h"
19 #include "wx/unix/private/sockunix.h"
23 #if defined(__WATCOMC__)
27 #include <sys/types.h>
29 #ifdef HAVE_SYS_SELECT_H
30 # include <sys/select.h>
34 #include <sys/select.h>
40 # define WX_SOCKLEN_T unsigned int
44 # define WX_SOCKLEN_T socklen_t
46 # elif defined(__WXMAC__)
47 # define WX_SOCKLEN_T socklen_t
49 # define WX_SOCKLEN_T int
53 #endif /* SOCKLEN_T */
56 #define SOCKOPTLEN_T WX_SOCKLEN_T
59 // UnixWare reportedly needs this for FIONBIO definition
61 #include <sys/filio.h>
64 // ============================================================================
65 // wxSocketImpl implementation
66 // ============================================================================
68 wxSocketError
wxSocketImplUnix::GetLastError() const
73 return wxSOCKET_NOERROR
;
76 return wxSOCKET_INVSOCK
;
78 // unfortunately EAGAIN only has the "would block" meaning for read(),
79 // not for connect() for which it means something rather different but
80 // we can't distinguish between these two situations currently...
82 // also notice that EWOULDBLOCK can be different from EAGAIN on some
83 // systems (HP-UX being the only known example) while it's defined as
84 // EAGAIN on most others (e.g. Linux)
87 #if EWOULDBLOCK != EAGAIN
92 return wxSOCKET_WOULDBLOCK
;
95 return wxSOCKET_IOERR
;
99 void wxSocketImplUnix::DoEnableEvents(int flags
, bool enable
)
101 wxSocketManager
* const manager
= wxSocketManager::Get();
107 if ( flags
& wxSOCKET_INPUT_FLAG
)
108 manager
->Install_Callback(this, wxSOCKET_INPUT
);
109 if ( flags
& wxSOCKET_OUTPUT_FLAG
)
110 manager
->Install_Callback(this, wxSOCKET_OUTPUT
);
114 if ( flags
& wxSOCKET_INPUT_FLAG
)
115 manager
->Uninstall_Callback(this, wxSOCKET_INPUT
);
116 if ( flags
& wxSOCKET_OUTPUT_FLAG
)
117 manager
->Uninstall_Callback(this, wxSOCKET_OUTPUT
);
121 int wxSocketImplUnix::CheckForInput()
127 rc
= recv(m_fd
, &c
, 1, MSG_PEEK
);
128 } while ( rc
== -1 && errno
== EINTR
);
133 void wxSocketImplUnix::OnStateChange(wxSocketNotify event
)
135 NotifyOnStateChange(event
);
137 if ( event
== wxSOCKET_LOST
)
141 void wxSocketImplUnix::OnReadWaiting()
143 wxASSERT_MSG( m_fd
!= INVALID_SOCKET
, "invalid socket ready for reading?" );
145 // we need to disable the read notifications until we read all the data
146 // already available for the socket, otherwise we're going to keep getting
147 // them continuously which is worse than inefficient: as IO notifications
148 // have higher priority than idle events in e.g. GTK+, our pending events
149 // whose handlers typically call Read() which would consume the data and so
150 // stop the notifications flood would never be dispatched at all if the
151 // notifications were not disabled
152 DisableEvents(wxSOCKET_INPUT_FLAG
);
155 // find out what are we going to notify about exactly
156 wxSocketNotify notify
;
158 // TCP listening sockets become ready for reading when there is a pending
160 if ( m_server
&& m_stream
)
162 notify
= wxSOCKET_CONNECTION
;
164 else // check if there is really any input available
166 switch ( CheckForInput() )
169 notify
= wxSOCKET_INPUT
;
173 // reading 0 bytes for a TCP socket means that the connection
174 // was closed by peer but for UDP it just means that we got an
176 notify
= m_stream
? wxSOCKET_LOST
: wxSOCKET_INPUT
;
180 wxFAIL_MSG( "unexpected CheckForInput() return value" );
184 if ( GetLastError() == wxSOCKET_WOULDBLOCK
)
186 // just a spurious wake up
187 EnableEvents(wxSOCKET_INPUT_FLAG
);
191 notify
= wxSOCKET_LOST
;
195 OnStateChange(notify
);
198 void wxSocketImplUnix::OnWriteWaiting()
200 wxASSERT_MSG( m_fd
!= INVALID_SOCKET
, "invalid socket ready for writing?" );
202 // see comment in the beginning of OnReadWaiting() above
203 DisableEvents(wxSOCKET_OUTPUT_FLAG
);
206 // check whether this is a notification for the completion of a
207 // non-blocking connect()
208 if ( m_establishing
&& !m_server
)
210 m_establishing
= false;
212 // check whether we connected successfully
214 SOCKOPTLEN_T len
= sizeof(error
);
216 getsockopt(m_fd
, SOL_SOCKET
, SO_ERROR
, (char*)&error
, &len
);
220 OnStateChange(wxSOCKET_LOST
);
224 OnStateChange(wxSOCKET_CONNECTION
);
227 OnStateChange(wxSOCKET_OUTPUT
);
230 void wxSocketImplUnix::OnExceptionWaiting()
232 // when using epoll() this is called when an error occurred on the socket
233 // so close it if it hadn't been done yet -- what else can we do?
235 // notice that we shouldn't be called at all when using select() as we
236 // don't use wxFDIO_EXCEPTION when registering the socket for monitoring
237 // and this is good because select() would call this for any OOB data which
238 // is not necessarily an error
239 if ( m_fd
!= INVALID_SOCKET
)
240 OnStateChange(wxSOCKET_LOST
);
243 #endif /* wxUSE_SOCKETS */