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