]>
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 */