]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
Remove apparently erroneous -1 from DrawBitmap() in wxMSW wxGC code.
[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
VZ
889 // Schedule this object for deletion instead of destroying it right now if
890 // possible as we may have other events pending for it
891 if ( wxTheApp )
c2116a35 892 {
3185abc2 893 wxTheApp->ScheduleForDestruction(this);
c2116a35 894 }
3185abc2 895 else // no app
c2116a35
VZ
896 {
897 // in wxBase we might have no app object at all, don't leak memory
898 delete this;
899 }
900
901 return true;
ef57d866 902}
9181a383 903
51fe4b60 904// ----------------------------------------------------------------------------
64b1cea0 905// simple accessors
51fe4b60
VZ
906// ----------------------------------------------------------------------------
907
64b1cea0
VZ
908void wxSocketBase::SetError(wxSocketError error)
909{
910 m_impl->m_error = error;
911}
912
51fe4b60
VZ
913wxSocketError wxSocketBase::LastError() const
914{
915 return m_impl->GetError();
916}
917
ef57d866 918// --------------------------------------------------------------------------
bffc1eaa 919// Basic IO calls
ef57d866
GRG
920// --------------------------------------------------------------------------
921
64b1cea0 922// The following IO operations update m_lcount:
ef57d866 923// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
f4ada568
GL
924bool wxSocketBase::Close()
925{
c2116a35
VZ
926 // Interrupt pending waits
927 InterruptWait();
928
b67397a7 929 ShutdownOutput();
c2116a35
VZ
930
931 m_connected = false;
932 m_establishing = false;
933 return true;
f4ada568
GL
934}
935
b67397a7
VZ
936void wxSocketBase::ShutdownOutput()
937{
938 if ( m_impl )
939 m_impl->Shutdown();
940}
941
f187448d 942wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
f4ada568 943{
365b8793 944 wxSocketReadGuard read(this);
a324a7bc 945
cc0972a2 946 m_lcount = DoRead(buffer, nbytes);
17aa2bec 947
c2116a35 948 return *this;
96db102a
GRG
949}
950
cc0972a2 951wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)
96db102a 952{
f5395600
VZ
953 wxCHECK_MSG( m_impl, 0, "socket must be valid" );
954
cc0972a2
VZ
955 // We use pointer arithmetic here which doesn't work with void pointers.
956 char *buffer = static_cast<char *>(buffer_);
f5395600 957 wxCHECK_MSG( buffer, 0, "NULL buffer" );
c2116a35 958
cc0972a2
VZ
959 // Try the push back buffer first, even before checking whether the socket
960 // is valid to allow reading previously pushed back data from an already
961 // closed socket.
962 wxUint32 total = GetPushback(buffer, nbytes, false);
c2116a35 963 nbytes -= total;
cc0972a2 964 buffer += total;
c2116a35 965
f5395600 966 while ( nbytes )
cc0972a2 967 {
f5395600
VZ
968 // our socket is non-blocking so Read() will return immediately if
969 // there is nothing to read yet and it's more efficient to try it first
6f405b31
VZ
970 // before entering DoWait() which is going to start dispatching GUI
971 // events and, even more importantly, we must do this under Windows
f5395600
VZ
972 // where we're not going to get notifications about socket being ready
973 // for reading before we read all the existing data from it
d34f724d
VZ
974 const int ret = !m_impl->m_stream || m_connected
975 ? m_impl->Read(buffer, nbytes)
976 : 0;
64b1cea0
VZ
977 if ( ret == -1 )
978 {
f5395600 979 if ( m_impl->GetLastError() == wxSOCKET_WOULDBLOCK )
c2116a35 980 {
f5395600
VZ
981 // if we don't want to wait, just return immediately
982 if ( m_flags & wxSOCKET_NOWAIT )
686d0cc0
VZ
983 {
984 // this shouldn't be counted as an error in this case
985 SetError(wxSOCKET_NOERROR);
f5395600 986 break;
686d0cc0 987 }
c2116a35 988
6f405b31
VZ
989 // otherwise wait until the socket becomes ready for reading or
990 // an error occurs on it
ebbf7407 991 if ( !DoWaitWithTimeout(wxSOCKET_INPUT_FLAG) )
f5395600
VZ
992 {
993 // and exit if the timeout elapsed before it did
994 SetError(wxSOCKET_TIMEDOUT);
995 break;
996 }
c2116a35 997
f5395600
VZ
998 // retry reading
999 continue;
1000 }
1001 else // "real" error
1002 {
1003 SetError(wxSOCKET_IOERR);
c2116a35 1004 break;
f5395600
VZ
1005 }
1006 }
1007 else if ( ret == 0 )
1008 {
1009 // for connection-oriented (e.g. TCP) sockets we can only read
1010 // 0 bytes if the other end has been closed, and for connectionless
1011 // ones (UDP) this flag doesn't make sense anyhow so we can set it
1012 // to true too without doing any harm
1013 m_closed = true;
1014
1015 // we're not going to read anything else and so if we haven't read
1016 // anything (or not everything in wxSOCKET_WAITALL case) already,
1017 // signal an error
1018 if ( (m_flags & wxSOCKET_WAITALL) || !total )
1019 SetError(wxSOCKET_IOERR);
1020 break;
1021 }
c2116a35 1022
f5395600 1023 total += ret;
c2116a35 1024
f5395600
VZ
1025 // if we are happy to read something and not the entire nbytes bytes,
1026 // then we're done
1027 if ( !(m_flags & wxSOCKET_WAITALL) )
1028 break;
64b1cea0 1029
f5395600
VZ
1030 nbytes -= ret;
1031 buffer += ret;
c2116a35 1032 }
96db102a 1033
96db102a 1034 return total;
c2116a35 1035}
f4ada568 1036
c2116a35
VZ
1037wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
1038{
c2116a35
VZ
1039 struct
1040 {
1041 unsigned char sig[4];
1042 unsigned char len[4];
1043 } msg;
1044
365b8793 1045 wxSocketReadGuard read(this);
c2116a35 1046
365b8793 1047 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
c9157492 1048
64b1cea0
VZ
1049 bool ok = false;
1050 if ( DoRead(&msg, sizeof(msg)) == sizeof(msg) )
56d8adc0 1051 {
64b1cea0
VZ
1052 wxUint32 sig = (wxUint32)msg.sig[0];
1053 sig |= (wxUint32)(msg.sig[1] << 8);
1054 sig |= (wxUint32)(msg.sig[2] << 16);
1055 sig |= (wxUint32)(msg.sig[3] << 24);
f4ada568 1056
64b1cea0
VZ
1057 if ( sig == 0xfeeddead )
1058 {
1059 wxUint32 len = (wxUint32)msg.len[0];
1060 len |= (wxUint32)(msg.len[1] << 8);
1061 len |= (wxUint32)(msg.len[2] << 16);
1062 len |= (wxUint32)(msg.len[3] << 24);
f4ada568 1063
64b1cea0
VZ
1064 wxUint32 len2;
1065 if (len > nbytes)
1066 {
1067 len2 = len - nbytes;
1068 len = nbytes;
1069 }
1070 else
1071 len2 = 0;
c2116a35 1072
64b1cea0
VZ
1073 // Don't attempt to read if the msg was zero bytes long.
1074 m_lcount = len ? DoRead(buffer, len) : 0;
c2116a35 1075
64b1cea0
VZ
1076 if ( len2 )
1077 {
1078 char discard_buffer[MAX_DISCARD_SIZE];
1079 long discard_len;
1080
1081 // NOTE: discarded bytes don't add to m_lcount.
1082 do
1083 {
1084 discard_len = len2 > MAX_DISCARD_SIZE
1085 ? MAX_DISCARD_SIZE
1086 : len2;
1087 discard_len = DoRead(discard_buffer, (wxUint32)discard_len);
1088 len2 -= (wxUint32)discard_len;
1089 }
1090 while ((discard_len > 0) && len2);
1091 }
17aa2bec 1092
64b1cea0
VZ
1093 if ( !len2 && DoRead(&msg, sizeof(msg)) == sizeof(msg) )
1094 {
1095 sig = (wxUint32)msg.sig[0];
1096 sig |= (wxUint32)(msg.sig[1] << 8);
1097 sig |= (wxUint32)(msg.sig[2] << 16);
1098 sig |= (wxUint32)(msg.sig[3] << 24);
c2116a35 1099
64b1cea0
VZ
1100 if ( sig == 0xdeadfeed )
1101 ok = true;
1102 }
c2116a35 1103 }
c2116a35 1104 }
062c4861 1105
64b1cea0
VZ
1106 if ( !ok )
1107 SetError(wxSOCKET_IOERR);
96db102a 1108
c2116a35 1109 return *this;
062c4861
GL
1110}
1111
f187448d 1112wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
f4ada568 1113{
365b8793 1114 wxSocketReadGuard read(this);
96db102a 1115
896576e3
VZ
1116 // Peek() should never block
1117 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_NOWAIT);
1118
cc0972a2 1119 m_lcount = DoRead(buffer, nbytes);
96db102a 1120
365b8793 1121 Pushback(buffer, m_lcount);
f4ada568 1122
c2116a35 1123 return *this;
f4ada568
GL
1124}
1125
f187448d 1126wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
f4ada568 1127{
365b8793 1128 wxSocketWriteGuard write(this);
56d8adc0 1129
cc0972a2 1130 m_lcount = DoWrite(buffer, nbytes);
96db102a 1131
c2116a35 1132 return *this;
96db102a
GRG
1133}
1134
cc0972a2 1135// This function is a mirror image of DoRead() except that it doesn't use the
f5395600
VZ
1136// push back buffer and doesn't treat 0 return value specially (normally this
1137// shouldn't happen at all here), so please see comments there for explanations
cc0972a2 1138wxUint32 wxSocketBase::DoWrite(const void *buffer_, wxUint32 nbytes)
96db102a 1139{
f5395600
VZ
1140 wxCHECK_MSG( m_impl, 0, "socket must be valid" );
1141
cc0972a2 1142 const char *buffer = static_cast<const char *>(buffer_);
f5395600 1143 wxCHECK_MSG( buffer, 0, "NULL buffer" );
c2116a35 1144
cc0972a2 1145 wxUint32 total = 0;
f5395600 1146 while ( nbytes )
cc0972a2 1147 {
d34f724d 1148 if ( m_impl->m_stream && !m_connected )
f1763270
VZ
1149 {
1150 if ( (m_flags & wxSOCKET_WAITALL) || !total )
1151 SetError(wxSOCKET_IOERR);
1152 break;
1153 }
1154
51fe4b60 1155 const int ret = m_impl->Write(buffer, nbytes);
64b1cea0
VZ
1156 if ( ret == -1 )
1157 {
f5395600 1158 if ( m_impl->GetLastError() == wxSOCKET_WOULDBLOCK )
c2116a35 1159 {
f5395600
VZ
1160 if ( m_flags & wxSOCKET_NOWAIT )
1161 break;
5c9eff30 1162
ebbf7407 1163 if ( !DoWaitWithTimeout(wxSOCKET_OUTPUT_FLAG) )
f5395600
VZ
1164 {
1165 SetError(wxSOCKET_TIMEDOUT);
1166 break;
1167 }
a324a7bc 1168
f5395600
VZ
1169 continue;
1170 }
1171 else // "real" error
1172 {
1173 SetError(wxSOCKET_IOERR);
c2116a35 1174 break;
f5395600
VZ
1175 }
1176 }
c9157492 1177
f5395600 1178 total += ret;
c9157492 1179
f5395600
VZ
1180 if ( !(m_flags & wxSOCKET_WAITALL) )
1181 break;
64b1cea0 1182
f5395600
VZ
1183 nbytes -= ret;
1184 buffer += ret;
81b92e17 1185 }
a324a7bc 1186
c2116a35 1187 return total;
f4ada568
GL
1188}
1189
f187448d 1190wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
062c4861 1191{
c2116a35
VZ
1192 struct
1193 {
1194 unsigned char sig[4];
1195 unsigned char len[4];
1196 } msg;
062c4861 1197
365b8793 1198 wxSocketWriteGuard write(this);
96db102a 1199
365b8793 1200 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
96db102a 1201
c2116a35
VZ
1202 msg.sig[0] = (unsigned char) 0xad;
1203 msg.sig[1] = (unsigned char) 0xde;
1204 msg.sig[2] = (unsigned char) 0xed;
1205 msg.sig[3] = (unsigned char) 0xfe;
062c4861 1206
c2116a35
VZ
1207 msg.len[0] = (unsigned char) (nbytes & 0xff);
1208 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
1209 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
1210 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
17aa2bec 1211
64b1cea0
VZ
1212 bool ok = false;
1213 if ( DoWrite(&msg, sizeof(msg)) == sizeof(msg) )
1214 {
1215 m_lcount = DoWrite(buffer, nbytes);
1216 if ( m_lcount == nbytes )
1217 {
1218 msg.sig[0] = (unsigned char) 0xed;
1219 msg.sig[1] = (unsigned char) 0xfe;
1220 msg.sig[2] = (unsigned char) 0xad;
1221 msg.sig[3] = (unsigned char) 0xde;
1222 msg.len[0] =
1223 msg.len[1] =
1224 msg.len[2] =
1225 msg.len[3] = (char) 0;
1226
1227 if ( DoWrite(&msg, sizeof(msg)) == sizeof(msg))
1228 ok = true;
1229 }
1230 }
17aa2bec 1231
64b1cea0
VZ
1232 if ( !ok )
1233 SetError(wxSOCKET_IOERR);
96db102a 1234
c2116a35 1235 return *this;
062c4861
GL
1236}
1237
f187448d 1238wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
f4ada568 1239{
c2116a35
VZ
1240 if (nbytes != 0)
1241 Pushback(buffer, nbytes);
f4ada568 1242
64b1cea0 1243 SetError(wxSOCKET_NOERROR);
c2116a35 1244 m_lcount = nbytes;
f4ada568 1245
c2116a35 1246 return *this;
a324a7bc
GL
1247}
1248
96db102a 1249wxSocketBase& wxSocketBase::Discard()
f4ada568 1250{
c2116a35
VZ
1251 char *buffer = new char[MAX_DISCARD_SIZE];
1252 wxUint32 ret;
1253 wxUint32 total = 0;
f4ada568 1254
365b8793 1255 wxSocketReadGuard read(this);
96db102a 1256
365b8793 1257 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_NOWAIT);
384b4373 1258
c2116a35
VZ
1259 do
1260 {
cc0972a2 1261 ret = DoRead(buffer, MAX_DISCARD_SIZE);
c2116a35
VZ
1262 total += ret;
1263 }
1264 while (ret == MAX_DISCARD_SIZE);
f4ada568 1265
c2116a35
VZ
1266 delete[] buffer;
1267 m_lcount = total;
64b1cea0 1268 SetError(wxSOCKET_NOERROR);
17aa2bec 1269
c2116a35 1270 return *this;
f4ada568
GL
1271}
1272
ef57d866
GRG
1273// --------------------------------------------------------------------------
1274// Wait functions
1275// --------------------------------------------------------------------------
f4ada568 1276
51fe4b60 1277/*
00414faf
VZ
1278 This function will check for the events specified in the flags parameter,
1279 and it will return a mask indicating which operations can be performed.
f0db5d75 1280 */
00414faf 1281wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags,
2b036c4b 1282 const timeval *timeout)
f0db5d75 1283{
5e9238f9
VZ
1284 if ( m_fd == INVALID_SOCKET )
1285 return (wxSOCKET_LOST_FLAG & flags);
f0db5d75 1286
5e9238f9
VZ
1287 struct timeval tv;
1288 if ( timeout )
1289 tv = *timeout;
1290 else
1291 tv.tv_sec = tv.tv_usec = 0;
f0db5d75 1292
5e9238f9
VZ
1293 // prepare the FD sets, passing NULL for the one(s) we don't use
1294 fd_set
1295 readfds, *preadfds = NULL,
1296 writefds, *pwritefds = NULL,
1297 exceptfds; // always want to know about errors
f0db5d75 1298
5e9238f9
VZ
1299 if ( flags & wxSOCKET_INPUT_FLAG )
1300 {
1301 preadfds = &readfds;
1302 wxFD_ZERO(preadfds);
1303 wxFD_SET(m_fd, preadfds);
1304 }
f0db5d75 1305
5e9238f9
VZ
1306 // when using non-blocking connect() the socket becomes connected
1307 // (successfully or not) when it becomes writable
1308 if ( flags & (wxSOCKET_OUTPUT_FLAG | wxSOCKET_CONNECTION_FLAG) )
1309 {
1310 pwritefds = &writefds;
1311 wxFD_ZERO(pwritefds);
1312 wxFD_SET(m_fd, pwritefds);
1313 }
f0db5d75 1314
5e9238f9
VZ
1315 wxFD_ZERO(&exceptfds);
1316 wxFD_SET(m_fd, &exceptfds);
f0db5d75 1317
5e9238f9
VZ
1318 const int rc = select(m_fd + 1, preadfds, pwritefds, &exceptfds, &tv);
1319
1320 // check for errors first
1321 if ( rc == -1 || wxFD_ISSET(m_fd, &exceptfds) )
f0db5d75 1322 {
5e9238f9
VZ
1323 m_establishing = false;
1324
1325 return wxSOCKET_LOST_FLAG & flags;
f0db5d75 1326 }
f0db5d75 1327
5e9238f9
VZ
1328 if ( rc == 0 )
1329 return 0;
f0db5d75 1330
5e9238f9 1331 wxASSERT_MSG( rc == 1, "unexpected select() return value" );
f0db5d75 1332
5e9238f9
VZ
1333 wxSocketEventFlags detected = 0;
1334 if ( preadfds && wxFD_ISSET(m_fd, preadfds) )
1335 detected |= wxSOCKET_INPUT_FLAG;
1336
1337 if ( pwritefds && wxFD_ISSET(m_fd, pwritefds) )
f0db5d75 1338 {
5e9238f9
VZ
1339 // check for the case of non-blocking connect()
1340 if ( m_establishing && !m_server )
1341 {
1342 int error;
1343 SOCKOPTLEN_T len = sizeof(error);
1344 m_establishing = false;
1345 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
1346
1347 if ( error )
1348 detected = wxSOCKET_LOST_FLAG;
1349 else
1350 detected |= wxSOCKET_CONNECTION_FLAG;
1351 }
1352 else // not called to get non-blocking connect() status
1353 {
1354 detected |= wxSOCKET_OUTPUT_FLAG;
1355 }
f0db5d75 1356 }
f0db5d75 1357
5e9238f9 1358 return detected & flags;
f0db5d75
VZ
1359}
1360
ebbf7407 1361int
60ee0172 1362wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
6f405b31
VZ
1363{
1364 // Use either the provided timeout or the default timeout value associated
1365 // with this socket.
1366 //
1367 // TODO: allow waiting forever, see #9443
1368 const long timeout = seconds == -1 ? m_timeout * 1000
1369 : seconds * 1000 + milliseconds;
1370
1371 return DoWait(timeout, flags);
1372}
1373
ebbf7407 1374int
6f405b31 1375wxSocketBase::DoWait(long timeout, wxSocketEventFlags flags)
375abe3d 1376{
ebbf7407 1377 wxCHECK_MSG( m_impl, -1, "can't wait on invalid socket" );
375abe3d 1378
1632883f
VZ
1379 // we're never going to become ready in a TCP client if we're not connected
1380 // any more (OTOH a server can call this to precisely wait for a connection
1381 // so do wait for it in this case and UDP client is never "connected")
1382 if ( !m_impl->IsServer() &&
1383 m_impl->m_stream && !m_connected && !m_establishing )
ebbf7407 1384 return -1;
9588640d 1385
60ee0172 1386 // This can be set to true from Interrupt() to exit this function a.s.a.p.
c2116a35 1387 m_interrupt = false;
81b92e17 1388
af2fd961 1389
60ee0172
VZ
1390 const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
1391
1392 // Get the active event loop which we'll use for the message dispatching
2b036c4b
VZ
1393 // when running in the main thread unless this was explicitly disabled by
1394 // setting wxSOCKET_BLOCK flag
60ee0172 1395 wxEventLoopBase *eventLoop;
2b036c4b 1396 if ( !(m_flags & wxSOCKET_BLOCK) && wxIsMainThread() )
60ee0172
VZ
1397 {
1398 eventLoop = wxEventLoop::GetActive();
60ee0172
VZ
1399 }
1400 else // in worker thread
af2fd961 1401 {
60ee0172
VZ
1402 // We never dispatch messages from threads other than the main one.
1403 eventLoop = NULL;
af2fd961
GRG
1404 }
1405
5ab2f257
VZ
1406 // Make sure the events we're interested in are enabled before waiting for
1407 // them: this is really necessary here as otherwise this could happen:
1408 // 1. DoRead(wxSOCKET_WAITALL) is called
1409 // 2. There is nothing to read so DoWait(wxSOCKET_INPUT_FLAG) is called
1410 // 3. Some, but not all data appears, wxSocketImplUnix::OnReadWaiting()
1411 // is called and wxSOCKET_INPUT_FLAG events are disabled in it
1412 // 4. Because of wxSOCKET_WAITALL we call DoWait() again but the events
1413 // are still disabled and we block forever
1414 //
1415 // More elegant solution would be nice but for now simply re-enabling the
1416 // events here will do
1417 m_impl->ReenableEvents(flags & (wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG));
1418
1419
00414faf
VZ
1420 // Wait until we receive the event we're waiting for or the timeout expires
1421 // (but note that we always execute the loop at least once, even if timeout
1422 // is 0 as this is used for polling)
ebbf7407
VZ
1423 int rc = 0;
1424 for ( bool firstTime = true; !m_interrupt; firstTime = false )
af2fd961 1425 {
00414faf
VZ
1426 long timeLeft = wxMilliClockToLong(timeEnd - wxGetLocalTimeMillis());
1427 if ( timeLeft < 0 )
1428 {
1429 if ( !firstTime )
1430 break; // timed out
1431
1432 timeLeft = 0;
1433 }
1434
2f1c8faf
VZ
1435 wxSocketEventFlags events;
1436 if ( eventLoop )
1437 {
00414faf
VZ
1438 // reset them before starting to wait
1439 m_eventsgot = 0;
1440
1441 eventLoop->DispatchTimeout(timeLeft);
2f1c8faf
VZ
1442
1443 events = m_eventsgot;
1444 }
00414faf
VZ
1445 else // no event loop or waiting in another thread
1446 {
1447 // as explained below, we should always check for wxSOCKET_LOST_FLAG
2b036c4b
VZ
1448 timeval tv;
1449 SetTimeValFromMS(tv, timeLeft);
1450 events = m_impl->Select(flags | wxSOCKET_LOST_FLAG, &tv);
00414faf
VZ
1451 }
1452
1453 // always check for wxSOCKET_LOST_FLAG, even if flags doesn't include
1454 // it, as continuing to wait for anything else after getting it is
1455 // pointless
1456 if ( events & wxSOCKET_LOST_FLAG )
2f1c8faf 1457 {
00414faf
VZ
1458 m_connected = false;
1459 m_establishing = false;
ebbf7407 1460 rc = -1;
00414faf 1461 break;
2f1c8faf 1462 }
60ee0172 1463
00414faf
VZ
1464 // otherwise mask out the bits we're not interested in
1465 events &= flags;
1466
60ee0172 1467 // Incoming connection (server) or connection established (client)?
2f1c8faf 1468 if ( events & wxSOCKET_CONNECTION_FLAG )
c2116a35
VZ
1469 {
1470 m_connected = true;
1471 m_establishing = false;
ebbf7407 1472 rc = true;
c2116a35
VZ
1473 break;
1474 }
c0043a50 1475
60ee0172 1476 // Data available or output buffer ready?
2f1c8faf 1477 if ( (events & wxSOCKET_INPUT_FLAG) || (events & wxSOCKET_OUTPUT_FLAG) )
b8d1915d 1478 {
ebbf7407 1479 rc = true;
c2116a35 1480 break;
b8d1915d 1481 }
f01bca89 1482 }
f4ada568 1483
ebbf7407 1484 return rc;
f4ada568 1485}
f4ada568 1486
a737331d 1487bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 1488{
60ee0172 1489 return DoWait(seconds, milliseconds,
ebbf7407
VZ
1490 wxSOCKET_INPUT_FLAG |
1491 wxSOCKET_OUTPUT_FLAG |
1492 wxSOCKET_CONNECTION_FLAG) != 0;
f4ada568 1493}
f4ada568 1494
a737331d 1495bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 1496{
60ee0172
VZ
1497 // Check pushback buffer before entering DoWait
1498 if ( m_unread )
c2116a35 1499 return true;
96db102a 1500
6f405b31
VZ
1501 // Check if the socket is not already ready for input, if it is, there is
1502 // no need to start waiting for it (worse, we'll actually never get a
1503 // notification about the socket becoming ready if it is already under
1504 // Windows)
1505 if ( m_impl->Select(wxSOCKET_INPUT_FLAG) )
1506 return true;
1507
ebbf7407 1508 return DoWait(seconds, milliseconds, wxSOCKET_INPUT_FLAG) != 0;
f4ada568
GL
1509}
1510
bfa7bf7d 1511
a737331d 1512bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 1513{
6f405b31
VZ
1514 if ( m_impl->Select(wxSOCKET_OUTPUT_FLAG) )
1515 return true;
1516
ebbf7407 1517 return DoWait(seconds, milliseconds, wxSOCKET_OUTPUT_FLAG) != 0;
a737331d 1518}
f4ada568 1519
a737331d
GL
1520bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
1521{
ebbf7407 1522 return DoWait(seconds, milliseconds, wxSOCKET_LOST_FLAG) == -1;
f4ada568 1523}
a737331d 1524
ef57d866
GRG
1525// --------------------------------------------------------------------------
1526// Miscellaneous
1527// --------------------------------------------------------------------------
1528
1529//
1530// Get local or peer address
1531//
1532
c9bccf23 1533bool wxSocketBase::GetPeer(wxSockAddress& addr) const
ef57d866 1534{
c9bccf23 1535 wxCHECK_MSG( m_impl, false, "invalid socket" );
ef57d866 1536
c9bccf23
VZ
1537 const wxSockAddressImpl& peer = m_impl->GetPeer();
1538 if ( !peer.IsOk() )
c2116a35 1539 return false;
007c77ab 1540
c9bccf23 1541 addr.SetAddress(peer);
ef57d866 1542
c2116a35 1543 return true;
ef57d866
GRG
1544}
1545
c9bccf23 1546bool wxSocketBase::GetLocal(wxSockAddress& addr) const
ef57d866 1547{
c9bccf23 1548 wxCHECK_MSG( m_impl, false, "invalid socket" );
ef57d866 1549
c9bccf23
VZ
1550 const wxSockAddressImpl& local = m_impl->GetLocal();
1551 if ( !local.IsOk() )
7fb0a11d 1552 return false;
ef57d866 1553
c9bccf23 1554 addr.SetAddress(local);
ef57d866 1555
7fb0a11d 1556 return true;
ef57d866
GRG
1557}
1558
1559//
1560// Save and restore socket state
1561//
1562
1563void wxSocketBase::SaveState()
1564{
7fb0a11d 1565 wxSocketState *state;
ef57d866 1566
7fb0a11d 1567 state = new wxSocketState();
ef57d866 1568
7fb0a11d
WS
1569 state->m_flags = m_flags;
1570 state->m_notify = m_notify;
1571 state->m_eventmask = m_eventmask;
1572 state->m_clientData = m_clientData;
ef57d866 1573
7fb0a11d 1574 m_states.Append(state);
ef57d866
GRG
1575}
1576
1577void wxSocketBase::RestoreState()
1578{
7fb0a11d
WS
1579 wxList::compatibility_iterator node;
1580 wxSocketState *state;
ef57d866 1581
7fb0a11d
WS
1582 node = m_states.GetLast();
1583 if (!node)
1584 return;
ef57d866 1585
7fb0a11d 1586 state = (wxSocketState *)node->GetData();
ef57d866 1587
7fb0a11d
WS
1588 m_flags = state->m_flags;
1589 m_notify = state->m_notify;
1590 m_eventmask = state->m_eventmask;
1591 m_clientData = state->m_clientData;
37340c48 1592
7fb0a11d
WS
1593 m_states.Erase(node);
1594 delete state;
ef57d866
GRG
1595}
1596
1597//
1598// Timeout and flags
1599//
1600
17aa2bec
GRG
1601void wxSocketBase::SetTimeout(long seconds)
1602{
7fb0a11d 1603 m_timeout = seconds;
17aa2bec 1604
51fe4b60
VZ
1605 if (m_impl)
1606 m_impl->SetTimeout(m_timeout * 1000);
17aa2bec
GRG
1607}
1608
71622a7a 1609void wxSocketBase::SetFlags(wxSocketFlags flags)
f4ada568 1610{
cc0972a2
VZ
1611 // Do some sanity checking on the flags used: not all values can be used
1612 // together.
1613 wxASSERT_MSG( !(flags & wxSOCKET_NOWAIT) ||
1614 !(flags & (wxSOCKET_WAITALL | wxSOCKET_BLOCK)),
1615 "Using wxSOCKET_WAITALL or wxSOCKET_BLOCK with "
1616 "wxSOCKET_NOWAIT doesn't make sense" );
1617
7fb0a11d 1618 m_flags = flags;
f4ada568 1619}
f0a56ab0 1620
f187448d 1621
ef57d866 1622// --------------------------------------------------------------------------
f187448d 1623// Event handling
ef57d866 1624// --------------------------------------------------------------------------
a324a7bc 1625
bffc1eaa 1626void wxSocketBase::OnRequest(wxSocketNotify notification)
f4ada568 1627{
c2116a35 1628 wxSocketEventFlags flag = 0;
5c1193e0 1629 switch ( notification )
c2116a35 1630 {
5c1193e0
VZ
1631 case wxSOCKET_INPUT:
1632 flag = wxSOCKET_INPUT_FLAG;
1633 break;
1634
1635 case wxSOCKET_OUTPUT:
1636 flag = wxSOCKET_OUTPUT_FLAG;
1637 break;
1638
1639 case wxSOCKET_CONNECTION:
1640 flag = wxSOCKET_CONNECTION_FLAG;
40a983ad
VZ
1641
1642 // we're now successfully connected
1643 m_connected = true;
609aa390
VZ
1644 m_establishing = false;
1645
1646 // error was previously set to wxSOCKET_WOULDBLOCK, but this is not
1647 // the case any longer
1648 SetError(wxSOCKET_NOERROR);
5c1193e0
VZ
1649 break;
1650
1651 case wxSOCKET_LOST:
1652 flag = wxSOCKET_LOST_FLAG;
40a983ad 1653
9038fc94
VZ
1654 // if we lost the connection the socket is now closed and not
1655 // connected any more
1656 m_connected = false;
40a983ad 1657 m_closed = true;
5c1193e0
VZ
1658 break;
1659
c2116a35 1660 default:
5c1193e0 1661 wxFAIL_MSG( "unknown wxSocket notification" );
c2116a35
VZ
1662 }
1663
5c1193e0
VZ
1664 // remember the events which were generated for this socket, we're going to
1665 // use this in DoWait()
1666 m_eventsgot |= flag;
1667
1668 // send the wx event if enabled and we're interested in it
1669 if ( m_notify && (m_eventmask & flag) && m_handler )
c2116a35 1670 {
0ed00ab5
VZ
1671 // don't generate the events when we're inside DoWait() called from our
1672 // own code as we are going to consume the data that has just become
1673 // available ourselves and the user code won't see it at all
1674 if ( (notification == wxSOCKET_INPUT && m_reading) ||
1675 (notification == wxSOCKET_OUTPUT && m_writing) )
1676 {
1677 return;
1678 }
1679
5c1193e0
VZ
1680 wxSocketEvent event(m_id);
1681 event.m_event = notification;
1682 event.m_clientData = m_clientData;
1683 event.SetEventObject(this);
c2116a35 1684
5c1193e0 1685 m_handler->AddPendingEvent(event);
bffc1eaa 1686 }
f4ada568
GL
1687}
1688
f187448d
GRG
1689void wxSocketBase::Notify(bool notify)
1690{
7fb0a11d 1691 m_notify = notify;
f187448d
GRG
1692}
1693
1694void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1695{
7fb0a11d 1696 m_eventmask = flags;
f187448d
GRG
1697}
1698
71622a7a 1699void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
f4ada568 1700{
7fb0a11d
WS
1701 m_handler = &handler;
1702 m_id = id;
f4ada568
GL
1703}
1704
ef57d866
GRG
1705// --------------------------------------------------------------------------
1706// Pushback buffer
1707// --------------------------------------------------------------------------
db131261 1708
f187448d 1709void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
f4ada568 1710{
c2116a35 1711 if (!size) return;
dc5c1114 1712
c2116a35
VZ
1713 if (m_unread == NULL)
1714 m_unread = malloc(size);
1715 else
1716 {
1717 void *tmp;
f4ada568 1718
c2116a35
VZ
1719 tmp = malloc(m_unrd_size + size);
1720 memcpy((char *)tmp + size, m_unread, m_unrd_size);
1721 free(m_unread);
a324a7bc 1722
c2116a35
VZ
1723 m_unread = tmp;
1724 }
31528cd3 1725
c2116a35 1726 m_unrd_size += size;
a324a7bc 1727
c2116a35 1728 memcpy(m_unread, buffer, size);
f4ada568
GL
1729}
1730
f187448d 1731wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
f4ada568 1732{
cc0972a2
VZ
1733 wxCHECK_MSG( buffer, 0, "NULL buffer" );
1734
c2116a35
VZ
1735 if (!m_unrd_size)
1736 return 0;
f4ada568 1737
c2116a35
VZ
1738 if (size > (m_unrd_size-m_unrd_cur))
1739 size = m_unrd_size-m_unrd_cur;
96db102a 1740
c2116a35 1741 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
f4ada568 1742
c2116a35 1743 if (!peek)
dc5c1114 1744 {
c2116a35
VZ
1745 m_unrd_cur += size;
1746 if (m_unrd_size == m_unrd_cur)
1747 {
1748 free(m_unread);
1749 m_unread = NULL;
1750 m_unrd_size = 0;
1751 m_unrd_cur = 0;
1752 }
f4ada568 1753 }
f4ada568 1754
c2116a35 1755 return size;
f4ada568
GL
1756}
1757
f187448d 1758
ef57d866 1759// ==========================================================================
c3e646b4 1760// wxSocketServer
ef57d866 1761// ==========================================================================
f4ada568 1762
ef57d866
GRG
1763// --------------------------------------------------------------------------
1764// Ctor
1765// --------------------------------------------------------------------------
56d8adc0 1766
c9bccf23 1767wxSocketServer::wxSocketServer(const wxSockAddress& addr,
71622a7a
GRG
1768 wxSocketFlags flags)
1769 : wxSocketBase(flags, wxSOCKET_SERVER)
f4ada568 1770{
9a83f860 1771 wxLogTrace( wxTRACE_Socket, wxT("Opening wxSocketServer") );
f4ada568 1772
4f260c9c
VZ
1773 wxSocketManager * const manager = wxSocketManager::Get();
1774 m_impl = manager ? manager->CreateSocket(*this) : NULL;
384b4373 1775
51fe4b60 1776 if (!m_impl)
007c77ab 1777 {
9a83f860 1778 wxLogTrace( wxTRACE_Socket, wxT("*** Failed to create m_impl") );
007c77ab
RL
1779 return;
1780 }
a737331d 1781
2804f77d 1782 // Setup the socket as server
c9bccf23 1783 m_impl->SetLocal(addr.GetAddress());
d775fa82 1784
74c481d1 1785 if (GetFlags() & wxSOCKET_REUSEADDR) {
51fe4b60 1786 m_impl->SetReusable();
74c481d1 1787 }
60edcf45 1788 if (GetFlags() & wxSOCKET_BROADCAST) {
51fe4b60 1789 m_impl->SetBroadcast();
60edcf45
VZ
1790 }
1791 if (GetFlags() & wxSOCKET_NOBIND) {
51fe4b60 1792 m_impl->DontDoBind();
60edcf45 1793 }
74c481d1 1794
51fe4b60 1795 if (m_impl->CreateServer() != wxSOCKET_NOERROR)
007c77ab 1796 {
5276b0a5 1797 wxDELETE(m_impl);
007c77ab 1798
9a83f860 1799 wxLogTrace( wxTRACE_Socket, wxT("*** CreateServer() failed") );
007c77ab
RL
1800 return;
1801 }
1802
9a83f860 1803 wxLogTrace( wxTRACE_Socket, wxT("wxSocketServer on fd %d"), m_impl->m_fd );
f4ada568
GL
1804}
1805
ef57d866
GRG
1806// --------------------------------------------------------------------------
1807// Accept
1808// --------------------------------------------------------------------------
8c14576d 1809
d80d1aba 1810bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1811{
2b036c4b
VZ
1812 if ( !m_impl || (m_impl->m_fd == INVALID_SOCKET) || !m_impl->IsServer() )
1813 {
1814 wxFAIL_MSG( "can only be called for a valid server socket" );
1815
64b1cea0 1816 SetError(wxSOCKET_INVSOCK);
2b036c4b 1817
c2116a35 1818 return false;
2b036c4b
VZ
1819 }
1820
1821 if ( wait )
1822 {
1823 // wait until we get a connection
1824 if ( !m_impl->SelectWithTimeout(wxSOCKET_INPUT_FLAG) )
1825 {
64b1cea0 1826 SetError(wxSOCKET_TIMEDOUT);
2b036c4b
VZ
1827
1828 return false;
1829 }
1830 }
17aa2bec 1831
2b036c4b 1832 sock.m_impl = m_impl->Accept(sock);
d80d1aba 1833
51fe4b60 1834 if ( !sock.m_impl )
2b036c4b 1835 {
64b1cea0 1836 SetError(m_impl->GetLastError());
2b036c4b 1837
c2116a35 1838 return false;
2b036c4b 1839 }
d80d1aba 1840
c2116a35 1841 sock.m_type = wxSOCKET_BASE;
c2116a35 1842 sock.m_connected = true;
f4ada568 1843
c2116a35 1844 return true;
f4ada568
GL
1845}
1846
d80d1aba 1847wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568 1848{
c2116a35 1849 wxSocketBase* sock = new wxSocketBase();
f4ada568 1850
c2116a35 1851 sock->SetFlags(m_flags);
f4ada568 1852
c2116a35
VZ
1853 if (!AcceptWith(*sock, wait))
1854 {
1855 sock->Destroy();
1856 sock = NULL;
1857 }
f4ada568 1858
c2116a35 1859 return sock;
f4ada568
GL
1860}
1861
17aa2bec 1862bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1863{
ebbf7407 1864 return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG) == 1;
d80d1aba
GRG
1865}
1866
bfa7bf7d
VZ
1867bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1868{
9a83f860 1869 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
11734f8a 1870
735ac2bc 1871 SOCKOPTLEN_T lenreal = *optlen;
51fe4b60
VZ
1872 if ( getsockopt(m_impl->m_fd, level, optname,
1873 static_cast<char *>(optval), &lenreal) != 0 )
d775fa82 1874 return false;
51fe4b60
VZ
1875
1876 *optlen = lenreal;
1877
d775fa82 1878 return true;
bfa7bf7d
VZ
1879}
1880
51fe4b60
VZ
1881bool
1882wxSocketBase::SetOption(int level, int optname, const void *optval, int optlen)
bfa7bf7d 1883{
9a83f860 1884 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
8e3f3880 1885
51fe4b60
VZ
1886 return setsockopt(m_impl->m_fd, level, optname,
1887 static_cast<const char *>(optval), optlen) == 0;
bfa7bf7d
VZ
1888}
1889
72ac4e88 1890bool wxSocketBase::SetLocal(const wxIPV4address& local)
33d925b0 1891{
c9bccf23 1892 m_localAddress = local;
33d925b0 1893
c9bccf23 1894 return true;
33d925b0
KH
1895}
1896
ef57d866 1897// ==========================================================================
8c14576d 1898// wxSocketClient
ef57d866 1899// ==========================================================================
f4ada568 1900
ef57d866
GRG
1901// --------------------------------------------------------------------------
1902// Ctor and dtor
1903// --------------------------------------------------------------------------
56d8adc0 1904
71622a7a
GRG
1905wxSocketClient::wxSocketClient(wxSocketFlags flags)
1906 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568 1907{
089b23d0
VZ
1908 m_initialRecvBufferSize =
1909 m_initialSendBufferSize = -1;
f4ada568
GL
1910}
1911
ef57d866
GRG
1912// --------------------------------------------------------------------------
1913// Connect
1914// --------------------------------------------------------------------------
dc5c1114 1915
2b036c4b 1916bool wxSocketClient::DoConnect(const wxSockAddress& remote,
72ac4e88
VZ
1917 const wxSockAddress* local,
1918 bool wait)
f4ada568 1919{
2b036c4b 1920 if ( m_impl )
c2116a35 1921 {
2b036c4b 1922 // Shutdown and destroy the old socket
c2116a35 1923 Close();
51fe4b60 1924 delete m_impl;
c2116a35 1925 }
a324a7bc 1926
c2116a35
VZ
1927 m_connected = false;
1928 m_establishing = false;
384b4373 1929
2b036c4b 1930 // Create and set up the new one
4f260c9c
VZ
1931 wxSocketManager * const manager = wxSocketManager::Get();
1932 m_impl = manager ? manager->CreateSocket(*this) : NULL;
2b036c4b 1933 if ( !m_impl )
c2116a35 1934 return false;
384b4373 1935
c2116a35
VZ
1936 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1937 if (GetFlags() & wxSOCKET_REUSEADDR)
51fe4b60 1938 m_impl->SetReusable();
c2116a35 1939 if (GetFlags() & wxSOCKET_BROADCAST)
51fe4b60 1940 m_impl->SetBroadcast();
c2116a35 1941 if (GetFlags() & wxSOCKET_NOBIND)
51fe4b60 1942 m_impl->DontDoBind();
33d925b0 1943
2b036c4b
VZ
1944 // Bind to the local IP address and port, when provided or if one had been
1945 // set before
c9bccf23 1946 if ( !local && m_localAddress.GetAddress().IsOk() )
c2116a35 1947 local = &m_localAddress;
c2116a35 1948
2b036c4b
VZ
1949 if ( local )
1950 m_impl->SetLocal(local->GetAddress());
33d925b0 1951
51fe4b60 1952 m_impl->SetInitialSocketBuffers(m_initialRecvBufferSize, m_initialSendBufferSize);
8c029a5b 1953
2b036c4b
VZ
1954 m_impl->SetPeer(remote.GetAddress());
1955
1956 // Finally do create the socket and connect to the peer
1957 const wxSocketError err = m_impl->CreateClient(wait);
791b24c4 1958
2b036c4b 1959 if ( err != wxSOCKET_NOERROR )
c2116a35 1960 {
2b036c4b
VZ
1961 if ( err == wxSOCKET_WOULDBLOCK )
1962 {
1963 wxASSERT_MSG( !wait, "shouldn't get this for blocking connect" );
1964
c2116a35 1965 m_establishing = true;
2b036c4b 1966 }
56d8adc0 1967
c2116a35
VZ
1968 return false;
1969 }
9111db68 1970
c2116a35
VZ
1971 m_connected = true;
1972 return true;
f4ada568
GL
1973}
1974
2b036c4b 1975bool wxSocketClient::Connect(const wxSockAddress& remote, bool wait)
33d925b0 1976{
2b036c4b 1977 return DoConnect(remote, NULL, wait);
33d925b0
KH
1978}
1979
2b036c4b 1980bool wxSocketClient::Connect(const wxSockAddress& remote,
72ac4e88
VZ
1981 const wxSockAddress& local,
1982 bool wait)
33d925b0 1983{
2b036c4b 1984 return DoConnect(remote, &local, wait);
33d925b0
KH
1985}
1986
d80d1aba 1987bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1988{
60ee0172
VZ
1989 if ( m_connected )
1990 {
1991 // this happens if the initial attempt to connect succeeded without
1992 // blocking
7fb0a11d 1993 return true;
60ee0172 1994 }
d80d1aba 1995
51fe4b60 1996 wxCHECK_MSG( m_establishing && m_impl, false,
60ee0172 1997 "No connection establishment attempt in progress" );
d80d1aba 1998
ebbf7407
VZ
1999 // notice that we return true even if DoWait() returned -1, i.e. if an
2000 // error occurred and connection was lost: this is intentional as we should
2001 // return false only if timeout expired without anything happening
2002 return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG) != 0;
f4ada568
GL
2003}
2004
ef57d866 2005// ==========================================================================
dc5c1114 2006// wxDatagramSocket
ef57d866 2007// ==========================================================================
dc5c1114 2008
fbfb8bcc 2009wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
71622a7a
GRG
2010 wxSocketFlags flags )
2011 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114 2012{
7fb0a11d 2013 // Create the socket
4f260c9c
VZ
2014 wxSocketManager * const manager = wxSocketManager::Get();
2015 m_impl = manager ? manager->CreateSocket(*this) : NULL;
dc5c1114 2016
51fe4b60 2017 if (!m_impl)
7fb0a11d 2018 return;
53a161e1 2019
7fb0a11d 2020 // Setup the socket as non connection oriented
51fe4b60 2021 m_impl->SetLocal(addr.GetAddress());
28bf2f3c
VZ
2022 if (flags & wxSOCKET_REUSEADDR)
2023 {
51fe4b60 2024 m_impl->SetReusable();
28bf2f3c 2025 }
60edcf45
VZ
2026 if (GetFlags() & wxSOCKET_BROADCAST)
2027 {
51fe4b60 2028 m_impl->SetBroadcast();
60edcf45
VZ
2029 }
2030 if (GetFlags() & wxSOCKET_NOBIND)
2031 {
51fe4b60 2032 m_impl->DontDoBind();
60edcf45 2033 }
51fe4b60
VZ
2034
2035 if ( m_impl->CreateUDP() != wxSOCKET_NOERROR )
7fb0a11d 2036 {
5276b0a5 2037 wxDELETE(m_impl);
7fb0a11d
WS
2038 return;
2039 }
dc5c1114 2040
7fb0a11d
WS
2041 // Initialize all stuff
2042 m_connected = false;
2043 m_establishing = false;
dc5c1114
GRG
2044}
2045
2046wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 2047 void* buf,
dc5c1114
GRG
2048 wxUint32 nBytes )
2049{
2050 Read(buf, nBytes);
2051 GetPeer(addr);
2052 return (*this);
2053}
2054
fbfb8bcc 2055wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
f187448d 2056 const void* buf,
dc5c1114
GRG
2057 wxUint32 nBytes )
2058{
9a83f860 2059 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
8e3f3880 2060
51fe4b60 2061 m_impl->SetPeer(addr.GetAddress());
dc5c1114
GRG
2062 Write(buf, nBytes);
2063 return (*this);
2064}
2065
ef57d866 2066// ==========================================================================
a58d5df4 2067// wxSocketModule
ef57d866 2068// ==========================================================================
dc5c1114 2069
ed4c6c69 2070class wxSocketModule : public wxModule
dc5c1114 2071{
dc5c1114 2072public:
6c0d0845
VZ
2073 virtual bool OnInit()
2074 {
51fe4b60
VZ
2075 // wxSocketBase will call Initialize() itself only if sockets are
2076 // really used, don't do it from here
d775fa82 2077 return true;
6c0d0845
VZ
2078 }
2079
2080 virtual void OnExit()
2081 {
2082 if ( wxSocketBase::IsInitialized() )
2083 wxSocketBase::Shutdown();
2084 }
2085
2086private:
2087 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
2088};
2089
2090IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
2091
4f61df82 2092#if defined(wxUSE_SELECT_DISPATCHER) && wxUSE_SELECT_DISPATCHER
54e757fc
FM
2093// NOTE: we need to force linking against socketiohandler.cpp otherwise in
2094// static builds of wxWidgets the ManagerSetter::ManagerSetter ctor
2095// contained there wouldn't be ever called
2096wxFORCE_LINK_MODULE( socketiohandler )
4f61df82 2097#endif
54e757fc 2098
4f260c9c
VZ
2099// same for ManagerSetter in the MSW file
2100#ifdef __WXMSW__
2101 wxFORCE_LINK_MODULE( mswsocket )
2102#endif
2103
3270038f 2104// and for OSXManagerSetter in the OS X one
74b1f0b4 2105#ifdef __WXOSX__
3270038f
VZ
2106 wxFORCE_LINK_MODULE( osxsocket )
2107#endif
2108
c2116a35 2109#endif // wxUSE_SOCKETS