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