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