]> git.saurik.com Git - wxWidgets.git/blame - src/unix/sockunix.cpp
Refactor wxXRC to allow defining handlers outside of xrc library.
[wxWidgets.git] / src / unix / sockunix.cpp
CommitLineData
51fe4b60 1/////////////////////////////////////////////////////////////////////////////
60913641 2// Name: src/unix/sockunix.cpp
51fe4b60
VZ
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
97e6ee04 13
7e1e6965 14#include "wx/wxprec.h"
7e1e6965 15
ebf94940
VZ
16#if wxUSE_SOCKETS
17
ebf94940
VZ
18#include "wx/private/fd.h"
19#include "wx/private/socket.h"
60913641 20#include "wx/unix/private/sockunix.h"
97e6ee04 21
c9bccf23 22#include <errno.h>
97e6ee04 23
ebf94940 24#if defined(__WATCOMC__)
c9bccf23 25 #include <nerrno.h>
ebf94940 26#endif
02564412 27
97e6ee04 28#include <sys/types.h>
97e6ee04 29
bc023abb
MW
30#ifdef HAVE_SYS_SELECT_H
31# include <sys/select.h>
32#endif
33
ebdab982 34#ifdef __EMX__
c9bccf23 35 #include <sys/select.h>
d1f8e97b 36#endif
97e6ee04 37
9e03e02d 38#ifndef WX_SOCKLEN_T
97e6ee04
DE
39
40#ifdef VMS
9e03e02d 41# define WX_SOCKLEN_T unsigned int
97e6ee04
DE
42#else
43# ifdef __GLIBC__
44# if __GLIBC__ == 2
9e03e02d 45# define WX_SOCKLEN_T socklen_t
97e6ee04 46# endif
fcbd7e5a 47# elif defined(__WXMAC__)
9e03e02d 48# define WX_SOCKLEN_T socklen_t
97e6ee04 49# else
9e03e02d 50# define WX_SOCKLEN_T int
97e6ee04
DE
51# endif
52#endif
53
54#endif /* SOCKLEN_T */
55
ddc1a35f 56#ifndef SOCKOPTLEN_T
c9bccf23 57 #define SOCKOPTLEN_T WX_SOCKLEN_T
ddc1a35f
DE
58#endif
59
c9bccf23 60// UnixWare reportedly needs this for FIONBIO definition
97e6ee04 61#ifdef __UNIXWARE__
c9bccf23 62 #include <sys/filio.h>
2887cb4e 63#endif
71b4a9b8 64
62088a3c
VZ
65// ============================================================================
66// wxSocketImpl implementation
67// ============================================================================
68
2b036c4b 69wxSocketError wxSocketImplUnix::GetLastError() const
97e6ee04 70{
2b036c4b
VZ
71 switch ( errno )
72 {
73 case 0:
74 return wxSOCKET_NOERROR;
97e6ee04 75
2b036c4b
VZ
76 case ENOTSOCK:
77 return wxSOCKET_INVSOCK;
97e6ee04 78
42dfe2b2
VZ
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...
14372de8
VZ
82 //
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)
42dfe2b2 86 case EAGAIN:
14372de8
VZ
87#ifdef EWOULDBLOCK
88 #if EWOULDBLOCK != EAGAIN
89 case EWOULDBLOCK:
90 #endif
91#endif // EWOULDBLOCK
2b036c4b
VZ
92 case EINPROGRESS:
93 return wxSOCKET_WOULDBLOCK;
97e6ee04 94
2b036c4b
VZ
95 default:
96 return wxSOCKET_IOERR;
97 }
97e6ee04
DE
98}
99
df21920b 100void wxSocketImplUnix::DoEnableEvents(int flags, bool enable)
2804f77d 101{
51fe4b60 102 wxSocketManager * const manager = wxSocketManager::Get();
54e757fc
FM
103 if (!manager)
104 return;
105
df21920b 106 if ( enable )
f0fbbe23 107 {
df21920b
VZ
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);
f0fbbe23
VZ
112 }
113 else // off
114 {
df21920b
VZ
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);
60edcf45 119 }
60edcf45
VZ
120}
121
df21920b
VZ
122int wxSocketImplUnix::CheckForInput()
123{
124 char c;
125 int rc;
126 do
127 {
128 rc = recv(m_fd, &c, 1, MSG_PEEK);
129 } while ( rc == -1 && errno == EINTR );
130
131 return rc;
132}
97e6ee04 133
51fe4b60 134void wxSocketImplUnix::OnStateChange(wxSocketNotify event)
53a161e1 135{
53a161e1
VZ
136 NotifyOnStateChange(event);
137
51fe4b60 138 if ( event == wxSOCKET_LOST )
53a161e1
VZ
139 Shutdown();
140}
141
a9d859df 142void wxSocketImplUnix::OnReadWaiting()
97e6ee04 143{
df21920b
VZ
144 wxASSERT_MSG( m_fd != INVALID_SOCKET, "invalid socket ready for reading?" );
145
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);
154
155
156 // find out what are we going to notify about exactly
157 wxSocketNotify notify;
158
159 // TCP listening sockets become ready for reading when there is a pending
160 // connection
161 if ( m_server && m_stream )
e37e082e 162 {
df21920b 163 notify = wxSOCKET_CONNECTION;
e37e082e 164 }
df21920b 165 else // check if there is really any input available
97e6ee04 166 {
df21920b
VZ
167 switch ( CheckForInput() )
168 {
169 case 1:
170 notify = wxSOCKET_INPUT;
171 break;
172
173 case 0:
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
176 // empty datagram
177 notify = m_stream ? wxSOCKET_LOST : wxSOCKET_INPUT;
178 break;
179
180 default:
181 wxFAIL_MSG( "unexpected CheckForInput() return value" );
182 // fall through
183
184 case -1:
185 if ( GetLastError() == wxSOCKET_WOULDBLOCK )
186 {
187 // just a spurious wake up
188 EnableEvents(wxSOCKET_INPUT_FLAG);
189 return;
190 }
191
192 notify = wxSOCKET_LOST;
193 }
97e6ee04 194 }
df21920b
VZ
195
196 OnStateChange(notify);
97e6ee04
DE
197}
198
a9d859df 199void wxSocketImplUnix::OnWriteWaiting()
97e6ee04 200{
df21920b 201 wxASSERT_MSG( m_fd != INVALID_SOCKET, "invalid socket ready for writing?" );
97e6ee04 202
df21920b
VZ
203 // see comment in the beginning of OnReadWaiting() above
204 DisableEvents(wxSOCKET_OUTPUT_FLAG);
97e6ee04 205
97e6ee04 206
df21920b
VZ
207 // check whether this is a notification for the completion of a
208 // non-blocking connect()
209 if ( m_establishing && !m_server )
97e6ee04 210 {
df21920b
VZ
211 m_establishing = false;
212
213 // check whether we connected successfully
214 int error;
215 SOCKOPTLEN_T len = sizeof(error);
216
217 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
218
219 if ( error )
220 {
221 OnStateChange(wxSOCKET_LOST);
222 return;
223 }
224
225 OnStateChange(wxSOCKET_CONNECTION);
97e6ee04 226 }
df21920b 227
51fe4b60 228 OnStateChange(wxSOCKET_OUTPUT);
97e6ee04
DE
229}
230
a9d859df
VZ
231void wxSocketImplUnix::OnExceptionWaiting()
232{
558e196c
VZ
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?
235 //
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);
a9d859df
VZ
242}
243
ebf94940 244#endif /* wxUSE_SOCKETS */