]>
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();
112 if ( flags
& wxSOCKET_INPUT_FLAG
)
113 manager
->Install_Callback(this, wxSOCKET_INPUT
);
114 if ( flags
& wxSOCKET_OUTPUT_FLAG
)
115 manager
->Install_Callback(this, wxSOCKET_OUTPUT
);
119 if ( flags
& wxSOCKET_INPUT_FLAG
)
120 manager
->Uninstall_Callback(this, wxSOCKET_INPUT
);
121 if ( flags
& wxSOCKET_OUTPUT_FLAG
)
122 manager
->Uninstall_Callback(this, wxSOCKET_OUTPUT
);
126 int wxSocketImplUnix::CheckForInput()
132 rc
= recv(m_fd
, &c
, 1, MSG_PEEK
);
133 } while ( rc
== -1 && errno
== EINTR
);
138 void wxSocketImplUnix::OnStateChange(wxSocketNotify event
)
140 NotifyOnStateChange(event
);
142 if ( event
== wxSOCKET_LOST
)
146 void wxSocketImplUnix::OnReadWaiting()
148 wxASSERT_MSG( m_fd
!= INVALID_SOCKET
, "invalid socket ready for reading?" );
150 // we need to disable the read notifications until we read all the data
151 // already available for the socket, otherwise we're going to keep getting
152 // them continuously which is worse than inefficient: as IO notifications
153 // have higher priority than idle events in e.g. GTK+, our pending events
154 // whose handlers typically call Read() which would consume the data and so
155 // stop the notifications flood would never be dispatched at all if the
156 // notifications were not disabled
157 DisableEvents(wxSOCKET_INPUT_FLAG
);
160 // find out what are we going to notify about exactly
161 wxSocketNotify notify
;
163 // TCP listening sockets become ready for reading when there is a pending
165 if ( m_server
&& m_stream
)
167 notify
= wxSOCKET_CONNECTION
;
169 else // check if there is really any input available
171 switch ( CheckForInput() )
174 notify
= wxSOCKET_INPUT
;
178 // reading 0 bytes for a TCP socket means that the connection
179 // was closed by peer but for UDP it just means that we got an
181 notify
= m_stream
? wxSOCKET_LOST
: wxSOCKET_INPUT
;
185 wxFAIL_MSG( "unexpected CheckForInput() return value" );
189 if ( GetLastError() == wxSOCKET_WOULDBLOCK
)
191 // just a spurious wake up
192 EnableEvents(wxSOCKET_INPUT_FLAG
);
196 notify
= wxSOCKET_LOST
;
200 OnStateChange(notify
);
203 void wxSocketImplUnix::OnWriteWaiting()
205 wxASSERT_MSG( m_fd
!= INVALID_SOCKET
, "invalid socket ready for writing?" );
207 // see comment in the beginning of OnReadWaiting() above
208 DisableEvents(wxSOCKET_OUTPUT_FLAG
);
211 // check whether this is a notification for the completion of a
212 // non-blocking connect()
213 if ( m_establishing
&& !m_server
)
215 m_establishing
= false;
217 // check whether we connected successfully
219 SOCKOPTLEN_T len
= sizeof(error
);
221 getsockopt(m_fd
, SOL_SOCKET
, SO_ERROR
, (char*)&error
, &len
);
225 OnStateChange(wxSOCKET_LOST
);
229 OnStateChange(wxSOCKET_CONNECTION
);
232 OnStateChange(wxSOCKET_OUTPUT
);
235 void wxSocketImplUnix::OnExceptionWaiting()
237 wxFAIL_MSG( "not supposed to be called" );
240 #endif /* wxUSE_SOCKETS */