]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
Fix uniconizing hidden top level windows in wxMSW.
[wxWidgets.git] / src / common / socket.cpp
CommitLineData
56d8adc0 1/////////////////////////////////////////////////////////////////////////////
7fb0a11d 2// Name: src/common/socket.cpp
f4ada568 3// Purpose: Socket handler classes
56d8adc0 4// Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
f4ada568 5// Created: April 1997
d3ea6527 6// Copyright: (C) 1999-1997, Guilhem Lavaux
51fe4b60
VZ
7// (C) 1999-2000, Guillermo Rodriguez Garcia
8// (C) 2008 Vadim Zeitlin
f4ada568 9// RCS_ID: $Id$
526954c5 10// Licence: wxWindows licence
56d8adc0
GRG
11/////////////////////////////////////////////////////////////////////////////
12
bffc1eaa
GRG
13// ==========================================================================
14// Declarations
15// ==========================================================================
16
fcc6dddd
JS
17// For compilers that support precompilation, includes "wx.h".
18#include "wx/wxprec.h"
19
20#ifdef __BORLANDC__
8e3f3880 21 #pragma hdrstop
fcc6dddd
JS
22#endif
23
35a4dab7
GL
24#if wxUSE_SOCKETS
25
df91131c
WS
26#include "wx/socket.h"
27
8e3f3880
WS
28#ifndef WX_PRECOMP
29 #include "wx/object.h"
df91131c 30 #include "wx/string.h"
88a7a4e1 31 #include "wx/intl.h"
e4db172a 32 #include "wx/log.h"
d5da0ce7 33 #include "wx/event.h"
670f9935 34 #include "wx/app.h"
de6185e2 35 #include "wx/utils.h"
c0badb70 36 #include "wx/timer.h"
02761f6c 37 #include "wx/module.h"
8e3f3880
WS
38#endif
39
e2478fde 40#include "wx/apptrait.h"
56d8adc0 41#include "wx/sckaddr.h"
4252569b 42#include "wx/stopwatch.h"
204abcd4 43#include "wx/thread.h"
2804f77d 44#include "wx/evtloop.h"
54e757fc 45#include "wx/link.h"
02564412 46
40e7c0b9 47#include "wx/private/fd.h"
60913641 48#include "wx/private/socket.h"
3b4183d8 49
14372de8
VZ
50#ifdef __UNIX__
51 #include <errno.h>
52#endif
53
54// we use MSG_NOSIGNAL to avoid getting SIGPIPE when sending data to a remote
55// host which closed the connection if it is available, otherwise we rely on
56// SO_NOSIGPIPE existency
57//
58// this should cover all the current Unix systems (Windows never sends any
59// signals anyhow) but if we find one that has neither we should explicitly
60// ignore SIGPIPE for it
66034aba
JJ
61// OpenVMS has neither MSG_NOSIGNAL nor SO_NOSIGPIPE. However the socket sample
62// seems to work. Not sure if problems will show up on OpenVMS using sockets.
14372de8
VZ
63#ifdef MSG_NOSIGNAL
64 #define wxSOCKET_MSG_NOSIGNAL MSG_NOSIGNAL
65#else // MSG_NOSIGNAL not available (BSD including OS X)
04b2ab1a 66 // next best possibility is to use SO_NOSIGPIPE socket option, this covers
335a0bc3
VZ
67 // BSD systems (including OS X) -- but if we don't have it neither (AIX and
68 // old HP-UX do not), we have to fall back to the old way of simply
69 // disabling SIGPIPE temporarily, so define a class to do it in a safe way
04b2ab1a 70 #if defined(__UNIX__) && !defined(SO_NOSIGPIPE)
a645ea88 71 extern "C" { typedef void (*wxSigHandler_t)(int); }
04b2ab1a
VZ
72 namespace
73 {
74 class IgnoreSignal
75 {
76 public:
77 // ctor disables the given signal
78 IgnoreSignal(int sig)
79 : m_handler(signal(sig, SIG_IGN)),
80 m_sig(sig)
81 {
82 }
83
84 // dtor restores the old handler
85 ~IgnoreSignal()
86 {
87 signal(m_sig, m_handler);
88 }
89
90 private:
a645ea88 91 const wxSigHandler_t m_handler;
04b2ab1a
VZ
92 const int m_sig;
93
94 wxDECLARE_NO_COPY_CLASS(IgnoreSignal);
95 };
96 } // anonymous namespace
335a0bc3
VZ
97
98 #define wxNEEDS_IGNORE_SIGPIPE
99 #endif // Unix without SO_NOSIGPIPE
14372de8
VZ
100
101 #define wxSOCKET_MSG_NOSIGNAL 0
102#endif
103
34fdf762
VS
104// DLL options compatibility check:
105#include "wx/build.h"
106WX_CHECK_BUILD_OPTIONS("wxNet")
107
bffc1eaa
GRG
108// --------------------------------------------------------------------------
109// macros and constants
110// --------------------------------------------------------------------------
ef57d866 111
3c778901
VZ
112// event
113wxDEFINE_EVENT(wxEVT_SOCKET, wxSocketEvent);
114
dc5c1114
GRG
115// discard buffer
116#define MAX_DISCARD_SIZE (10 * 1024)
96db102a 117
9a83f860 118#define wxTRACE_Socket wxT("wxSocket")
007c77ab 119
ef57d866 120// --------------------------------------------------------------------------
bffc1eaa 121// wxWin macros
ef57d866 122// --------------------------------------------------------------------------
81b92e17 123
a737331d
GL
124IMPLEMENT_CLASS(wxSocketBase, wxObject)
125IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
126IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
dc5c1114 127IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
a737331d 128IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
f4ada568 129
00414faf
VZ
130// ----------------------------------------------------------------------------
131// private functions
132// ----------------------------------------------------------------------------
133
134namespace
135{
136
137void SetTimeValFromMS(timeval& tv, unsigned long ms)
138{
139 tv.tv_sec = (ms / 1000);
140 tv.tv_usec = (ms % 1000) * 1000;
141}
142
143} // anonymous namespace
144
bffc1eaa
GRG
145// --------------------------------------------------------------------------
146// private classes
147// --------------------------------------------------------------------------
148
56d8adc0
GRG
149class wxSocketState : public wxObject
150{
a324a7bc 151public:
c2116a35
VZ
152 wxSocketFlags m_flags;
153 wxSocketEventFlags m_eventmask;
154 bool m_notify;
155 void *m_clientData;
a324a7bc
GL
156
157public:
c2116a35 158 wxSocketState() : wxObject() {}
22f3361e 159
c0c133e1 160 wxDECLARE_NO_COPY_CLASS(wxSocketState);
a324a7bc
GL
161};
162
365b8793
VZ
163// wxSocketWaitModeChanger: temporarily change the socket flags affecting its
164// wait mode
165class wxSocketWaitModeChanger
166{
167public:
168 // temporarily set the flags to include the flag value which may be either
169 // wxSOCKET_NOWAIT or wxSOCKET_WAITALL
170 wxSocketWaitModeChanger(wxSocketBase *socket, int flag)
171 : m_socket(socket),
172 m_oldflags(socket->GetFlags())
173
174 {
175 wxASSERT_MSG( flag == wxSOCKET_WAITALL || flag == wxSOCKET_NOWAIT,
176 "not a wait flag" );
177
178 // preserve wxSOCKET_BLOCK value when switching to wxSOCKET_WAITALL
179 // mode but not when switching to wxSOCKET_NOWAIT as the latter is
180 // incompatible with wxSOCKET_BLOCK
181 if ( flag != wxSOCKET_NOWAIT )
182 flag |= m_oldflags & wxSOCKET_BLOCK;
183
184 socket->SetFlags(flag);
185 }
186
187 ~wxSocketWaitModeChanger()
188 {
189 m_socket->SetFlags(m_oldflags);
190 }
191
192private:
193 wxSocketBase * const m_socket;
194 const int m_oldflags;
195
c0c133e1 196 wxDECLARE_NO_COPY_CLASS(wxSocketWaitModeChanger);
365b8793
VZ
197};
198
199// wxSocketRead/WriteGuard are instantiated before starting reading
200// from/writing to the socket
201class wxSocketReadGuard
202{
203public:
204 wxSocketReadGuard(wxSocketBase *socket)
205 : m_socket(socket)
206 {
207 wxASSERT_MSG( !m_socket->m_reading, "read reentrancy?" );
208
209 m_socket->m_reading = true;
210 }
211
212 ~wxSocketReadGuard()
213 {
214 m_socket->m_reading = false;
df21920b 215
f46a0165
VZ
216 // connection could have been lost while reading, in this case calling
217 // ReenableEvents() would assert and is not necessary anyhow
218 wxSocketImpl * const impl = m_socket->m_impl;
219 if ( impl && impl->m_fd != INVALID_SOCKET )
220 impl->ReenableEvents(wxSOCKET_INPUT_FLAG);
365b8793
VZ
221 }
222
223private:
224 wxSocketBase * const m_socket;
225
c0c133e1 226 wxDECLARE_NO_COPY_CLASS(wxSocketReadGuard);
365b8793
VZ
227};
228
229class wxSocketWriteGuard
230{
231public:
232 wxSocketWriteGuard(wxSocketBase *socket)
233 : m_socket(socket)
234 {
235 wxASSERT_MSG( !m_socket->m_writing, "write reentrancy?" );
236
237 m_socket->m_writing = true;
238 }
239
240 ~wxSocketWriteGuard()
241 {
242 m_socket->m_writing = false;
f46a0165
VZ
243
244 wxSocketImpl * const impl = m_socket->m_impl;
245 if ( impl && impl->m_fd != INVALID_SOCKET )
246 impl->ReenableEvents(wxSOCKET_OUTPUT_FLAG);
365b8793
VZ
247 }
248
249private:
250 wxSocketBase * const m_socket;
251
c0c133e1 252 wxDECLARE_NO_COPY_CLASS(wxSocketWriteGuard);
365b8793
VZ
253};
254
2804f77d 255// ============================================================================
51fe4b60 256// wxSocketManager
2804f77d
VZ
257// ============================================================================
258
51fe4b60 259wxSocketManager *wxSocketManager::ms_manager = NULL;
2804f77d
VZ
260
261/* static */
51fe4b60 262void wxSocketManager::Set(wxSocketManager *manager)
2804f77d
VZ
263{
264 wxASSERT_MSG( !ms_manager, "too late to set manager now" );
265
266 ms_manager = manager;
267}
268
269/* static */
51fe4b60 270void wxSocketManager::Init()
2804f77d
VZ
271{
272 wxASSERT_MSG( !ms_manager, "shouldn't be initialized twice" );
273
274 /*
275 Details: Initialize() creates a hidden window as a sink for socket
276 events, such as 'read completed'. wxMSW has only one message loop
277 for the main thread. If Initialize is called in a secondary thread,
278 the socket window will be created for the secondary thread, but
279 since there is no message loop on this thread, it will never
280 receive events and all socket operations will time out.
281 BTW, the main thread must not be stopped using sleep or block
282 on a semaphore (a bad idea in any case) or socket operations
283 will time out.
284
285 On the Mac side, Initialize() stores a pointer to the CFRunLoop for
286 the main thread. Because secondary threads do not have run loops,
287 adding event notifications to the "Current" loop would have no
288 effect at all, events would never fire.
289 */
290 wxASSERT_MSG( wxIsMainThread(),
291 "sockets must be initialized from the main thread" );
292
293 wxAppConsole * const app = wxAppConsole::GetInstance();
294 wxCHECK_RET( app, "sockets can't be initialized without wxApp" );
295
296 ms_manager = app->GetTraits()->GetSocketManager();
297}
298
eb97543d 299// ==========================================================================
51fe4b60 300// wxSocketImpl
eb97543d
VZ
301// ==========================================================================
302
51fe4b60 303wxSocketImpl::wxSocketImpl(wxSocketBase& wxsocket)
53a161e1 304 : m_wxsocket(&wxsocket)
eb97543d
VZ
305{
306 m_fd = INVALID_SOCKET;
51fe4b60 307 m_error = wxSOCKET_NOERROR;
eb97543d
VZ
308 m_server = false;
309 m_stream = true;
53a161e1
VZ
310
311 SetTimeout(wxsocket.GetTimeout() * 1000);
eb97543d
VZ
312
313 m_establishing = false;
314 m_reusable = false;
315 m_broadcast = false;
316 m_dobind = true;
317 m_initialRecvBufferSize = -1;
318 m_initialSendBufferSize = -1;
eb97543d
VZ
319}
320
51fe4b60 321wxSocketImpl::~wxSocketImpl()
eb97543d 322{
c9bccf23 323 if ( m_fd != INVALID_SOCKET )
eb97543d 324 Shutdown();
51fe4b60
VZ
325}
326
c9bccf23 327bool wxSocketImpl::PreCreateCheck(const wxSockAddressImpl& addr)
51fe4b60
VZ
328{
329 if ( m_fd != INVALID_SOCKET )
330 {
331 m_error = wxSOCKET_INVSOCK;
332 return false;
333 }
334
c9bccf23 335 if ( !addr.IsOk() )
51fe4b60
VZ
336 {
337 m_error = wxSOCKET_INVADDR;
338 return false;
339 }
340
341 return true;
342}
343
344void wxSocketImpl::PostCreation()
345{
346 // FreeBSD variants can't use MSG_NOSIGNAL, and instead use a socket option
347#ifdef SO_NOSIGPIPE
348 EnableSocketOption(SO_NOSIGPIPE);
349#endif
350
351 if ( m_reusable )
352 EnableSocketOption(SO_REUSEADDR);
353
354 if ( m_broadcast )
355 {
356 wxASSERT_MSG( !m_stream, "broadcasting is for datagram sockets only" );
357
358 EnableSocketOption(SO_BROADCAST);
359 }
360
361 if ( m_initialRecvBufferSize >= 0 )
362 SetSocketOption(SO_RCVBUF, m_initialRecvBufferSize);
363 if ( m_initialSendBufferSize >= 0 )
364 SetSocketOption(SO_SNDBUF, m_initialSendBufferSize);
eb97543d 365
2b036c4b
VZ
366 // we always put our sockets in unblocked mode and handle blocking
367 // ourselves in DoRead/Write() if wxSOCKET_WAITALL is specified
51fe4b60 368 UnblockAndRegisterWithEventLoop();
eb97543d
VZ
369}
370
51fe4b60
VZ
371wxSocketError wxSocketImpl::UpdateLocalAddress()
372{
7172db18
VZ
373 if ( !m_local.IsOk() )
374 {
375 // ensure that we have a valid object using the correct family: correct
376 // being the same one as our peer uses as we have no other way to
377 // determine it
378 m_local.Create(m_peer.GetFamily());
379 }
380
c9bccf23
VZ
381 WX_SOCKLEN_T lenAddr = m_local.GetLen();
382 if ( getsockname(m_fd, m_local.GetWritableAddr(), &lenAddr) != 0 )
51fe4b60
VZ
383 {
384 Close();
385 m_error = wxSOCKET_IOERR;
386 return m_error;
387 }
388
51fe4b60
VZ
389 return wxSOCKET_NOERROR;
390}
391
392wxSocketError wxSocketImpl::CreateServer()
393{
394 if ( !PreCreateCheck(m_local) )
395 return m_error;
396
397 m_server = true;
398 m_stream = true;
399
400 // do create the socket
c9bccf23 401 m_fd = socket(m_local.GetFamily(), SOCK_STREAM, 0);
51fe4b60
VZ
402
403 if ( m_fd == INVALID_SOCKET )
404 {
405 m_error = wxSOCKET_IOERR;
406 return wxSOCKET_IOERR;
407 }
408
409 PostCreation();
410
411 // and then bind to and listen on it
412 //
413 // FIXME: should we test for m_dobind here?
c9bccf23 414 if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 )
51fe4b60
VZ
415 m_error = wxSOCKET_IOERR;
416
417 if ( IsOk() )
418 {
419 if ( listen(m_fd, 5) != 0 )
420 m_error = wxSOCKET_IOERR;
421 }
422
423 if ( !IsOk() )
424 {
425 Close();
426 return m_error;
427 }
428
429 // finally retrieve the address we effectively bound to
430 return UpdateLocalAddress();
431}
432
2b036c4b 433wxSocketError wxSocketImpl::CreateClient(bool wait)
51fe4b60
VZ
434{
435 if ( !PreCreateCheck(m_peer) )
436 return m_error;
437
c9bccf23 438 m_fd = socket(m_peer.GetFamily(), SOCK_STREAM, 0);
51fe4b60
VZ
439
440 if ( m_fd == INVALID_SOCKET )
441 {
2b036c4b
VZ
442 m_error = wxSOCKET_IOERR;
443 return wxSOCKET_IOERR;
51fe4b60
VZ
444 }
445
446 PostCreation();
447
448 // If a local address has been set, then bind to it before calling connect
c9bccf23 449 if ( m_local.IsOk() )
51fe4b60 450 {
c9bccf23 451 if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 )
51fe4b60
VZ
452 {
453 Close();
454 m_error = wxSOCKET_IOERR;
455 return m_error;
456 }
457 }
458
2b036c4b 459 // Do connect now
c9bccf23 460 int rc = connect(m_fd, m_peer.GetAddr(), m_peer.GetLen());
2b036c4b
VZ
461 if ( rc == SOCKET_ERROR )
462 {
463 wxSocketError err = GetLastError();
464 if ( err == wxSOCKET_WOULDBLOCK )
465 {
466 m_establishing = true;
467
468 // block waiting for connection if we should (otherwise just return
469 // wxSOCKET_WOULDBLOCK to the caller)
470 if ( wait )
471 {
472 err = SelectWithTimeout(wxSOCKET_CONNECTION_FLAG)
473 ? wxSOCKET_NOERROR
474 : wxSOCKET_TIMEDOUT;
475 m_establishing = false;
476 }
477 }
478
479 m_error = err;
480 }
481 else // connected
482 {
483 m_error = wxSOCKET_NOERROR;
484 }
485
486 return m_error;
51fe4b60
VZ
487}
488
489
490wxSocketError wxSocketImpl::CreateUDP()
491{
492 if ( !PreCreateCheck(m_local) )
493 return m_error;
494
495 m_stream = false;
496 m_server = false;
497
c9bccf23 498 m_fd = socket(m_local.GetFamily(), SOCK_DGRAM, 0);
51fe4b60
VZ
499
500 if ( m_fd == INVALID_SOCKET )
501 {
502 m_error = wxSOCKET_IOERR;
503 return wxSOCKET_IOERR;
504 }
505
506 PostCreation();
507
508 if ( m_dobind )
509 {
c9bccf23 510 if ( bind(m_fd, m_local.GetAddr(), m_local.GetLen()) != 0 )
51fe4b60
VZ
511 {
512 Close();
513 m_error = wxSOCKET_IOERR;
514 return m_error;
515 }
516
517 return UpdateLocalAddress();
518 }
519
520 return wxSOCKET_NOERROR;
521}
522
2b036c4b
VZ
523wxSocketImpl *wxSocketImpl::Accept(wxSocketBase& wxsocket)
524{
c9bccf23 525 wxSockAddressStorage from;
2b036c4b 526 WX_SOCKLEN_T fromlen = sizeof(from);
c9bccf23 527 const SOCKET fd = accept(m_fd, &from.addr, &fromlen);
2b036c4b 528
df21920b
VZ
529 // accepting is similar to reading in the sense that it resets "ready for
530 // read" flag on the socket
531 ReenableEvents(wxSOCKET_INPUT_FLAG);
532
2b036c4b
VZ
533 if ( fd == INVALID_SOCKET )
534 return NULL;
535
4f260c9c
VZ
536 wxSocketManager * const manager = wxSocketManager::Get();
537 if ( !manager )
538 return NULL;
539
540 wxSocketImpl * const sock = manager->CreateSocket(wxsocket);
541 if ( !sock )
542 return NULL;
543
2b036c4b 544 sock->m_fd = fd;
c9bccf23 545 sock->m_peer = wxSockAddressImpl(from.addr, fromlen);
2b036c4b
VZ
546
547 sock->UnblockAndRegisterWithEventLoop();
548
549 return sock;
550}
551
51fe4b60
VZ
552
553void wxSocketImpl::Close()
f0fbbe23
VZ
554{
555 if ( m_fd != INVALID_SOCKET )
556 {
51fe4b60 557 DoClose();
f0fbbe23
VZ
558 m_fd = INVALID_SOCKET;
559 }
560}
561
51fe4b60 562void wxSocketImpl::Shutdown()
eb97543d
VZ
563{
564 if ( m_fd != INVALID_SOCKET )
565 {
566 shutdown(m_fd, 1 /* SD_SEND */);
567 Close();
568 }
eb97543d
VZ
569}
570
51fe4b60 571/*
53a161e1
VZ
572 * Sets the timeout for blocking calls. Time is expressed in
573 * milliseconds.
574 */
51fe4b60 575void wxSocketImpl::SetTimeout(unsigned long millis)
53a161e1 576{
00414faf 577 SetTimeValFromMS(m_timeout, millis);
53a161e1
VZ
578}
579
51fe4b60 580void wxSocketImpl::NotifyOnStateChange(wxSocketNotify event)
53a161e1 581{
51fe4b60 582 m_wxsocket->OnRequest(event);
53a161e1
VZ
583}
584
02564412 585/* Address handling */
c9bccf23 586wxSocketError wxSocketImpl::SetLocal(const wxSockAddressImpl& local)
02564412 587{
c9bccf23
VZ
588 /* the socket must be initialized, or it must be a server */
589 if (m_fd != INVALID_SOCKET && !m_server)
590 {
591 m_error = wxSOCKET_INVSOCK;
592 return wxSOCKET_INVSOCK;
593 }
02564412 594
c9bccf23
VZ
595 if ( !local.IsOk() )
596 {
597 m_error = wxSOCKET_INVADDR;
598 return wxSOCKET_INVADDR;
599 }
02564412 600
c9bccf23 601 m_local = local;
02564412 602
c9bccf23 603 return wxSOCKET_NOERROR;
02564412
VZ
604}
605
c9bccf23 606wxSocketError wxSocketImpl::SetPeer(const wxSockAddressImpl& peer)
02564412 607{
c9bccf23
VZ
608 if ( !peer.IsOk() )
609 {
610 m_error = wxSOCKET_INVADDR;
611 return wxSOCKET_INVADDR;
612 }
02564412 613
c9bccf23 614 m_peer = peer;
02564412 615
c9bccf23 616 return wxSOCKET_NOERROR;
02564412
VZ
617}
618
c9bccf23 619const wxSockAddressImpl& wxSocketImpl::GetLocal()
02564412 620{
c9bccf23
VZ
621 if ( !m_local.IsOk() )
622 UpdateLocalAddress();
02564412 623
c9bccf23 624 return m_local;
02564412
VZ
625}
626
14372de8
VZ
627// ----------------------------------------------------------------------------
628// wxSocketImpl IO
629// ----------------------------------------------------------------------------
630
631// this macro wraps the given expression (normally a syscall) in a loop which
632// ignores any interruptions, i.e. reevaluates it again if it failed and errno
633// is EINTR
634#ifdef __UNIX__
635 #define DO_WHILE_EINTR( rc, syscall ) \
636 do { \
637 rc = (syscall); \
638 } \
639 while ( rc == -1 && errno == EINTR )
640#else
641 #define DO_WHILE_EINTR( rc, syscall ) rc = (syscall)
642#endif
643
644int wxSocketImpl::RecvStream(void *buffer, int size)
645{
646 int ret;
647 DO_WHILE_EINTR( ret, recv(m_fd, static_cast<char *>(buffer), size, 0) );
648
649 if ( !ret )
650 {
651 // receiving 0 bytes for a TCP socket indicates that the connection was
652 // closed by peer so shut down our end as well (for UDP sockets empty
653 // datagrams are also possible)
654 m_establishing = false;
655 NotifyOnStateChange(wxSOCKET_LOST);
656
657 Shutdown();
658
659 // do not return an error in this case however
660 }
661
662 return ret;
663}
664
665int wxSocketImpl::SendStream(const void *buffer, int size)
666{
335a0bc3 667#ifdef wxNEEDS_IGNORE_SIGPIPE
04b2ab1a
VZ
668 IgnoreSignal ignore(SIGPIPE);
669#endif
670
14372de8
VZ
671 int ret;
672 DO_WHILE_EINTR( ret, send(m_fd, static_cast<const char *>(buffer), size,
673 wxSOCKET_MSG_NOSIGNAL) );
674
675 return ret;
676}
677
678int wxSocketImpl::RecvDgram(void *buffer, int size)
679{
c9bccf23 680 wxSockAddressStorage from;
14372de8
VZ
681 WX_SOCKLEN_T fromlen = sizeof(from);
682
683 int ret;
684 DO_WHILE_EINTR( ret, recvfrom(m_fd, static_cast<char *>(buffer), size,
c9bccf23 685 0, &from.addr, &fromlen) );
14372de8
VZ
686
687 if ( ret == SOCKET_ERROR )
688 return SOCKET_ERROR;
689
c9bccf23
VZ
690 m_peer = wxSockAddressImpl(from.addr, fromlen);
691 if ( !m_peer.IsOk() )
14372de8 692 return -1;
14372de8
VZ
693
694 return ret;
695}
696
697int wxSocketImpl::SendDgram(const void *buffer, int size)
698{
c9bccf23 699 if ( !m_peer.IsOk() )
14372de8
VZ
700 {
701 m_error = wxSOCKET_INVADDR;
702 return -1;
703 }
704
14372de8
VZ
705 int ret;
706 DO_WHILE_EINTR( ret, sendto(m_fd, static_cast<const char *>(buffer), size,
c9bccf23 707 0, m_peer.GetAddr(), m_peer.GetLen()) );
14372de8
VZ
708
709 return ret;
710}
711
712int wxSocketImpl::Read(void *buffer, int size)
713{
714 // server sockets can't be used for IO, only to accept new connections
715 if ( m_fd == INVALID_SOCKET || m_server )
716 {
717 m_error = wxSOCKET_INVSOCK;
718 return -1;
719 }
720
721 int ret = m_stream ? RecvStream(buffer, size)
722 : RecvDgram(buffer, size);
723
724 m_error = ret == SOCKET_ERROR ? GetLastError() : wxSOCKET_NOERROR;
725
726 return ret;
727}
728
729int wxSocketImpl::Write(const void *buffer, int size)
730{
731 if ( m_fd == INVALID_SOCKET || m_server )
732 {
733 m_error = wxSOCKET_INVSOCK;
734 return -1;
735 }
736
737 int ret = m_stream ? SendStream(buffer, size)
738 : SendDgram(buffer, size);
739
740 m_error = ret == SOCKET_ERROR ? GetLastError() : wxSOCKET_NOERROR;
741
742 return ret;
743}
744
ef57d866
GRG
745// ==========================================================================
746// wxSocketBase
747// ==========================================================================
748
6c0d0845
VZ
749// --------------------------------------------------------------------------
750// Initialization and shutdown
751// --------------------------------------------------------------------------
752
4017f5ca
VZ
753namespace
754{
755
44c2703f
VZ
756// counts the number of calls to Initialize() minus the number of calls to
757// Shutdown(): we don't really need it any more but it was documented that
758// Shutdown() must be called the same number of times as Initialize() and using
759// a counter helps us to check it
760int gs_socketInitCount = 0;
4017f5ca
VZ
761
762} // anonymous namespace
6c0d0845
VZ
763
764bool wxSocketBase::IsInitialized()
765{
4017f5ca
VZ
766 wxASSERT_MSG( wxIsMainThread(), "unsafe to call from other threads" );
767
44c2703f 768 return gs_socketInitCount != 0;
6c0d0845
VZ
769}
770
771bool wxSocketBase::Initialize()
772{
4017f5ca
VZ
773 wxCHECK_MSG( wxIsMainThread(), false,
774 "must be called from the main thread" );
775
44c2703f 776 if ( !gs_socketInitCount )
6c0d0845 777 {
51fe4b60
VZ
778 wxSocketManager * const manager = wxSocketManager::Get();
779 if ( !manager || !manager->OnInit() )
d775fa82 780 return false;
6c0d0845
VZ
781 }
782
44c2703f
VZ
783 gs_socketInitCount++;
784
d775fa82 785 return true;
6c0d0845
VZ
786}
787
788void wxSocketBase::Shutdown()
789{
4017f5ca 790 wxCHECK_RET( wxIsMainThread(), "must be called from the main thread" );
51fe4b60 791
44c2703f 792 wxCHECK_RET( gs_socketInitCount > 0, "too many calls to Shutdown()" );
4017f5ca 793
44c2703f
VZ
794 if ( !--gs_socketInitCount )
795 {
796 wxSocketManager * const manager = wxSocketManager::Get();
797 wxCHECK_RET( manager, "should have a socket manager" );
4017f5ca 798
44c2703f
VZ
799 manager->OnExit();
800 }
6c0d0845
VZ
801}
802
ef57d866
GRG
803// --------------------------------------------------------------------------
804// Ctor and dtor
805// --------------------------------------------------------------------------
56d8adc0 806
71622a7a 807void wxSocketBase::Init()
f4ada568 808{
365b8793 809 m_impl = NULL;
c2116a35
VZ
810 m_type = wxSOCKET_UNINIT;
811
812 // state
813 m_flags = 0;
814 m_connected =
815 m_establishing =
816 m_reading =
817 m_writing =
c2116a35
VZ
818 m_closed = false;
819 m_lcount = 0;
820 m_timeout = 600;
821 m_beingDeleted = false;
822
823 // pushback buffer
824 m_unread = NULL;
825 m_unrd_size = 0;
826 m_unrd_cur = 0;
827
828 // events
829 m_id = wxID_ANY;
830 m_handler = NULL;
831 m_clientData = NULL;
832 m_notify = false;
5c1193e0
VZ
833 m_eventmask =
834 m_eventsgot = 0;
c2116a35 835
4017f5ca
VZ
836 // when we create the first socket in the main thread we initialize the
837 // OS-dependent socket stuff: notice that this means that the user code
838 // needs to call wxSocket::Initialize() itself if the first socket it
839 // creates is not created in the main thread
840 if ( wxIsMainThread() )
c2116a35 841 {
4017f5ca 842 if ( !Initialize() )
af588446 843 {
4017f5ca 844 wxLogError(_("Cannot initialize sockets"));
af588446 845 }
c2116a35 846 }
f4ada568
GL
847}
848
f187448d
GRG
849wxSocketBase::wxSocketBase()
850{
c2116a35 851 Init();
f187448d 852}
71622a7a
GRG
853
854wxSocketBase::wxSocketBase(wxSocketFlags flags, wxSocketType type)
f4ada568 855{
c2116a35 856 Init();
71622a7a 857
cc0972a2
VZ
858 SetFlags(flags);
859
860 m_type = type;
f4ada568
GL
861}
862
f4ada568
GL
863wxSocketBase::~wxSocketBase()
864{
c2116a35
VZ
865 // Shutdown and close the socket
866 if (!m_beingDeleted)
867 Close();
9181a383 868
51fe4b60
VZ
869 // Destroy the implementation object
870 delete m_impl;
c2116a35
VZ
871
872 // Free the pushback buffer
3185abc2 873 free(m_unread);
f4ada568
GL
874}
875
ef57d866
GRG
876bool wxSocketBase::Destroy()
877{
c2116a35
VZ
878 // Delayed destruction: the socket will be deleted during the next idle
879 // loop iteration. This ensures that all pending events have been
880 // processed.
881 m_beingDeleted = true;
882
883 // Shutdown and close the socket
884 Close();
885
22185a1f 886 // Suppress events from now on
c2116a35
VZ
887 Notify(false);
888
3185abc2 889 // Schedule this object for deletion instead of destroying it right now if
ee5cc630
VZ
890 // it can have other events pending for it and we have a way to do it.
891 //
892 // Notice that sockets used in other threads won't have any events for them
893 // and we shouldn't use delayed destruction mechanism for them as it's not
894 // MT-safe.
895 if ( wxIsMainThread() && wxTheApp )
c2116a35 896 {
3185abc2 897 wxTheApp->ScheduleForDestruction(this);
c2116a35 898 }
3185abc2 899 else // no app
c2116a35
VZ
900 {
901 // in wxBase we might have no app object at all, don't leak memory
902 delete this;
903 }
904
905 return true;
ef57d866 906}
9181a383 907
51fe4b60 908// ----------------------------------------------------------------------------
64b1cea0 909// simple accessors
51fe4b60
VZ
910// ----------------------------------------------------------------------------
911
64b1cea0
VZ
912void wxSocketBase::SetError(wxSocketError error)
913{
914 m_impl->m_error = error;
915}
916
51fe4b60
VZ
917wxSocketError wxSocketBase::LastError() const
918{
919 return m_impl->GetError();
920}
921
ef57d866 922// --------------------------------------------------------------------------
bffc1eaa 923// Basic IO calls
ef57d866
GRG
924// --------------------------------------------------------------------------
925
64b1cea0 926// The following IO operations update m_lcount:
ef57d866 927// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
f4ada568
GL
928bool wxSocketBase::Close()
929{
c2116a35
VZ
930 // Interrupt pending waits
931 InterruptWait();
932
b67397a7 933 ShutdownOutput();
c2116a35
VZ
934
935 m_connected = false;
936 m_establishing = false;
937 return true;
f4ada568
GL
938}
939
b67397a7
VZ
940void wxSocketBase::ShutdownOutput()
941{
942 if ( m_impl )
943 m_impl->Shutdown();
944}
945
f187448d 946wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
f4ada568 947{
365b8793 948 wxSocketReadGuard read(this);
a324a7bc 949
cc0972a2 950 m_lcount = DoRead(buffer, nbytes);
17aa2bec 951
c2116a35 952 return *this;
96db102a
GRG
953}
954
cc0972a2 955wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)
96db102a 956{
f5395600
VZ
957 wxCHECK_MSG( m_impl, 0, "socket must be valid" );
958
cc0972a2
VZ
959 // We use pointer arithmetic here which doesn't work with void pointers.
960 char *buffer = static_cast<char *>(buffer_);
f5395600 961 wxCHECK_MSG( buffer, 0, "NULL buffer" );
c2116a35 962
cc0972a2
VZ
963 // Try the push back buffer first, even before checking whether the socket
964 // is valid to allow reading previously pushed back data from an already
965 // closed socket.
966 wxUint32 total = GetPushback(buffer, nbytes, false);
c2116a35 967 nbytes -= total;
cc0972a2 968 buffer += total;
c2116a35 969
f5395600 970 while ( nbytes )
cc0972a2 971 {
f5395600
VZ
972 // our socket is non-blocking so Read() will return immediately if
973 // there is nothing to read yet and it's more efficient to try it first
6f405b31
VZ
974 // before entering DoWait() which is going to start dispatching GUI
975 // events and, even more importantly, we must do this under Windows
f5395600
VZ
976 // where we're not going to get notifications about socket being ready
977 // for reading before we read all the existing data from it
d34f724d
VZ
978 const int ret = !m_impl->m_stream || m_connected
979 ? m_impl->Read(buffer, nbytes)
980 : 0;
64b1cea0
VZ
981 if ( ret == -1 )
982 {
f5395600 983 if ( m_impl->GetLastError() == wxSOCKET_WOULDBLOCK )
c2116a35 984 {
f5395600
VZ
985 // if we don't want to wait, just return immediately
986 if ( m_flags & wxSOCKET_NOWAIT )
686d0cc0
VZ
987 {
988 // this shouldn't be counted as an error in this case
989 SetError(wxSOCKET_NOERROR);
f5395600 990 break;
686d0cc0 991 }
c2116a35 992
6f405b31
VZ
993 // otherwise wait until the socket becomes ready for reading or
994 // an error occurs on it
ebbf7407 995 if ( !DoWaitWithTimeout(wxSOCKET_INPUT_FLAG) )
f5395600
VZ
996 {
997 // and exit if the timeout elapsed before it did
998 SetError(wxSOCKET_TIMEDOUT);
999 break;
1000 }
c2116a35 1001
f5395600
VZ
1002 // retry reading
1003 continue;
1004 }
1005 else // "real" error
1006 {
1007 SetError(wxSOCKET_IOERR);
c2116a35 1008 break;
f5395600
VZ
1009 }
1010 }
1011 else if ( ret == 0 )
1012 {
1013 // for connection-oriented (e.g. TCP) sockets we can only read
1014 // 0 bytes if the other end has been closed, and for connectionless
1015 // ones (UDP) this flag doesn't make sense anyhow so we can set it
1016 // to true too without doing any harm
1017 m_closed = true;
1018
1019 // we're not going to read anything else and so if we haven't read
1020 // anything (or not everything in wxSOCKET_WAITALL case) already,
1021 // signal an error
1022 if ( (m_flags & wxSOCKET_WAITALL) || !total )
1023 SetError(wxSOCKET_IOERR);
1024 break;
1025 }
c2116a35 1026
f5395600 1027 total += ret;
c2116a35 1028
f5395600
VZ
1029 // if we are happy to read something and not the entire nbytes bytes,
1030 // then we're done
1031 if ( !(m_flags & wxSOCKET_WAITALL) )
1032 break;
64b1cea0 1033
f5395600
VZ
1034 nbytes -= ret;
1035 buffer += ret;
c2116a35 1036 }
96db102a 1037
96db102a 1038 return total;
c2116a35 1039}
f4ada568 1040
c2116a35
VZ
1041wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
1042{
c2116a35
VZ
1043 struct
1044 {
1045 unsigned char sig[4];
1046 unsigned char len[4];
1047 } msg;
1048
365b8793 1049 wxSocketReadGuard read(this);
c2116a35 1050
365b8793 1051 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
c9157492 1052
64b1cea0
VZ
1053 bool ok = false;
1054 if ( DoRead(&msg, sizeof(msg)) == sizeof(msg) )
56d8adc0 1055 {
64b1cea0
VZ
1056 wxUint32 sig = (wxUint32)msg.sig[0];
1057 sig |= (wxUint32)(msg.sig[1] << 8);
1058 sig |= (wxUint32)(msg.sig[2] << 16);
1059 sig |= (wxUint32)(msg.sig[3] << 24);
f4ada568 1060
64b1cea0
VZ
1061 if ( sig == 0xfeeddead )
1062 {
1063 wxUint32 len = (wxUint32)msg.len[0];
1064 len |= (wxUint32)(msg.len[1] << 8);
1065 len |= (wxUint32)(msg.len[2] << 16);
1066 len |= (wxUint32)(msg.len[3] << 24);
f4ada568 1067
64b1cea0
VZ
1068 wxUint32 len2;
1069 if (len > nbytes)
1070 {
1071 len2 = len - nbytes;
1072 len = nbytes;
1073 }
1074 else
1075 len2 = 0;
c2116a35 1076
64b1cea0
VZ
1077 // Don't attempt to read if the msg was zero bytes long.
1078 m_lcount = len ? DoRead(buffer, len) : 0;
c2116a35 1079
64b1cea0
VZ
1080 if ( len2 )
1081 {
1082 char discard_buffer[MAX_DISCARD_SIZE];
1083 long discard_len;
1084
1085 // NOTE: discarded bytes don't add to m_lcount.
1086 do
1087 {
1088 discard_len = len2 > MAX_DISCARD_SIZE
1089 ? MAX_DISCARD_SIZE
1090 : len2;
1091 discard_len = DoRead(discard_buffer, (wxUint32)discard_len);
1092 len2 -= (wxUint32)discard_len;
1093 }
1094 while ((discard_len > 0) && len2);
1095 }
17aa2bec 1096
64b1cea0
VZ
1097 if ( !len2 && DoRead(&msg, sizeof(msg)) == sizeof(msg) )
1098 {
1099 sig = (wxUint32)msg.sig[0];
1100 sig |= (wxUint32)(msg.sig[1] << 8);
1101 sig |= (wxUint32)(msg.sig[2] << 16);
1102 sig |= (wxUint32)(msg.sig[3] << 24);
c2116a35 1103
64b1cea0
VZ
1104 if ( sig == 0xdeadfeed )
1105 ok = true;
1106 }
c2116a35 1107 }
c2116a35 1108 }
062c4861 1109
64b1cea0
VZ
1110 if ( !ok )
1111 SetError(wxSOCKET_IOERR);
96db102a 1112
c2116a35 1113 return *this;
062c4861
GL
1114}
1115
f187448d 1116wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
f4ada568 1117{
365b8793 1118 wxSocketReadGuard read(this);
96db102a 1119
896576e3
VZ
1120 // Peek() should never block
1121 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_NOWAIT);
1122
cc0972a2 1123 m_lcount = DoRead(buffer, nbytes);
96db102a 1124
365b8793 1125 Pushback(buffer, m_lcount);
f4ada568 1126
c2116a35 1127 return *this;
f4ada568
GL
1128}
1129
f187448d 1130wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
f4ada568 1131{
365b8793 1132 wxSocketWriteGuard write(this);
56d8adc0 1133
cc0972a2 1134 m_lcount = DoWrite(buffer, nbytes);
96db102a 1135
c2116a35 1136 return *this;
96db102a
GRG
1137}
1138
cc0972a2 1139// This function is a mirror image of DoRead() except that it doesn't use the
f5395600
VZ
1140// push back buffer and doesn't treat 0 return value specially (normally this
1141// shouldn't happen at all here), so please see comments there for explanations
cc0972a2 1142wxUint32 wxSocketBase::DoWrite(const void *buffer_, wxUint32 nbytes)
96db102a 1143{
f5395600
VZ
1144 wxCHECK_MSG( m_impl, 0, "socket must be valid" );
1145
cc0972a2 1146 const char *buffer = static_cast<const char *>(buffer_);
f5395600 1147 wxCHECK_MSG( buffer, 0, "NULL buffer" );
c2116a35 1148
cc0972a2 1149 wxUint32 total = 0;
f5395600 1150 while ( nbytes )
cc0972a2 1151 {
d34f724d 1152 if ( m_impl->m_stream && !m_connected )
f1763270
VZ
1153 {
1154 if ( (m_flags & wxSOCKET_WAITALL) || !total )
1155 SetError(wxSOCKET_IOERR);
1156 break;
1157 }
1158
51fe4b60 1159 const int ret = m_impl->Write(buffer, nbytes);
64b1cea0
VZ
1160 if ( ret == -1 )
1161 {
f5395600 1162 if ( m_impl->GetLastError() == wxSOCKET_WOULDBLOCK )
c2116a35 1163 {
f5395600
VZ
1164 if ( m_flags & wxSOCKET_NOWAIT )
1165 break;
5c9eff30 1166
ebbf7407 1167 if ( !DoWaitWithTimeout(wxSOCKET_OUTPUT_FLAG) )
f5395600
VZ
1168 {
1169 SetError(wxSOCKET_TIMEDOUT);
1170 break;
1171 }
a324a7bc 1172
f5395600
VZ
1173 continue;
1174 }
1175 else // "real" error
1176 {
1177 SetError(wxSOCKET_IOERR);
c2116a35 1178 break;
f5395600
VZ
1179 }
1180 }
c9157492 1181
f5395600 1182 total += ret;
c9157492 1183
f5395600
VZ
1184 if ( !(m_flags & wxSOCKET_WAITALL) )
1185 break;
64b1cea0 1186
f5395600
VZ
1187 nbytes -= ret;
1188 buffer += ret;
81b92e17 1189 }
a324a7bc 1190
c2116a35 1191 return total;
f4ada568
GL
1192}
1193
f187448d 1194wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
062c4861 1195{
c2116a35
VZ
1196 struct
1197 {
1198 unsigned char sig[4];
1199 unsigned char len[4];
1200 } msg;
062c4861 1201
365b8793 1202 wxSocketWriteGuard write(this);
96db102a 1203
365b8793 1204 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
96db102a 1205
c2116a35
VZ
1206 msg.sig[0] = (unsigned char) 0xad;
1207 msg.sig[1] = (unsigned char) 0xde;
1208 msg.sig[2] = (unsigned char) 0xed;
1209 msg.sig[3] = (unsigned char) 0xfe;
062c4861 1210
c2116a35
VZ
1211 msg.len[0] = (unsigned char) (nbytes & 0xff);
1212 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
1213 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
1214 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
17aa2bec 1215
64b1cea0
VZ
1216 bool ok = false;
1217 if ( DoWrite(&msg, sizeof(msg)) == sizeof(msg) )
1218 {
1219 m_lcount = DoWrite(buffer, nbytes);
1220 if ( m_lcount == nbytes )
1221 {
1222 msg.sig[0] = (unsigned char) 0xed;
1223 msg.sig[1] = (unsigned char) 0xfe;
1224 msg.sig[2] = (unsigned char) 0xad;
1225 msg.sig[3] = (unsigned char) 0xde;
1226 msg.len[0] =
1227 msg.len[1] =
1228 msg.len[2] =
1229 msg.len[3] = (char) 0;
1230
1231 if ( DoWrite(&msg, sizeof(msg)) == sizeof(msg))
1232 ok = true;
1233 }
1234 }
17aa2bec 1235
64b1cea0
VZ
1236 if ( !ok )
1237 SetError(wxSOCKET_IOERR);
96db102a 1238
c2116a35 1239 return *this;
062c4861
GL
1240}
1241
f187448d 1242wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
f4ada568 1243{
c2116a35
VZ
1244 if (nbytes != 0)
1245 Pushback(buffer, nbytes);
f4ada568 1246
64b1cea0 1247 SetError(wxSOCKET_NOERROR);
c2116a35 1248 m_lcount = nbytes;
f4ada568 1249
c2116a35 1250 return *this;
a324a7bc
GL
1251}
1252
96db102a 1253wxSocketBase& wxSocketBase::Discard()
f4ada568 1254{
c2116a35
VZ
1255 char *buffer = new char[MAX_DISCARD_SIZE];
1256 wxUint32 ret;
1257 wxUint32 total = 0;
f4ada568 1258
365b8793 1259 wxSocketReadGuard read(this);
96db102a 1260
365b8793 1261 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_NOWAIT);
384b4373 1262
c2116a35
VZ
1263 do
1264 {
cc0972a2 1265 ret = DoRead(buffer, MAX_DISCARD_SIZE);
c2116a35
VZ
1266 total += ret;
1267 }
1268 while (ret == MAX_DISCARD_SIZE);
f4ada568 1269
c2116a35
VZ
1270 delete[] buffer;
1271 m_lcount = total;
64b1cea0 1272 SetError(wxSOCKET_NOERROR);
17aa2bec 1273
c2116a35 1274 return *this;
f4ada568
GL
1275}
1276
ef57d866
GRG
1277// --------------------------------------------------------------------------
1278// Wait functions
1279// --------------------------------------------------------------------------
f4ada568 1280
51fe4b60 1281/*
00414faf
VZ
1282 This function will check for the events specified in the flags parameter,
1283 and it will return a mask indicating which operations can be performed.
f0db5d75 1284 */
00414faf 1285wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags,
2b036c4b 1286 const timeval *timeout)
f0db5d75 1287{
5e9238f9
VZ
1288 if ( m_fd == INVALID_SOCKET )
1289 return (wxSOCKET_LOST_FLAG & flags);
f0db5d75 1290
5e9238f9
VZ
1291 struct timeval tv;
1292 if ( timeout )
1293 tv = *timeout;
1294 else
1295 tv.tv_sec = tv.tv_usec = 0;
f0db5d75 1296
5e9238f9
VZ
1297 // prepare the FD sets, passing NULL for the one(s) we don't use
1298 fd_set
1299 readfds, *preadfds = NULL,
1300 writefds, *pwritefds = NULL,
1301 exceptfds; // always want to know about errors
f0db5d75 1302
5e9238f9 1303 if ( flags & wxSOCKET_INPUT_FLAG )
5e9238f9 1304 preadfds = &readfds;
9be02147
VZ
1305
1306 if ( flags & wxSOCKET_OUTPUT_FLAG )
1307 pwritefds = &writefds;
1308
1309 // When using non-blocking connect() the client socket becomes connected
1310 // (successfully or not) when it becomes writable but when using
1311 // non-blocking accept() the server socket becomes connected when it
1312 // becomes readable.
1313 if ( flags & wxSOCKET_CONNECTION_FLAG )
1314 {
1315 if ( m_server )
1316 preadfds = &readfds;
1317 else
1318 pwritefds = &writefds;
1319 }
1320
1321 if ( preadfds )
1322 {
5e9238f9
VZ
1323 wxFD_ZERO(preadfds);
1324 wxFD_SET(m_fd, preadfds);
1325 }
f0db5d75 1326
9be02147 1327 if ( pwritefds )
5e9238f9 1328 {
5e9238f9
VZ
1329 wxFD_ZERO(pwritefds);
1330 wxFD_SET(m_fd, pwritefds);
1331 }
f0db5d75 1332
5e9238f9
VZ
1333 wxFD_ZERO(&exceptfds);
1334 wxFD_SET(m_fd, &exceptfds);
f0db5d75 1335
5e9238f9
VZ
1336 const int rc = select(m_fd + 1, preadfds, pwritefds, &exceptfds, &tv);
1337
1338 // check for errors first
1339 if ( rc == -1 || wxFD_ISSET(m_fd, &exceptfds) )
f0db5d75 1340 {
5e9238f9
VZ
1341 m_establishing = false;
1342
1343 return wxSOCKET_LOST_FLAG & flags;
f0db5d75 1344 }
f0db5d75 1345
5e9238f9
VZ
1346 if ( rc == 0 )
1347 return 0;
f0db5d75 1348
5e9238f9 1349 wxASSERT_MSG( rc == 1, "unexpected select() return value" );
f0db5d75 1350
5e9238f9
VZ
1351 wxSocketEventFlags detected = 0;
1352 if ( preadfds && wxFD_ISSET(m_fd, preadfds) )
1353 detected |= wxSOCKET_INPUT_FLAG;
1354
1355 if ( pwritefds && wxFD_ISSET(m_fd, pwritefds) )
f0db5d75 1356 {
5e9238f9
VZ
1357 // check for the case of non-blocking connect()
1358 if ( m_establishing && !m_server )
1359 {
1360 int error;
1361 SOCKOPTLEN_T len = sizeof(error);
1362 m_establishing = false;
1363 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
1364
1365 if ( error )
1366 detected = wxSOCKET_LOST_FLAG;
1367 else
1368 detected |= wxSOCKET_CONNECTION_FLAG;
1369 }
1370 else // not called to get non-blocking connect() status
1371 {
1372 detected |= wxSOCKET_OUTPUT_FLAG;
1373 }
f0db5d75 1374 }
f0db5d75 1375
5e9238f9 1376 return detected & flags;
f0db5d75
VZ
1377}
1378
ebbf7407 1379int
60ee0172 1380wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
6f405b31
VZ
1381{
1382 // Use either the provided timeout or the default timeout value associated
1383 // with this socket.
1384 //
1385 // TODO: allow waiting forever, see #9443
1386 const long timeout = seconds == -1 ? m_timeout * 1000
1387 : seconds * 1000 + milliseconds;
1388
1389 return DoWait(timeout, flags);
1390}
1391
ebbf7407 1392int
6f405b31 1393wxSocketBase::DoWait(long timeout, wxSocketEventFlags flags)
375abe3d 1394{
ebbf7407 1395 wxCHECK_MSG( m_impl, -1, "can't wait on invalid socket" );
375abe3d 1396
1632883f
VZ
1397 // we're never going to become ready in a TCP client if we're not connected
1398 // any more (OTOH a server can call this to precisely wait for a connection
1399 // so do wait for it in this case and UDP client is never "connected")
1400 if ( !m_impl->IsServer() &&
1401 m_impl->m_stream && !m_connected && !m_establishing )
ebbf7407 1402 return -1;
9588640d 1403
60ee0172 1404 // This can be set to true from Interrupt() to exit this function a.s.a.p.
c2116a35 1405 m_interrupt = false;
81b92e17 1406
af2fd961 1407
60ee0172
VZ
1408 const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
1409
1410 // Get the active event loop which we'll use for the message dispatching
2b036c4b
VZ
1411 // when running in the main thread unless this was explicitly disabled by
1412 // setting wxSOCKET_BLOCK flag
60ee0172 1413 wxEventLoopBase *eventLoop;
2b036c4b 1414 if ( !(m_flags & wxSOCKET_BLOCK) && wxIsMainThread() )
60ee0172
VZ
1415 {
1416 eventLoop = wxEventLoop::GetActive();
60ee0172
VZ
1417 }
1418 else // in worker thread
af2fd961 1419 {
60ee0172
VZ
1420 // We never dispatch messages from threads other than the main one.
1421 eventLoop = NULL;
af2fd961
GRG
1422 }
1423
5ab2f257
VZ
1424 // Make sure the events we're interested in are enabled before waiting for
1425 // them: this is really necessary here as otherwise this could happen:
1426 // 1. DoRead(wxSOCKET_WAITALL) is called
1427 // 2. There is nothing to read so DoWait(wxSOCKET_INPUT_FLAG) is called
1428 // 3. Some, but not all data appears, wxSocketImplUnix::OnReadWaiting()
1429 // is called and wxSOCKET_INPUT_FLAG events are disabled in it
1430 // 4. Because of wxSOCKET_WAITALL we call DoWait() again but the events
1431 // are still disabled and we block forever
1432 //
1433 // More elegant solution would be nice but for now simply re-enabling the
1434 // events here will do
1435 m_impl->ReenableEvents(flags & (wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG));
1436
1437
00414faf
VZ
1438 // Wait until we receive the event we're waiting for or the timeout expires
1439 // (but note that we always execute the loop at least once, even if timeout
1440 // is 0 as this is used for polling)
ebbf7407
VZ
1441 int rc = 0;
1442 for ( bool firstTime = true; !m_interrupt; firstTime = false )
af2fd961 1443 {
00414faf
VZ
1444 long timeLeft = wxMilliClockToLong(timeEnd - wxGetLocalTimeMillis());
1445 if ( timeLeft < 0 )
1446 {
1447 if ( !firstTime )
1448 break; // timed out
1449
1450 timeLeft = 0;
1451 }
1452
2f1c8faf
VZ
1453 wxSocketEventFlags events;
1454 if ( eventLoop )
1455 {
00414faf
VZ
1456 // reset them before starting to wait
1457 m_eventsgot = 0;
1458
1459 eventLoop->DispatchTimeout(timeLeft);
2f1c8faf
VZ
1460
1461 events = m_eventsgot;
1462 }
00414faf
VZ
1463 else // no event loop or waiting in another thread
1464 {
1465 // as explained below, we should always check for wxSOCKET_LOST_FLAG
2b036c4b
VZ
1466 timeval tv;
1467 SetTimeValFromMS(tv, timeLeft);
1468 events = m_impl->Select(flags | wxSOCKET_LOST_FLAG, &tv);
00414faf
VZ
1469 }
1470
1471 // always check for wxSOCKET_LOST_FLAG, even if flags doesn't include
1472 // it, as continuing to wait for anything else after getting it is
1473 // pointless
1474 if ( events & wxSOCKET_LOST_FLAG )
2f1c8faf 1475 {
00414faf
VZ
1476 m_connected = false;
1477 m_establishing = false;
ebbf7407 1478 rc = -1;
00414faf 1479 break;
2f1c8faf 1480 }
60ee0172 1481
00414faf
VZ
1482 // otherwise mask out the bits we're not interested in
1483 events &= flags;
1484
60ee0172 1485 // Incoming connection (server) or connection established (client)?
2f1c8faf 1486 if ( events & wxSOCKET_CONNECTION_FLAG )
c2116a35
VZ
1487 {
1488 m_connected = true;
1489 m_establishing = false;
ebbf7407 1490 rc = true;
c2116a35
VZ
1491 break;
1492 }
c0043a50 1493
60ee0172 1494 // Data available or output buffer ready?
2f1c8faf 1495 if ( (events & wxSOCKET_INPUT_FLAG) || (events & wxSOCKET_OUTPUT_FLAG) )
b8d1915d 1496 {
ebbf7407 1497 rc = true;
c2116a35 1498 break;
b8d1915d 1499 }
f01bca89 1500 }
f4ada568 1501
ebbf7407 1502 return rc;
f4ada568 1503}
f4ada568 1504
a737331d 1505bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 1506{
60ee0172 1507 return DoWait(seconds, milliseconds,
ebbf7407
VZ
1508 wxSOCKET_INPUT_FLAG |
1509 wxSOCKET_OUTPUT_FLAG |
1510 wxSOCKET_CONNECTION_FLAG) != 0;
f4ada568 1511}
f4ada568 1512
a737331d 1513bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 1514{
60ee0172
VZ
1515 // Check pushback buffer before entering DoWait
1516 if ( m_unread )
c2116a35 1517 return true;
96db102a 1518
6f405b31
VZ
1519 // Check if the socket is not already ready for input, if it is, there is
1520 // no need to start waiting for it (worse, we'll actually never get a
1521 // notification about the socket becoming ready if it is already under
1522 // Windows)
1523 if ( m_impl->Select(wxSOCKET_INPUT_FLAG) )
1524 return true;
1525
ebbf7407 1526 return DoWait(seconds, milliseconds, wxSOCKET_INPUT_FLAG) != 0;
f4ada568
GL
1527}
1528
bfa7bf7d 1529
a737331d 1530bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 1531{
6f405b31
VZ
1532 if ( m_impl->Select(wxSOCKET_OUTPUT_FLAG) )
1533 return true;
1534
ebbf7407 1535 return DoWait(seconds, milliseconds, wxSOCKET_OUTPUT_FLAG) != 0;
a737331d 1536}
f4ada568 1537
a737331d
GL
1538bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
1539{
ebbf7407 1540 return DoWait(seconds, milliseconds, wxSOCKET_LOST_FLAG) == -1;
f4ada568 1541}
a737331d 1542
ef57d866
GRG
1543// --------------------------------------------------------------------------
1544// Miscellaneous
1545// --------------------------------------------------------------------------
1546
1547//
1548// Get local or peer address
1549//
1550
c9bccf23 1551bool wxSocketBase::GetPeer(wxSockAddress& addr) const
ef57d866 1552{
c9bccf23 1553 wxCHECK_MSG( m_impl, false, "invalid socket" );
ef57d866 1554
c9bccf23
VZ
1555 const wxSockAddressImpl& peer = m_impl->GetPeer();
1556 if ( !peer.IsOk() )
c2116a35 1557 return false;
007c77ab 1558
c9bccf23 1559 addr.SetAddress(peer);
ef57d866 1560
c2116a35 1561 return true;
ef57d866
GRG
1562}
1563
c9bccf23 1564bool wxSocketBase::GetLocal(wxSockAddress& addr) const
ef57d866 1565{
c9bccf23 1566 wxCHECK_MSG( m_impl, false, "invalid socket" );
ef57d866 1567
c9bccf23
VZ
1568 const wxSockAddressImpl& local = m_impl->GetLocal();
1569 if ( !local.IsOk() )
7fb0a11d 1570 return false;
ef57d866 1571
c9bccf23 1572 addr.SetAddress(local);
ef57d866 1573
7fb0a11d 1574 return true;
ef57d866
GRG
1575}
1576
1577//
1578// Save and restore socket state
1579//
1580
1581void wxSocketBase::SaveState()
1582{
7fb0a11d 1583 wxSocketState *state;
ef57d866 1584
7fb0a11d 1585 state = new wxSocketState();
ef57d866 1586
7fb0a11d
WS
1587 state->m_flags = m_flags;
1588 state->m_notify = m_notify;
1589 state->m_eventmask = m_eventmask;
1590 state->m_clientData = m_clientData;
ef57d866 1591
7fb0a11d 1592 m_states.Append(state);
ef57d866
GRG
1593}
1594
1595void wxSocketBase::RestoreState()
1596{
7fb0a11d
WS
1597 wxList::compatibility_iterator node;
1598 wxSocketState *state;
ef57d866 1599
7fb0a11d
WS
1600 node = m_states.GetLast();
1601 if (!node)
1602 return;
ef57d866 1603
7fb0a11d 1604 state = (wxSocketState *)node->GetData();
ef57d866 1605
7fb0a11d
WS
1606 m_flags = state->m_flags;
1607 m_notify = state->m_notify;
1608 m_eventmask = state->m_eventmask;
1609 m_clientData = state->m_clientData;
37340c48 1610
7fb0a11d
WS
1611 m_states.Erase(node);
1612 delete state;
ef57d866
GRG
1613}
1614
1615//
1616// Timeout and flags
1617//
1618
17aa2bec
GRG
1619void wxSocketBase::SetTimeout(long seconds)
1620{
7fb0a11d 1621 m_timeout = seconds;
17aa2bec 1622
51fe4b60
VZ
1623 if (m_impl)
1624 m_impl->SetTimeout(m_timeout * 1000);
17aa2bec
GRG
1625}
1626
71622a7a 1627void wxSocketBase::SetFlags(wxSocketFlags flags)
f4ada568 1628{
cc0972a2
VZ
1629 // Do some sanity checking on the flags used: not all values can be used
1630 // together.
1631 wxASSERT_MSG( !(flags & wxSOCKET_NOWAIT) ||
1632 !(flags & (wxSOCKET_WAITALL | wxSOCKET_BLOCK)),
1633 "Using wxSOCKET_WAITALL or wxSOCKET_BLOCK with "
1634 "wxSOCKET_NOWAIT doesn't make sense" );
1635
7fb0a11d 1636 m_flags = flags;
f4ada568 1637}
f0a56ab0 1638
f187448d 1639
ef57d866 1640// --------------------------------------------------------------------------
f187448d 1641// Event handling
ef57d866 1642// --------------------------------------------------------------------------
a324a7bc 1643
bffc1eaa 1644void wxSocketBase::OnRequest(wxSocketNotify notification)
f4ada568 1645{
c2116a35 1646 wxSocketEventFlags flag = 0;
5c1193e0 1647 switch ( notification )
c2116a35 1648 {
5c1193e0
VZ
1649 case wxSOCKET_INPUT:
1650 flag = wxSOCKET_INPUT_FLAG;
1651 break;
1652
1653 case wxSOCKET_OUTPUT:
1654 flag = wxSOCKET_OUTPUT_FLAG;
1655 break;
1656
1657 case wxSOCKET_CONNECTION:
1658 flag = wxSOCKET_CONNECTION_FLAG;
40a983ad
VZ
1659
1660 // we're now successfully connected
1661 m_connected = true;
609aa390
VZ
1662 m_establishing = false;
1663
1664 // error was previously set to wxSOCKET_WOULDBLOCK, but this is not
1665 // the case any longer
1666 SetError(wxSOCKET_NOERROR);
5c1193e0
VZ
1667 break;
1668
1669 case wxSOCKET_LOST:
1670 flag = wxSOCKET_LOST_FLAG;
40a983ad 1671
9038fc94
VZ
1672 // if we lost the connection the socket is now closed and not
1673 // connected any more
1674 m_connected = false;
40a983ad 1675 m_closed = true;
5c1193e0
VZ
1676 break;
1677
c2116a35 1678 default:
5c1193e0 1679 wxFAIL_MSG( "unknown wxSocket notification" );
c2116a35
VZ
1680 }
1681
5c1193e0
VZ
1682 // remember the events which were generated for this socket, we're going to
1683 // use this in DoWait()
1684 m_eventsgot |= flag;
1685
1686 // send the wx event if enabled and we're interested in it
1687 if ( m_notify && (m_eventmask & flag) && m_handler )
c2116a35 1688 {
0ed00ab5
VZ
1689 // don't generate the events when we're inside DoWait() called from our
1690 // own code as we are going to consume the data that has just become
1691 // available ourselves and the user code won't see it at all
1692 if ( (notification == wxSOCKET_INPUT && m_reading) ||
1693 (notification == wxSOCKET_OUTPUT && m_writing) )
1694 {
1695 return;
1696 }
1697
5c1193e0
VZ
1698 wxSocketEvent event(m_id);
1699 event.m_event = notification;
1700 event.m_clientData = m_clientData;
1701 event.SetEventObject(this);
c2116a35 1702
5c1193e0 1703 m_handler->AddPendingEvent(event);
bffc1eaa 1704 }
f4ada568
GL
1705}
1706
f187448d
GRG
1707void wxSocketBase::Notify(bool notify)
1708{
7fb0a11d 1709 m_notify = notify;
f187448d
GRG
1710}
1711
1712void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1713{
7fb0a11d 1714 m_eventmask = flags;
f187448d
GRG
1715}
1716
71622a7a 1717void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
f4ada568 1718{
7fb0a11d
WS
1719 m_handler = &handler;
1720 m_id = id;
f4ada568
GL
1721}
1722
ef57d866
GRG
1723// --------------------------------------------------------------------------
1724// Pushback buffer
1725// --------------------------------------------------------------------------
db131261 1726
f187448d 1727void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
f4ada568 1728{
c2116a35 1729 if (!size) return;
dc5c1114 1730
c2116a35
VZ
1731 if (m_unread == NULL)
1732 m_unread = malloc(size);
1733 else
1734 {
1735 void *tmp;
f4ada568 1736
c2116a35
VZ
1737 tmp = malloc(m_unrd_size + size);
1738 memcpy((char *)tmp + size, m_unread, m_unrd_size);
1739 free(m_unread);
a324a7bc 1740
c2116a35
VZ
1741 m_unread = tmp;
1742 }
31528cd3 1743
c2116a35 1744 m_unrd_size += size;
a324a7bc 1745
c2116a35 1746 memcpy(m_unread, buffer, size);
f4ada568
GL
1747}
1748
f187448d 1749wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
f4ada568 1750{
cc0972a2
VZ
1751 wxCHECK_MSG( buffer, 0, "NULL buffer" );
1752
c2116a35
VZ
1753 if (!m_unrd_size)
1754 return 0;
f4ada568 1755
c2116a35
VZ
1756 if (size > (m_unrd_size-m_unrd_cur))
1757 size = m_unrd_size-m_unrd_cur;
96db102a 1758
c2116a35 1759 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
f4ada568 1760
c2116a35 1761 if (!peek)
dc5c1114 1762 {
c2116a35
VZ
1763 m_unrd_cur += size;
1764 if (m_unrd_size == m_unrd_cur)
1765 {
1766 free(m_unread);
1767 m_unread = NULL;
1768 m_unrd_size = 0;
1769 m_unrd_cur = 0;
1770 }
f4ada568 1771 }
f4ada568 1772
c2116a35 1773 return size;
f4ada568
GL
1774}
1775
f187448d 1776
ef57d866 1777// ==========================================================================
c3e646b4 1778// wxSocketServer
ef57d866 1779// ==========================================================================
f4ada568 1780
ef57d866
GRG
1781// --------------------------------------------------------------------------
1782// Ctor
1783// --------------------------------------------------------------------------
56d8adc0 1784
c9bccf23 1785wxSocketServer::wxSocketServer(const wxSockAddress& addr,
71622a7a
GRG
1786 wxSocketFlags flags)
1787 : wxSocketBase(flags, wxSOCKET_SERVER)
f4ada568 1788{
9a83f860 1789 wxLogTrace( wxTRACE_Socket, wxT("Opening wxSocketServer") );
f4ada568 1790
4f260c9c
VZ
1791 wxSocketManager * const manager = wxSocketManager::Get();
1792 m_impl = manager ? manager->CreateSocket(*this) : NULL;
384b4373 1793
51fe4b60 1794 if (!m_impl)
007c77ab 1795 {
9a83f860 1796 wxLogTrace( wxTRACE_Socket, wxT("*** Failed to create m_impl") );
007c77ab
RL
1797 return;
1798 }
a737331d 1799
2804f77d 1800 // Setup the socket as server
c9bccf23 1801 m_impl->SetLocal(addr.GetAddress());
d775fa82 1802
74c481d1 1803 if (GetFlags() & wxSOCKET_REUSEADDR) {
51fe4b60 1804 m_impl->SetReusable();
74c481d1 1805 }
60edcf45 1806 if (GetFlags() & wxSOCKET_BROADCAST) {
51fe4b60 1807 m_impl->SetBroadcast();
60edcf45
VZ
1808 }
1809 if (GetFlags() & wxSOCKET_NOBIND) {
51fe4b60 1810 m_impl->DontDoBind();
60edcf45 1811 }
74c481d1 1812
51fe4b60 1813 if (m_impl->CreateServer() != wxSOCKET_NOERROR)
007c77ab 1814 {
5276b0a5 1815 wxDELETE(m_impl);
007c77ab 1816
9a83f860 1817 wxLogTrace( wxTRACE_Socket, wxT("*** CreateServer() failed") );
007c77ab
RL
1818 return;
1819 }
1820
45cecdf9
VZ
1821 // Notice that we need a cast as SOCKET is 64 bit under Win64 and that the
1822 // cast is safe because a SOCKET is a handle and so limited to 32 (or,
1823 // actually, even 24) bit values anyhow.
1824 wxLogTrace( wxTRACE_Socket, wxT("wxSocketServer on fd %u"),
1825 static_cast<unsigned>(m_impl->m_fd) );
f4ada568
GL
1826}
1827
ef57d866
GRG
1828// --------------------------------------------------------------------------
1829// Accept
1830// --------------------------------------------------------------------------
8c14576d 1831
d80d1aba 1832bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1833{
2b036c4b
VZ
1834 if ( !m_impl || (m_impl->m_fd == INVALID_SOCKET) || !m_impl->IsServer() )
1835 {
1836 wxFAIL_MSG( "can only be called for a valid server socket" );
1837
64b1cea0 1838 SetError(wxSOCKET_INVSOCK);
2b036c4b 1839
c2116a35 1840 return false;
2b036c4b
VZ
1841 }
1842
1843 if ( wait )
1844 {
1845 // wait until we get a connection
1846 if ( !m_impl->SelectWithTimeout(wxSOCKET_INPUT_FLAG) )
1847 {
64b1cea0 1848 SetError(wxSOCKET_TIMEDOUT);
2b036c4b
VZ
1849
1850 return false;
1851 }
1852 }
17aa2bec 1853
2b036c4b 1854 sock.m_impl = m_impl->Accept(sock);
d80d1aba 1855
51fe4b60 1856 if ( !sock.m_impl )
2b036c4b 1857 {
64b1cea0 1858 SetError(m_impl->GetLastError());
2b036c4b 1859
c2116a35 1860 return false;
2b036c4b 1861 }
d80d1aba 1862
c2116a35 1863 sock.m_type = wxSOCKET_BASE;
c2116a35 1864 sock.m_connected = true;
f4ada568 1865
c2116a35 1866 return true;
f4ada568
GL
1867}
1868
d80d1aba 1869wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568 1870{
c2116a35 1871 wxSocketBase* sock = new wxSocketBase();
f4ada568 1872
c2116a35 1873 sock->SetFlags(m_flags);
f4ada568 1874
c2116a35
VZ
1875 if (!AcceptWith(*sock, wait))
1876 {
1877 sock->Destroy();
1878 sock = NULL;
1879 }
f4ada568 1880
c2116a35 1881 return sock;
f4ada568
GL
1882}
1883
17aa2bec 1884bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1885{
ebbf7407 1886 return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG) == 1;
d80d1aba
GRG
1887}
1888
bfa7bf7d
VZ
1889bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1890{
9a83f860 1891 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
11734f8a 1892
735ac2bc 1893 SOCKOPTLEN_T lenreal = *optlen;
51fe4b60
VZ
1894 if ( getsockopt(m_impl->m_fd, level, optname,
1895 static_cast<char *>(optval), &lenreal) != 0 )
d775fa82 1896 return false;
51fe4b60
VZ
1897
1898 *optlen = lenreal;
1899
d775fa82 1900 return true;
bfa7bf7d
VZ
1901}
1902
51fe4b60
VZ
1903bool
1904wxSocketBase::SetOption(int level, int optname, const void *optval, int optlen)
bfa7bf7d 1905{
9a83f860 1906 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
8e3f3880 1907
51fe4b60
VZ
1908 return setsockopt(m_impl->m_fd, level, optname,
1909 static_cast<const char *>(optval), optlen) == 0;
bfa7bf7d
VZ
1910}
1911
72ac4e88 1912bool wxSocketBase::SetLocal(const wxIPV4address& local)
33d925b0 1913{
c9bccf23 1914 m_localAddress = local;
33d925b0 1915
c9bccf23 1916 return true;
33d925b0
KH
1917}
1918
ef57d866 1919// ==========================================================================
8c14576d 1920// wxSocketClient
ef57d866 1921// ==========================================================================
f4ada568 1922
ef57d866
GRG
1923// --------------------------------------------------------------------------
1924// Ctor and dtor
1925// --------------------------------------------------------------------------
56d8adc0 1926
71622a7a
GRG
1927wxSocketClient::wxSocketClient(wxSocketFlags flags)
1928 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568 1929{
089b23d0
VZ
1930 m_initialRecvBufferSize =
1931 m_initialSendBufferSize = -1;
f4ada568
GL
1932}
1933
ef57d866
GRG
1934// --------------------------------------------------------------------------
1935// Connect
1936// --------------------------------------------------------------------------
dc5c1114 1937
2b036c4b 1938bool wxSocketClient::DoConnect(const wxSockAddress& remote,
72ac4e88
VZ
1939 const wxSockAddress* local,
1940 bool wait)
f4ada568 1941{
2b036c4b 1942 if ( m_impl )
c2116a35 1943 {
2b036c4b 1944 // Shutdown and destroy the old socket
c2116a35 1945 Close();
51fe4b60 1946 delete m_impl;
c2116a35 1947 }
a324a7bc 1948
c2116a35
VZ
1949 m_connected = false;
1950 m_establishing = false;
384b4373 1951
2b036c4b 1952 // Create and set up the new one
4f260c9c
VZ
1953 wxSocketManager * const manager = wxSocketManager::Get();
1954 m_impl = manager ? manager->CreateSocket(*this) : NULL;
2b036c4b 1955 if ( !m_impl )
c2116a35 1956 return false;
384b4373 1957
c2116a35
VZ
1958 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1959 if (GetFlags() & wxSOCKET_REUSEADDR)
51fe4b60 1960 m_impl->SetReusable();
c2116a35 1961 if (GetFlags() & wxSOCKET_BROADCAST)
51fe4b60 1962 m_impl->SetBroadcast();
c2116a35 1963 if (GetFlags() & wxSOCKET_NOBIND)
51fe4b60 1964 m_impl->DontDoBind();
33d925b0 1965
2b036c4b
VZ
1966 // Bind to the local IP address and port, when provided or if one had been
1967 // set before
c9bccf23 1968 if ( !local && m_localAddress.GetAddress().IsOk() )
c2116a35 1969 local = &m_localAddress;
c2116a35 1970
2b036c4b
VZ
1971 if ( local )
1972 m_impl->SetLocal(local->GetAddress());
33d925b0 1973
51fe4b60 1974 m_impl->SetInitialSocketBuffers(m_initialRecvBufferSize, m_initialSendBufferSize);
8c029a5b 1975
2b036c4b
VZ
1976 m_impl->SetPeer(remote.GetAddress());
1977
1978 // Finally do create the socket and connect to the peer
1979 const wxSocketError err = m_impl->CreateClient(wait);
791b24c4 1980
2b036c4b 1981 if ( err != wxSOCKET_NOERROR )
c2116a35 1982 {
2b036c4b
VZ
1983 if ( err == wxSOCKET_WOULDBLOCK )
1984 {
1985 wxASSERT_MSG( !wait, "shouldn't get this for blocking connect" );
1986
c2116a35 1987 m_establishing = true;
2b036c4b 1988 }
56d8adc0 1989
c2116a35
VZ
1990 return false;
1991 }
9111db68 1992
c2116a35
VZ
1993 m_connected = true;
1994 return true;
f4ada568
GL
1995}
1996
2b036c4b 1997bool wxSocketClient::Connect(const wxSockAddress& remote, bool wait)
33d925b0 1998{
2b036c4b 1999 return DoConnect(remote, NULL, wait);
33d925b0
KH
2000}
2001
2b036c4b 2002bool wxSocketClient::Connect(const wxSockAddress& remote,
72ac4e88
VZ
2003 const wxSockAddress& local,
2004 bool wait)
33d925b0 2005{
2b036c4b 2006 return DoConnect(remote, &local, wait);
33d925b0
KH
2007}
2008
d80d1aba 2009bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 2010{
60ee0172
VZ
2011 if ( m_connected )
2012 {
2013 // this happens if the initial attempt to connect succeeded without
2014 // blocking
7fb0a11d 2015 return true;
60ee0172 2016 }
d80d1aba 2017
51fe4b60 2018 wxCHECK_MSG( m_establishing && m_impl, false,
60ee0172 2019 "No connection establishment attempt in progress" );
d80d1aba 2020
ebbf7407
VZ
2021 // notice that we return true even if DoWait() returned -1, i.e. if an
2022 // error occurred and connection was lost: this is intentional as we should
2023 // return false only if timeout expired without anything happening
2024 return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG) != 0;
f4ada568
GL
2025}
2026
ef57d866 2027// ==========================================================================
dc5c1114 2028// wxDatagramSocket
ef57d866 2029// ==========================================================================
dc5c1114 2030
fbfb8bcc 2031wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
71622a7a
GRG
2032 wxSocketFlags flags )
2033 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114 2034{
7fb0a11d 2035 // Create the socket
4f260c9c
VZ
2036 wxSocketManager * const manager = wxSocketManager::Get();
2037 m_impl = manager ? manager->CreateSocket(*this) : NULL;
dc5c1114 2038
51fe4b60 2039 if (!m_impl)
7fb0a11d 2040 return;
53a161e1 2041
7fb0a11d 2042 // Setup the socket as non connection oriented
51fe4b60 2043 m_impl->SetLocal(addr.GetAddress());
28bf2f3c
VZ
2044 if (flags & wxSOCKET_REUSEADDR)
2045 {
51fe4b60 2046 m_impl->SetReusable();
28bf2f3c 2047 }
60edcf45
VZ
2048 if (GetFlags() & wxSOCKET_BROADCAST)
2049 {
51fe4b60 2050 m_impl->SetBroadcast();
60edcf45
VZ
2051 }
2052 if (GetFlags() & wxSOCKET_NOBIND)
2053 {
51fe4b60 2054 m_impl->DontDoBind();
60edcf45 2055 }
51fe4b60
VZ
2056
2057 if ( m_impl->CreateUDP() != wxSOCKET_NOERROR )
7fb0a11d 2058 {
5276b0a5 2059 wxDELETE(m_impl);
7fb0a11d
WS
2060 return;
2061 }
dc5c1114 2062
7fb0a11d
WS
2063 // Initialize all stuff
2064 m_connected = false;
2065 m_establishing = false;
dc5c1114
GRG
2066}
2067
2068wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 2069 void* buf,
dc5c1114
GRG
2070 wxUint32 nBytes )
2071{
2072 Read(buf, nBytes);
2073 GetPeer(addr);
2074 return (*this);
2075}
2076
fbfb8bcc 2077wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
f187448d 2078 const void* buf,
dc5c1114
GRG
2079 wxUint32 nBytes )
2080{
9a83f860 2081 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
8e3f3880 2082
51fe4b60 2083 m_impl->SetPeer(addr.GetAddress());
dc5c1114
GRG
2084 Write(buf, nBytes);
2085 return (*this);
2086}
2087
ef57d866 2088// ==========================================================================
a58d5df4 2089// wxSocketModule
ef57d866 2090// ==========================================================================
dc5c1114 2091
ed4c6c69 2092class wxSocketModule : public wxModule
dc5c1114 2093{
dc5c1114 2094public:
6c0d0845
VZ
2095 virtual bool OnInit()
2096 {
51fe4b60
VZ
2097 // wxSocketBase will call Initialize() itself only if sockets are
2098 // really used, don't do it from here
d775fa82 2099 return true;
6c0d0845
VZ
2100 }
2101
2102 virtual void OnExit()
2103 {
2104 if ( wxSocketBase::IsInitialized() )
2105 wxSocketBase::Shutdown();
2106 }
2107
2108private:
2109 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
2110};
2111
2112IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
2113
4f61df82 2114#if defined(wxUSE_SELECT_DISPATCHER) && wxUSE_SELECT_DISPATCHER
54e757fc
FM
2115// NOTE: we need to force linking against socketiohandler.cpp otherwise in
2116// static builds of wxWidgets the ManagerSetter::ManagerSetter ctor
2117// contained there wouldn't be ever called
2118wxFORCE_LINK_MODULE( socketiohandler )
4f61df82 2119#endif
54e757fc 2120
4f260c9c 2121// same for ManagerSetter in the MSW file
bb5a9514 2122#ifdef __WINDOWS__
4f260c9c
VZ
2123 wxFORCE_LINK_MODULE( mswsocket )
2124#endif
2125
3270038f 2126// and for OSXManagerSetter in the OS X one
74b1f0b4 2127#ifdef __WXOSX__
3270038f
VZ
2128 wxFORCE_LINK_MODULE( osxsocket )
2129#endif
2130
c2116a35 2131#endif // wxUSE_SOCKETS