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