]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/unix/sockunix.cpp
no need to check for wxID_HELP buttons in SetLabel() now that it's overridden in...
[wxWidgets.git] / src / unix / sockunix.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/unix/sockunix.cpp
3// Purpose: wxSocketImpl implementation for Unix systems
4// Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia, David Elliott,
5// Vadim Zeitlin
6// Created: April 1997
7// RCS-ID: $Id$
8// Copyright: (c) 1997 Guilhem Lavaux
9// (c) 2008 Vadim Zeitlin
10// Licence: wxWindows licence
11/////////////////////////////////////////////////////////////////////////////
12
13
14#include "wx/wxprec.h"
15
16#if wxUSE_SOCKETS
17
18#include "wx/private/fd.h"
19#include "wx/private/socket.h"
20#include "wx/unix/private/sockunix.h"
21
22#include <errno.h>
23
24#if defined(__WATCOMC__)
25 #include <nerrno.h>
26#endif
27
28#include <sys/types.h>
29
30#ifdef HAVE_SYS_SELECT_H
31# include <sys/select.h>
32#endif
33
34#ifdef __EMX__
35 #include <sys/select.h>
36#endif
37
38#ifndef WX_SOCKLEN_T
39
40#ifdef VMS
41# define WX_SOCKLEN_T unsigned int
42#else
43# ifdef __GLIBC__
44# if __GLIBC__ == 2
45# define WX_SOCKLEN_T socklen_t
46# endif
47# elif defined(__WXMAC__)
48# define WX_SOCKLEN_T socklen_t
49# else
50# define WX_SOCKLEN_T int
51# endif
52#endif
53
54#endif /* SOCKLEN_T */
55
56#ifndef SOCKOPTLEN_T
57 #define SOCKOPTLEN_T WX_SOCKLEN_T
58#endif
59
60// UnixWare reportedly needs this for FIONBIO definition
61#ifdef __UNIXWARE__
62 #include <sys/filio.h>
63#endif
64
65// ============================================================================
66// wxSocketImpl implementation
67// ============================================================================
68
69/* static */
70wxSocketImpl *wxSocketImpl::Create(wxSocketBase& wxsocket)
71{
72 return new wxSocketImplUnix(wxsocket);
73}
74
75
76wxSocketError wxSocketImplUnix::GetLastError() const
77{
78 switch ( errno )
79 {
80 case 0:
81 return wxSOCKET_NOERROR;
82
83 case ENOTSOCK:
84 return wxSOCKET_INVSOCK;
85
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...
89 //
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)
93 case EAGAIN:
94#ifdef EWOULDBLOCK
95 #if EWOULDBLOCK != EAGAIN
96 case EWOULDBLOCK:
97 #endif
98#endif // EWOULDBLOCK
99 case EINPROGRESS:
100 return wxSOCKET_WOULDBLOCK;
101
102 default:
103 return wxSOCKET_IOERR;
104 }
105}
106
107void wxSocketImplUnix::DoEnableEvents(int flags, bool enable)
108{
109 wxSocketManager * const manager = wxSocketManager::Get();
110 if (!manager)
111 return;
112
113 if ( enable )
114 {
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);
119 }
120 else // off
121 {
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);
126 }
127}
128
129int wxSocketImplUnix::CheckForInput()
130{
131 char c;
132 int rc;
133 do
134 {
135 rc = recv(m_fd, &c, 1, MSG_PEEK);
136 } while ( rc == -1 && errno == EINTR );
137
138 return rc;
139}
140
141void wxSocketImplUnix::OnStateChange(wxSocketNotify event)
142{
143 NotifyOnStateChange(event);
144
145 if ( event == wxSOCKET_LOST )
146 Shutdown();
147}
148
149void wxSocketImplUnix::OnReadWaiting()
150{
151 wxASSERT_MSG( m_fd != INVALID_SOCKET, "invalid socket ready for reading?" );
152
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);
161
162
163 // find out what are we going to notify about exactly
164 wxSocketNotify notify;
165
166 // TCP listening sockets become ready for reading when there is a pending
167 // connection
168 if ( m_server && m_stream )
169 {
170 notify = wxSOCKET_CONNECTION;
171 }
172 else // check if there is really any input available
173 {
174 switch ( CheckForInput() )
175 {
176 case 1:
177 notify = wxSOCKET_INPUT;
178 break;
179
180 case 0:
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
183 // empty datagram
184 notify = m_stream ? wxSOCKET_LOST : wxSOCKET_INPUT;
185 break;
186
187 default:
188 wxFAIL_MSG( "unexpected CheckForInput() return value" );
189 // fall through
190
191 case -1:
192 if ( GetLastError() == wxSOCKET_WOULDBLOCK )
193 {
194 // just a spurious wake up
195 EnableEvents(wxSOCKET_INPUT_FLAG);
196 return;
197 }
198
199 notify = wxSOCKET_LOST;
200 }
201 }
202
203 OnStateChange(notify);
204}
205
206void wxSocketImplUnix::OnWriteWaiting()
207{
208 wxASSERT_MSG( m_fd != INVALID_SOCKET, "invalid socket ready for writing?" );
209
210 // see comment in the beginning of OnReadWaiting() above
211 DisableEvents(wxSOCKET_OUTPUT_FLAG);
212
213
214 // check whether this is a notification for the completion of a
215 // non-blocking connect()
216 if ( m_establishing && !m_server )
217 {
218 m_establishing = false;
219
220 // check whether we connected successfully
221 int error;
222 SOCKOPTLEN_T len = sizeof(error);
223
224 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
225
226 if ( error )
227 {
228 OnStateChange(wxSOCKET_LOST);
229 return;
230 }
231
232 OnStateChange(wxSOCKET_CONNECTION);
233 }
234
235 OnStateChange(wxSOCKET_OUTPUT);
236}
237
238void wxSocketImplUnix::OnExceptionWaiting()
239{
240 wxFAIL_MSG( "not supposed to be called" );
241}
242
243#endif /* wxUSE_SOCKETS */