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