]> git.saurik.com Git - wxWidgets.git/blame - src/unix/sockunix.cpp
wxRTC: save and load the 'shown' status in case there's a situation where layout...
[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
51fe4b60
VZ
7// Copyright: (c) 1997 Guilhem Lavaux
8// (c) 2008 Vadim Zeitlin
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
97e6ee04 12
7e1e6965 13#include "wx/wxprec.h"
7e1e6965 14
ebf94940
VZ
15#if wxUSE_SOCKETS
16
ebf94940
VZ
17#include "wx/private/fd.h"
18#include "wx/private/socket.h"
60913641 19#include "wx/unix/private/sockunix.h"
97e6ee04 20
c9bccf23 21#include <errno.h>
97e6ee04 22
ebf94940 23#if defined(__WATCOMC__)
c9bccf23 24 #include <nerrno.h>
ebf94940 25#endif
02564412 26
97e6ee04 27#include <sys/types.h>
97e6ee04 28
bc023abb
MW
29#ifdef HAVE_SYS_SELECT_H
30# include <sys/select.h>
31#endif
32
ebdab982 33#ifdef __EMX__
c9bccf23 34 #include <sys/select.h>
d1f8e97b 35#endif
97e6ee04 36
9e03e02d 37#ifndef WX_SOCKLEN_T
97e6ee04
DE
38
39#ifdef VMS
9e03e02d 40# define WX_SOCKLEN_T unsigned int
97e6ee04
DE
41#else
42# ifdef __GLIBC__
43# if __GLIBC__ == 2
9e03e02d 44# define WX_SOCKLEN_T socklen_t
97e6ee04 45# endif
fcbd7e5a 46# elif defined(__WXMAC__)
9e03e02d 47# define WX_SOCKLEN_T socklen_t
97e6ee04 48# else
9e03e02d 49# define WX_SOCKLEN_T int
97e6ee04
DE
50# endif
51#endif
52
53#endif /* SOCKLEN_T */
54
ddc1a35f 55#ifndef SOCKOPTLEN_T
c9bccf23 56 #define SOCKOPTLEN_T WX_SOCKLEN_T
ddc1a35f
DE
57#endif
58
c9bccf23 59// UnixWare reportedly needs this for FIONBIO definition
97e6ee04 60#ifdef __UNIXWARE__
c9bccf23 61 #include <sys/filio.h>
2887cb4e 62#endif
71b4a9b8 63
62088a3c
VZ
64// ============================================================================
65// wxSocketImpl implementation
66// ============================================================================
67
2b036c4b 68wxSocketError wxSocketImplUnix::GetLastError() const
97e6ee04 69{
2b036c4b
VZ
70 switch ( errno )
71 {
72 case 0:
73 return wxSOCKET_NOERROR;
97e6ee04 74
2b036c4b
VZ
75 case ENOTSOCK:
76 return wxSOCKET_INVSOCK;
97e6ee04 77
42dfe2b2
VZ
78 // unfortunately EAGAIN only has the "would block" meaning for read(),
79 // not for connect() for which it means something rather different but
80 // we can't distinguish between these two situations currently...
14372de8
VZ
81 //
82 // also notice that EWOULDBLOCK can be different from EAGAIN on some
83 // systems (HP-UX being the only known example) while it's defined as
84 // EAGAIN on most others (e.g. Linux)
42dfe2b2 85 case EAGAIN:
14372de8
VZ
86#ifdef EWOULDBLOCK
87 #if EWOULDBLOCK != EAGAIN
88 case EWOULDBLOCK:
89 #endif
90#endif // EWOULDBLOCK
2b036c4b
VZ
91 case EINPROGRESS:
92 return wxSOCKET_WOULDBLOCK;
97e6ee04 93
2b036c4b
VZ
94 default:
95 return wxSOCKET_IOERR;
96 }
97e6ee04
DE
97}
98
df21920b 99void wxSocketImplUnix::DoEnableEvents(int flags, bool enable)
2804f77d 100{
51fe4b60 101 wxSocketManager * const manager = wxSocketManager::Get();
54e757fc
FM
102 if (!manager)
103 return;
104
df21920b 105 if ( enable )
f0fbbe23 106 {
df21920b
VZ
107 if ( flags & wxSOCKET_INPUT_FLAG )
108 manager->Install_Callback(this, wxSOCKET_INPUT);
109 if ( flags & wxSOCKET_OUTPUT_FLAG )
110 manager->Install_Callback(this, wxSOCKET_OUTPUT);
f0fbbe23
VZ
111 }
112 else // off
113 {
df21920b
VZ
114 if ( flags & wxSOCKET_INPUT_FLAG )
115 manager->Uninstall_Callback(this, wxSOCKET_INPUT);
116 if ( flags & wxSOCKET_OUTPUT_FLAG )
117 manager->Uninstall_Callback(this, wxSOCKET_OUTPUT);
60edcf45 118 }
60edcf45
VZ
119}
120
df21920b
VZ
121int wxSocketImplUnix::CheckForInput()
122{
123 char c;
124 int rc;
125 do
126 {
127 rc = recv(m_fd, &c, 1, MSG_PEEK);
128 } while ( rc == -1 && errno == EINTR );
129
130 return rc;
131}
97e6ee04 132
51fe4b60 133void wxSocketImplUnix::OnStateChange(wxSocketNotify event)
53a161e1 134{
53a161e1
VZ
135 NotifyOnStateChange(event);
136
51fe4b60 137 if ( event == wxSOCKET_LOST )
53a161e1
VZ
138 Shutdown();
139}
140
a9d859df 141void wxSocketImplUnix::OnReadWaiting()
97e6ee04 142{
df21920b
VZ
143 wxASSERT_MSG( m_fd != INVALID_SOCKET, "invalid socket ready for reading?" );
144
145 // we need to disable the read notifications until we read all the data
146 // already available for the socket, otherwise we're going to keep getting
147 // them continuously which is worse than inefficient: as IO notifications
148 // have higher priority than idle events in e.g. GTK+, our pending events
149 // whose handlers typically call Read() which would consume the data and so
150 // stop the notifications flood would never be dispatched at all if the
151 // notifications were not disabled
152 DisableEvents(wxSOCKET_INPUT_FLAG);
153
154
155 // find out what are we going to notify about exactly
156 wxSocketNotify notify;
157
158 // TCP listening sockets become ready for reading when there is a pending
159 // connection
160 if ( m_server && m_stream )
e37e082e 161 {
df21920b 162 notify = wxSOCKET_CONNECTION;
e37e082e 163 }
df21920b 164 else // check if there is really any input available
97e6ee04 165 {
df21920b
VZ
166 switch ( CheckForInput() )
167 {
168 case 1:
169 notify = wxSOCKET_INPUT;
170 break;
171
172 case 0:
173 // reading 0 bytes for a TCP socket means that the connection
174 // was closed by peer but for UDP it just means that we got an
175 // empty datagram
176 notify = m_stream ? wxSOCKET_LOST : wxSOCKET_INPUT;
177 break;
178
179 default:
180 wxFAIL_MSG( "unexpected CheckForInput() return value" );
181 // fall through
182
183 case -1:
184 if ( GetLastError() == wxSOCKET_WOULDBLOCK )
185 {
186 // just a spurious wake up
187 EnableEvents(wxSOCKET_INPUT_FLAG);
188 return;
189 }
190
191 notify = wxSOCKET_LOST;
192 }
97e6ee04 193 }
df21920b
VZ
194
195 OnStateChange(notify);
97e6ee04
DE
196}
197
a9d859df 198void wxSocketImplUnix::OnWriteWaiting()
97e6ee04 199{
df21920b 200 wxASSERT_MSG( m_fd != INVALID_SOCKET, "invalid socket ready for writing?" );
97e6ee04 201
df21920b
VZ
202 // see comment in the beginning of OnReadWaiting() above
203 DisableEvents(wxSOCKET_OUTPUT_FLAG);
97e6ee04 204
97e6ee04 205
df21920b
VZ
206 // check whether this is a notification for the completion of a
207 // non-blocking connect()
208 if ( m_establishing && !m_server )
97e6ee04 209 {
df21920b
VZ
210 m_establishing = false;
211
212 // check whether we connected successfully
213 int error;
214 SOCKOPTLEN_T len = sizeof(error);
215
216 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
217
218 if ( error )
219 {
220 OnStateChange(wxSOCKET_LOST);
221 return;
222 }
223
224 OnStateChange(wxSOCKET_CONNECTION);
97e6ee04 225 }
df21920b 226
51fe4b60 227 OnStateChange(wxSOCKET_OUTPUT);
97e6ee04
DE
228}
229
a9d859df
VZ
230void wxSocketImplUnix::OnExceptionWaiting()
231{
558e196c
VZ
232 // when using epoll() this is called when an error occurred on the socket
233 // so close it if it hadn't been done yet -- what else can we do?
234 //
235 // notice that we shouldn't be called at all when using select() as we
236 // don't use wxFDIO_EXCEPTION when registering the socket for monitoring
237 // and this is good because select() would call this for any OOB data which
238 // is not necessarily an error
239 if ( m_fd != INVALID_SOCKET )
240 OnStateChange(wxSOCKET_LOST);
a9d859df
VZ
241}
242
ebf94940 243#endif /* wxUSE_SOCKETS */