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