]>
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 // ============================================================================
70 wxSocketImpl
*wxSocketImpl::Create(wxSocketBase
& wxsocket
)
72 return new wxSocketImplUnix(wxsocket
);
76 wxSocketError
wxSocketImplUnix::GetLastError() const
81 return wxSOCKET_NOERROR
;
84 return wxSOCKET_INVSOCK
;
86 // unfortunately EAGAIN only has the "would block" meaning for read(),
87 // not for connect() for which it means something rather different but
88 // we can't distinguish between these two situations currently...
90 // also notice that EWOULDBLOCK can be different from EAGAIN on some
91 // systems (HP-UX being the only known example) while it's defined as
92 // EAGAIN on most others (e.g. Linux)
95 #if EWOULDBLOCK != EAGAIN
100 return wxSOCKET_WOULDBLOCK
;
103 return wxSOCKET_IOERR
;
107 void wxSocketImplUnix::DoEnableEvents(int flags
, bool enable
)
109 wxSocketManager
* const manager
= wxSocketManager::Get();
115 if ( flags
& wxSOCKET_INPUT_FLAG
)
116 manager
->Install_Callback(this, wxSOCKET_INPUT
);
117 if ( flags
& wxSOCKET_OUTPUT_FLAG
)
118 manager
->Install_Callback(this, wxSOCKET_OUTPUT
);
122 if ( flags
& wxSOCKET_INPUT_FLAG
)
123 manager
->Uninstall_Callback(this, wxSOCKET_INPUT
);
124 if ( flags
& wxSOCKET_OUTPUT_FLAG
)
125 manager
->Uninstall_Callback(this, wxSOCKET_OUTPUT
);
129 int wxSocketImplUnix::CheckForInput()
135 rc
= recv(m_fd
, &c
, 1, MSG_PEEK
);
136 } while ( rc
== -1 && errno
== EINTR
);
141 void wxSocketImplUnix::OnStateChange(wxSocketNotify event
)
143 NotifyOnStateChange(event
);
145 if ( event
== wxSOCKET_LOST
)
149 void wxSocketImplUnix::OnReadWaiting()
151 wxASSERT_MSG( m_fd
!= INVALID_SOCKET
, "invalid socket ready for reading?" );
153 // we need to disable the read notifications until we read all the data
154 // already available for the socket, otherwise we're going to keep getting
155 // them continuously which is worse than inefficient: as IO notifications
156 // have higher priority than idle events in e.g. GTK+, our pending events
157 // whose handlers typically call Read() which would consume the data and so
158 // stop the notifications flood would never be dispatched at all if the
159 // notifications were not disabled
160 DisableEvents(wxSOCKET_INPUT_FLAG
);
163 // find out what are we going to notify about exactly
164 wxSocketNotify notify
;
166 // TCP listening sockets become ready for reading when there is a pending
168 if ( m_server
&& m_stream
)
170 notify
= wxSOCKET_CONNECTION
;
172 else // check if there is really any input available
174 switch ( CheckForInput() )
177 notify
= wxSOCKET_INPUT
;
181 // reading 0 bytes for a TCP socket means that the connection
182 // was closed by peer but for UDP it just means that we got an
184 notify
= m_stream
? wxSOCKET_LOST
: wxSOCKET_INPUT
;
188 wxFAIL_MSG( "unexpected CheckForInput() return value" );
192 if ( GetLastError() == wxSOCKET_WOULDBLOCK
)
194 // just a spurious wake up
195 EnableEvents(wxSOCKET_INPUT_FLAG
);
199 notify
= wxSOCKET_LOST
;
203 OnStateChange(notify
);
206 void wxSocketImplUnix::OnWriteWaiting()
208 wxASSERT_MSG( m_fd
!= INVALID_SOCKET
, "invalid socket ready for writing?" );
210 // see comment in the beginning of OnReadWaiting() above
211 DisableEvents(wxSOCKET_OUTPUT_FLAG
);
214 // check whether this is a notification for the completion of a
215 // non-blocking connect()
216 if ( m_establishing
&& !m_server
)
218 m_establishing
= false;
220 // check whether we connected successfully
222 SOCKOPTLEN_T len
= sizeof(error
);
224 getsockopt(m_fd
, SOL_SOCKET
, SO_ERROR
, (char*)&error
, &len
);
228 OnStateChange(wxSOCKET_LOST
);
232 OnStateChange(wxSOCKET_CONNECTION
);
235 OnStateChange(wxSOCKET_OUTPUT
);
238 void wxSocketImplUnix::OnExceptionWaiting()
240 wxFAIL_MSG( "not supposed to be called" );
243 #endif /* wxUSE_SOCKETS */