]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
Don't use mnemonic for Cancel button under MSW.
[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
9a83f860 118#define wxTRACE_Socket wxT("wxSocket")
007c77ab 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
9a83f860 774 wxASSERT_MSG( m_countInit > 0, wxT("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 // Shutdown and close the socket
845 if (!m_beingDeleted)
846 Close();
9181a383 847
51fe4b60
VZ
848 // Destroy the implementation object
849 delete m_impl;
c2116a35
VZ
850
851 // Free the pushback buffer
3185abc2 852 free(m_unread);
f4ada568
GL
853}
854
ef57d866
GRG
855bool wxSocketBase::Destroy()
856{
c2116a35
VZ
857 // Delayed destruction: the socket will be deleted during the next idle
858 // loop iteration. This ensures that all pending events have been
859 // processed.
860 m_beingDeleted = true;
861
862 // Shutdown and close the socket
863 Close();
864
22185a1f 865 // Suppress events from now on
c2116a35
VZ
866 Notify(false);
867
3185abc2
VZ
868 // Schedule this object for deletion instead of destroying it right now if
869 // possible as we may have other events pending for it
870 if ( wxTheApp )
c2116a35 871 {
3185abc2 872 wxTheApp->ScheduleForDestruction(this);
c2116a35 873 }
3185abc2 874 else // no app
c2116a35
VZ
875 {
876 // in wxBase we might have no app object at all, don't leak memory
877 delete this;
878 }
879
880 return true;
ef57d866 881}
9181a383 882
51fe4b60 883// ----------------------------------------------------------------------------
64b1cea0 884// simple accessors
51fe4b60
VZ
885// ----------------------------------------------------------------------------
886
64b1cea0
VZ
887void wxSocketBase::SetError(wxSocketError error)
888{
889 m_impl->m_error = error;
890}
891
51fe4b60
VZ
892wxSocketError wxSocketBase::LastError() const
893{
894 return m_impl->GetError();
895}
896
ef57d866 897// --------------------------------------------------------------------------
bffc1eaa 898// Basic IO calls
ef57d866
GRG
899// --------------------------------------------------------------------------
900
64b1cea0 901// The following IO operations update m_lcount:
ef57d866 902// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
f4ada568
GL
903bool wxSocketBase::Close()
904{
c2116a35
VZ
905 // Interrupt pending waits
906 InterruptWait();
907
b67397a7 908 ShutdownOutput();
c2116a35
VZ
909
910 m_connected = false;
911 m_establishing = false;
912 return true;
f4ada568
GL
913}
914
b67397a7
VZ
915void wxSocketBase::ShutdownOutput()
916{
917 if ( m_impl )
918 m_impl->Shutdown();
919}
920
f187448d 921wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
f4ada568 922{
365b8793 923 wxSocketReadGuard read(this);
a324a7bc 924
cc0972a2 925 m_lcount = DoRead(buffer, nbytes);
17aa2bec 926
c2116a35 927 return *this;
96db102a
GRG
928}
929
cc0972a2 930wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)
96db102a 931{
f5395600
VZ
932 wxCHECK_MSG( m_impl, 0, "socket must be valid" );
933
cc0972a2
VZ
934 // We use pointer arithmetic here which doesn't work with void pointers.
935 char *buffer = static_cast<char *>(buffer_);
f5395600 936 wxCHECK_MSG( buffer, 0, "NULL buffer" );
c2116a35 937
cc0972a2
VZ
938 // Try the push back buffer first, even before checking whether the socket
939 // is valid to allow reading previously pushed back data from an already
940 // closed socket.
941 wxUint32 total = GetPushback(buffer, nbytes, false);
c2116a35 942 nbytes -= total;
cc0972a2 943 buffer += total;
c2116a35 944
f5395600 945 while ( nbytes )
cc0972a2 946 {
f5395600
VZ
947 // our socket is non-blocking so Read() will return immediately if
948 // there is nothing to read yet and it's more efficient to try it first
6f405b31
VZ
949 // before entering DoWait() which is going to start dispatching GUI
950 // events and, even more importantly, we must do this under Windows
f5395600
VZ
951 // where we're not going to get notifications about socket being ready
952 // for reading before we read all the existing data from it
d34f724d
VZ
953 const int ret = !m_impl->m_stream || m_connected
954 ? m_impl->Read(buffer, nbytes)
955 : 0;
64b1cea0
VZ
956 if ( ret == -1 )
957 {
f5395600 958 if ( m_impl->GetLastError() == wxSOCKET_WOULDBLOCK )
c2116a35 959 {
f5395600
VZ
960 // if we don't want to wait, just return immediately
961 if ( m_flags & wxSOCKET_NOWAIT )
962 break;
c2116a35 963
6f405b31
VZ
964 // otherwise wait until the socket becomes ready for reading or
965 // an error occurs on it
ebbf7407 966 if ( !DoWaitWithTimeout(wxSOCKET_INPUT_FLAG) )
f5395600
VZ
967 {
968 // and exit if the timeout elapsed before it did
969 SetError(wxSOCKET_TIMEDOUT);
970 break;
971 }
c2116a35 972
f5395600
VZ
973 // retry reading
974 continue;
975 }
976 else // "real" error
977 {
978 SetError(wxSOCKET_IOERR);
c2116a35 979 break;
f5395600
VZ
980 }
981 }
982 else if ( ret == 0 )
983 {
984 // for connection-oriented (e.g. TCP) sockets we can only read
985 // 0 bytes if the other end has been closed, and for connectionless
986 // ones (UDP) this flag doesn't make sense anyhow so we can set it
987 // to true too without doing any harm
988 m_closed = true;
989
990 // we're not going to read anything else and so if we haven't read
991 // anything (or not everything in wxSOCKET_WAITALL case) already,
992 // signal an error
993 if ( (m_flags & wxSOCKET_WAITALL) || !total )
994 SetError(wxSOCKET_IOERR);
995 break;
996 }
c2116a35 997
f5395600 998 total += ret;
c2116a35 999
f5395600
VZ
1000 // if we are happy to read something and not the entire nbytes bytes,
1001 // then we're done
1002 if ( !(m_flags & wxSOCKET_WAITALL) )
1003 break;
64b1cea0 1004
f5395600
VZ
1005 nbytes -= ret;
1006 buffer += ret;
c2116a35 1007 }
96db102a 1008
96db102a 1009 return total;
c2116a35 1010}
f4ada568 1011
c2116a35
VZ
1012wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
1013{
c2116a35
VZ
1014 struct
1015 {
1016 unsigned char sig[4];
1017 unsigned char len[4];
1018 } msg;
1019
365b8793 1020 wxSocketReadGuard read(this);
c2116a35 1021
365b8793 1022 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
c9157492 1023
64b1cea0
VZ
1024 bool ok = false;
1025 if ( DoRead(&msg, sizeof(msg)) == sizeof(msg) )
56d8adc0 1026 {
64b1cea0
VZ
1027 wxUint32 sig = (wxUint32)msg.sig[0];
1028 sig |= (wxUint32)(msg.sig[1] << 8);
1029 sig |= (wxUint32)(msg.sig[2] << 16);
1030 sig |= (wxUint32)(msg.sig[3] << 24);
f4ada568 1031
64b1cea0
VZ
1032 if ( sig == 0xfeeddead )
1033 {
1034 wxUint32 len = (wxUint32)msg.len[0];
1035 len |= (wxUint32)(msg.len[1] << 8);
1036 len |= (wxUint32)(msg.len[2] << 16);
1037 len |= (wxUint32)(msg.len[3] << 24);
f4ada568 1038
64b1cea0
VZ
1039 wxUint32 len2;
1040 if (len > nbytes)
1041 {
1042 len2 = len - nbytes;
1043 len = nbytes;
1044 }
1045 else
1046 len2 = 0;
c2116a35 1047
64b1cea0
VZ
1048 // Don't attempt to read if the msg was zero bytes long.
1049 m_lcount = len ? DoRead(buffer, len) : 0;
c2116a35 1050
64b1cea0
VZ
1051 if ( len2 )
1052 {
1053 char discard_buffer[MAX_DISCARD_SIZE];
1054 long discard_len;
1055
1056 // NOTE: discarded bytes don't add to m_lcount.
1057 do
1058 {
1059 discard_len = len2 > MAX_DISCARD_SIZE
1060 ? MAX_DISCARD_SIZE
1061 : len2;
1062 discard_len = DoRead(discard_buffer, (wxUint32)discard_len);
1063 len2 -= (wxUint32)discard_len;
1064 }
1065 while ((discard_len > 0) && len2);
1066 }
17aa2bec 1067
64b1cea0
VZ
1068 if ( !len2 && DoRead(&msg, sizeof(msg)) == sizeof(msg) )
1069 {
1070 sig = (wxUint32)msg.sig[0];
1071 sig |= (wxUint32)(msg.sig[1] << 8);
1072 sig |= (wxUint32)(msg.sig[2] << 16);
1073 sig |= (wxUint32)(msg.sig[3] << 24);
c2116a35 1074
64b1cea0
VZ
1075 if ( sig == 0xdeadfeed )
1076 ok = true;
1077 }
c2116a35 1078 }
c2116a35 1079 }
062c4861 1080
64b1cea0
VZ
1081 if ( !ok )
1082 SetError(wxSOCKET_IOERR);
96db102a 1083
c2116a35 1084 return *this;
062c4861
GL
1085}
1086
f187448d 1087wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
f4ada568 1088{
365b8793 1089 wxSocketReadGuard read(this);
96db102a 1090
cc0972a2 1091 m_lcount = DoRead(buffer, nbytes);
96db102a 1092
365b8793 1093 Pushback(buffer, m_lcount);
f4ada568 1094
c2116a35 1095 return *this;
f4ada568
GL
1096}
1097
f187448d 1098wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
f4ada568 1099{
365b8793 1100 wxSocketWriteGuard write(this);
56d8adc0 1101
cc0972a2 1102 m_lcount = DoWrite(buffer, nbytes);
96db102a 1103
c2116a35 1104 return *this;
96db102a
GRG
1105}
1106
cc0972a2 1107// This function is a mirror image of DoRead() except that it doesn't use the
f5395600
VZ
1108// push back buffer and doesn't treat 0 return value specially (normally this
1109// shouldn't happen at all here), so please see comments there for explanations
cc0972a2 1110wxUint32 wxSocketBase::DoWrite(const void *buffer_, wxUint32 nbytes)
96db102a 1111{
f5395600
VZ
1112 wxCHECK_MSG( m_impl, 0, "socket must be valid" );
1113
cc0972a2 1114 const char *buffer = static_cast<const char *>(buffer_);
f5395600 1115 wxCHECK_MSG( buffer, 0, "NULL buffer" );
c2116a35 1116
cc0972a2 1117 wxUint32 total = 0;
f5395600 1118 while ( nbytes )
cc0972a2 1119 {
d34f724d 1120 if ( m_impl->m_stream && !m_connected )
f1763270
VZ
1121 {
1122 if ( (m_flags & wxSOCKET_WAITALL) || !total )
1123 SetError(wxSOCKET_IOERR);
1124 break;
1125 }
1126
51fe4b60 1127 const int ret = m_impl->Write(buffer, nbytes);
64b1cea0
VZ
1128 if ( ret == -1 )
1129 {
f5395600 1130 if ( m_impl->GetLastError() == wxSOCKET_WOULDBLOCK )
c2116a35 1131 {
f5395600
VZ
1132 if ( m_flags & wxSOCKET_NOWAIT )
1133 break;
5c9eff30 1134
ebbf7407 1135 if ( !DoWaitWithTimeout(wxSOCKET_OUTPUT_FLAG) )
f5395600
VZ
1136 {
1137 SetError(wxSOCKET_TIMEDOUT);
1138 break;
1139 }
a324a7bc 1140
f5395600
VZ
1141 continue;
1142 }
1143 else // "real" error
1144 {
1145 SetError(wxSOCKET_IOERR);
c2116a35 1146 break;
f5395600
VZ
1147 }
1148 }
c9157492 1149
f5395600 1150 total += ret;
c9157492 1151
f5395600
VZ
1152 if ( !(m_flags & wxSOCKET_WAITALL) )
1153 break;
64b1cea0 1154
f5395600
VZ
1155 nbytes -= ret;
1156 buffer += ret;
81b92e17 1157 }
a324a7bc 1158
c2116a35 1159 return total;
f4ada568
GL
1160}
1161
f187448d 1162wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
062c4861 1163{
c2116a35
VZ
1164 struct
1165 {
1166 unsigned char sig[4];
1167 unsigned char len[4];
1168 } msg;
062c4861 1169
365b8793 1170 wxSocketWriteGuard write(this);
96db102a 1171
365b8793 1172 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_WAITALL);
96db102a 1173
c2116a35
VZ
1174 msg.sig[0] = (unsigned char) 0xad;
1175 msg.sig[1] = (unsigned char) 0xde;
1176 msg.sig[2] = (unsigned char) 0xed;
1177 msg.sig[3] = (unsigned char) 0xfe;
062c4861 1178
c2116a35
VZ
1179 msg.len[0] = (unsigned char) (nbytes & 0xff);
1180 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
1181 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
1182 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
17aa2bec 1183
64b1cea0
VZ
1184 bool ok = false;
1185 if ( DoWrite(&msg, sizeof(msg)) == sizeof(msg) )
1186 {
1187 m_lcount = DoWrite(buffer, nbytes);
1188 if ( m_lcount == nbytes )
1189 {
1190 msg.sig[0] = (unsigned char) 0xed;
1191 msg.sig[1] = (unsigned char) 0xfe;
1192 msg.sig[2] = (unsigned char) 0xad;
1193 msg.sig[3] = (unsigned char) 0xde;
1194 msg.len[0] =
1195 msg.len[1] =
1196 msg.len[2] =
1197 msg.len[3] = (char) 0;
1198
1199 if ( DoWrite(&msg, sizeof(msg)) == sizeof(msg))
1200 ok = true;
1201 }
1202 }
17aa2bec 1203
64b1cea0
VZ
1204 if ( !ok )
1205 SetError(wxSOCKET_IOERR);
96db102a 1206
c2116a35 1207 return *this;
062c4861
GL
1208}
1209
f187448d 1210wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
f4ada568 1211{
c2116a35
VZ
1212 if (nbytes != 0)
1213 Pushback(buffer, nbytes);
f4ada568 1214
64b1cea0 1215 SetError(wxSOCKET_NOERROR);
c2116a35 1216 m_lcount = nbytes;
f4ada568 1217
c2116a35 1218 return *this;
a324a7bc
GL
1219}
1220
96db102a 1221wxSocketBase& wxSocketBase::Discard()
f4ada568 1222{
c2116a35
VZ
1223 char *buffer = new char[MAX_DISCARD_SIZE];
1224 wxUint32 ret;
1225 wxUint32 total = 0;
f4ada568 1226
365b8793 1227 wxSocketReadGuard read(this);
96db102a 1228
365b8793 1229 wxSocketWaitModeChanger changeFlags(this, wxSOCKET_NOWAIT);
384b4373 1230
c2116a35
VZ
1231 do
1232 {
cc0972a2 1233 ret = DoRead(buffer, MAX_DISCARD_SIZE);
c2116a35
VZ
1234 total += ret;
1235 }
1236 while (ret == MAX_DISCARD_SIZE);
f4ada568 1237
c2116a35
VZ
1238 delete[] buffer;
1239 m_lcount = total;
64b1cea0 1240 SetError(wxSOCKET_NOERROR);
17aa2bec 1241
c2116a35 1242 return *this;
f4ada568
GL
1243}
1244
ef57d866
GRG
1245// --------------------------------------------------------------------------
1246// Wait functions
1247// --------------------------------------------------------------------------
f4ada568 1248
51fe4b60 1249/*
00414faf
VZ
1250 This function will check for the events specified in the flags parameter,
1251 and it will return a mask indicating which operations can be performed.
f0db5d75 1252 */
00414faf 1253wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags,
2b036c4b 1254 const timeval *timeout)
f0db5d75 1255{
5e9238f9
VZ
1256 if ( m_fd == INVALID_SOCKET )
1257 return (wxSOCKET_LOST_FLAG & flags);
f0db5d75 1258
5e9238f9
VZ
1259 struct timeval tv;
1260 if ( timeout )
1261 tv = *timeout;
1262 else
1263 tv.tv_sec = tv.tv_usec = 0;
f0db5d75 1264
5e9238f9
VZ
1265 // prepare the FD sets, passing NULL for the one(s) we don't use
1266 fd_set
1267 readfds, *preadfds = NULL,
1268 writefds, *pwritefds = NULL,
1269 exceptfds; // always want to know about errors
f0db5d75 1270
5e9238f9
VZ
1271 if ( flags & wxSOCKET_INPUT_FLAG )
1272 {
1273 preadfds = &readfds;
1274 wxFD_ZERO(preadfds);
1275 wxFD_SET(m_fd, preadfds);
1276 }
f0db5d75 1277
5e9238f9
VZ
1278 // when using non-blocking connect() the socket becomes connected
1279 // (successfully or not) when it becomes writable
1280 if ( flags & (wxSOCKET_OUTPUT_FLAG | wxSOCKET_CONNECTION_FLAG) )
1281 {
1282 pwritefds = &writefds;
1283 wxFD_ZERO(pwritefds);
1284 wxFD_SET(m_fd, pwritefds);
1285 }
f0db5d75 1286
5e9238f9
VZ
1287 wxFD_ZERO(&exceptfds);
1288 wxFD_SET(m_fd, &exceptfds);
f0db5d75 1289
5e9238f9
VZ
1290 const int rc = select(m_fd + 1, preadfds, pwritefds, &exceptfds, &tv);
1291
1292 // check for errors first
1293 if ( rc == -1 || wxFD_ISSET(m_fd, &exceptfds) )
f0db5d75 1294 {
5e9238f9
VZ
1295 m_establishing = false;
1296
1297 return wxSOCKET_LOST_FLAG & flags;
f0db5d75 1298 }
f0db5d75 1299
5e9238f9
VZ
1300 if ( rc == 0 )
1301 return 0;
f0db5d75 1302
5e9238f9 1303 wxASSERT_MSG( rc == 1, "unexpected select() return value" );
f0db5d75 1304
5e9238f9
VZ
1305 wxSocketEventFlags detected = 0;
1306 if ( preadfds && wxFD_ISSET(m_fd, preadfds) )
1307 detected |= wxSOCKET_INPUT_FLAG;
1308
1309 if ( pwritefds && wxFD_ISSET(m_fd, pwritefds) )
f0db5d75 1310 {
5e9238f9
VZ
1311 // check for the case of non-blocking connect()
1312 if ( m_establishing && !m_server )
1313 {
1314 int error;
1315 SOCKOPTLEN_T len = sizeof(error);
1316 m_establishing = false;
1317 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
1318
1319 if ( error )
1320 detected = wxSOCKET_LOST_FLAG;
1321 else
1322 detected |= wxSOCKET_CONNECTION_FLAG;
1323 }
1324 else // not called to get non-blocking connect() status
1325 {
1326 detected |= wxSOCKET_OUTPUT_FLAG;
1327 }
f0db5d75 1328 }
f0db5d75 1329
5e9238f9 1330 return detected & flags;
f0db5d75
VZ
1331}
1332
ebbf7407 1333int
60ee0172 1334wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
6f405b31
VZ
1335{
1336 // Use either the provided timeout or the default timeout value associated
1337 // with this socket.
1338 //
1339 // TODO: allow waiting forever, see #9443
1340 const long timeout = seconds == -1 ? m_timeout * 1000
1341 : seconds * 1000 + milliseconds;
1342
1343 return DoWait(timeout, flags);
1344}
1345
ebbf7407 1346int
6f405b31 1347wxSocketBase::DoWait(long timeout, wxSocketEventFlags flags)
375abe3d 1348{
ebbf7407 1349 wxCHECK_MSG( m_impl, -1, "can't wait on invalid socket" );
375abe3d 1350
9588640d
VZ
1351 // we're never going to become ready if we're not connected (any more)
1352 if ( !m_connected && !m_establishing )
ebbf7407 1353 return -1;
9588640d 1354
60ee0172 1355 // This can be set to true from Interrupt() to exit this function a.s.a.p.
c2116a35 1356 m_interrupt = false;
81b92e17 1357
af2fd961 1358
60ee0172
VZ
1359 const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
1360
1361 // Get the active event loop which we'll use for the message dispatching
2b036c4b
VZ
1362 // when running in the main thread unless this was explicitly disabled by
1363 // setting wxSOCKET_BLOCK flag
60ee0172 1364 wxEventLoopBase *eventLoop;
2b036c4b 1365 if ( !(m_flags & wxSOCKET_BLOCK) && wxIsMainThread() )
60ee0172
VZ
1366 {
1367 eventLoop = wxEventLoop::GetActive();
60ee0172
VZ
1368 }
1369 else // in worker thread
af2fd961 1370 {
60ee0172
VZ
1371 // We never dispatch messages from threads other than the main one.
1372 eventLoop = NULL;
af2fd961
GRG
1373 }
1374
5ab2f257
VZ
1375 // Make sure the events we're interested in are enabled before waiting for
1376 // them: this is really necessary here as otherwise this could happen:
1377 // 1. DoRead(wxSOCKET_WAITALL) is called
1378 // 2. There is nothing to read so DoWait(wxSOCKET_INPUT_FLAG) is called
1379 // 3. Some, but not all data appears, wxSocketImplUnix::OnReadWaiting()
1380 // is called and wxSOCKET_INPUT_FLAG events are disabled in it
1381 // 4. Because of wxSOCKET_WAITALL we call DoWait() again but the events
1382 // are still disabled and we block forever
1383 //
1384 // More elegant solution would be nice but for now simply re-enabling the
1385 // events here will do
1386 m_impl->ReenableEvents(flags & (wxSOCKET_INPUT_FLAG | wxSOCKET_OUTPUT_FLAG));
1387
1388
00414faf
VZ
1389 // Wait until we receive the event we're waiting for or the timeout expires
1390 // (but note that we always execute the loop at least once, even if timeout
1391 // is 0 as this is used for polling)
ebbf7407
VZ
1392 int rc = 0;
1393 for ( bool firstTime = true; !m_interrupt; firstTime = false )
af2fd961 1394 {
00414faf
VZ
1395 long timeLeft = wxMilliClockToLong(timeEnd - wxGetLocalTimeMillis());
1396 if ( timeLeft < 0 )
1397 {
1398 if ( !firstTime )
1399 break; // timed out
1400
1401 timeLeft = 0;
1402 }
1403
2f1c8faf
VZ
1404 wxSocketEventFlags events;
1405 if ( eventLoop )
1406 {
00414faf
VZ
1407 // reset them before starting to wait
1408 m_eventsgot = 0;
1409
1410 eventLoop->DispatchTimeout(timeLeft);
2f1c8faf
VZ
1411
1412 events = m_eventsgot;
1413 }
00414faf
VZ
1414 else // no event loop or waiting in another thread
1415 {
1416 // as explained below, we should always check for wxSOCKET_LOST_FLAG
2b036c4b
VZ
1417 timeval tv;
1418 SetTimeValFromMS(tv, timeLeft);
1419 events = m_impl->Select(flags | wxSOCKET_LOST_FLAG, &tv);
00414faf
VZ
1420 }
1421
1422 // always check for wxSOCKET_LOST_FLAG, even if flags doesn't include
1423 // it, as continuing to wait for anything else after getting it is
1424 // pointless
1425 if ( events & wxSOCKET_LOST_FLAG )
2f1c8faf 1426 {
00414faf
VZ
1427 m_connected = false;
1428 m_establishing = false;
ebbf7407 1429 rc = -1;
00414faf 1430 break;
2f1c8faf 1431 }
60ee0172 1432
00414faf
VZ
1433 // otherwise mask out the bits we're not interested in
1434 events &= flags;
1435
60ee0172 1436 // Incoming connection (server) or connection established (client)?
2f1c8faf 1437 if ( events & wxSOCKET_CONNECTION_FLAG )
c2116a35
VZ
1438 {
1439 m_connected = true;
1440 m_establishing = false;
ebbf7407 1441 rc = true;
c2116a35
VZ
1442 break;
1443 }
c0043a50 1444
60ee0172 1445 // Data available or output buffer ready?
2f1c8faf 1446 if ( (events & wxSOCKET_INPUT_FLAG) || (events & wxSOCKET_OUTPUT_FLAG) )
b8d1915d 1447 {
ebbf7407 1448 rc = true;
c2116a35 1449 break;
b8d1915d 1450 }
f01bca89 1451 }
f4ada568 1452
ebbf7407 1453 return rc;
f4ada568 1454}
f4ada568 1455
a737331d 1456bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 1457{
60ee0172 1458 return DoWait(seconds, milliseconds,
ebbf7407
VZ
1459 wxSOCKET_INPUT_FLAG |
1460 wxSOCKET_OUTPUT_FLAG |
1461 wxSOCKET_CONNECTION_FLAG) != 0;
f4ada568 1462}
f4ada568 1463
a737331d 1464bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 1465{
60ee0172
VZ
1466 // Check pushback buffer before entering DoWait
1467 if ( m_unread )
c2116a35 1468 return true;
96db102a 1469
6f405b31
VZ
1470 // Check if the socket is not already ready for input, if it is, there is
1471 // no need to start waiting for it (worse, we'll actually never get a
1472 // notification about the socket becoming ready if it is already under
1473 // Windows)
1474 if ( m_impl->Select(wxSOCKET_INPUT_FLAG) )
1475 return true;
1476
ebbf7407 1477 return DoWait(seconds, milliseconds, wxSOCKET_INPUT_FLAG) != 0;
f4ada568
GL
1478}
1479
bfa7bf7d 1480
a737331d 1481bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 1482{
6f405b31
VZ
1483 if ( m_impl->Select(wxSOCKET_OUTPUT_FLAG) )
1484 return true;
1485
ebbf7407 1486 return DoWait(seconds, milliseconds, wxSOCKET_OUTPUT_FLAG) != 0;
a737331d 1487}
f4ada568 1488
a737331d
GL
1489bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
1490{
ebbf7407 1491 return DoWait(seconds, milliseconds, wxSOCKET_LOST_FLAG) == -1;
f4ada568 1492}
a737331d 1493
ef57d866
GRG
1494// --------------------------------------------------------------------------
1495// Miscellaneous
1496// --------------------------------------------------------------------------
1497
1498//
1499// Get local or peer address
1500//
1501
c9bccf23 1502bool wxSocketBase::GetPeer(wxSockAddress& addr) const
ef57d866 1503{
c9bccf23 1504 wxCHECK_MSG( m_impl, false, "invalid socket" );
ef57d866 1505
c9bccf23
VZ
1506 const wxSockAddressImpl& peer = m_impl->GetPeer();
1507 if ( !peer.IsOk() )
c2116a35 1508 return false;
007c77ab 1509
c9bccf23 1510 addr.SetAddress(peer);
ef57d866 1511
c2116a35 1512 return true;
ef57d866
GRG
1513}
1514
c9bccf23 1515bool wxSocketBase::GetLocal(wxSockAddress& addr) const
ef57d866 1516{
c9bccf23 1517 wxCHECK_MSG( m_impl, false, "invalid socket" );
ef57d866 1518
c9bccf23
VZ
1519 const wxSockAddressImpl& local = m_impl->GetLocal();
1520 if ( !local.IsOk() )
7fb0a11d 1521 return false;
ef57d866 1522
c9bccf23 1523 addr.SetAddress(local);
ef57d866 1524
7fb0a11d 1525 return true;
ef57d866
GRG
1526}
1527
1528//
1529// Save and restore socket state
1530//
1531
1532void wxSocketBase::SaveState()
1533{
7fb0a11d 1534 wxSocketState *state;
ef57d866 1535
7fb0a11d 1536 state = new wxSocketState();
ef57d866 1537
7fb0a11d
WS
1538 state->m_flags = m_flags;
1539 state->m_notify = m_notify;
1540 state->m_eventmask = m_eventmask;
1541 state->m_clientData = m_clientData;
ef57d866 1542
7fb0a11d 1543 m_states.Append(state);
ef57d866
GRG
1544}
1545
1546void wxSocketBase::RestoreState()
1547{
7fb0a11d
WS
1548 wxList::compatibility_iterator node;
1549 wxSocketState *state;
ef57d866 1550
7fb0a11d
WS
1551 node = m_states.GetLast();
1552 if (!node)
1553 return;
ef57d866 1554
7fb0a11d 1555 state = (wxSocketState *)node->GetData();
ef57d866 1556
7fb0a11d
WS
1557 m_flags = state->m_flags;
1558 m_notify = state->m_notify;
1559 m_eventmask = state->m_eventmask;
1560 m_clientData = state->m_clientData;
37340c48 1561
7fb0a11d
WS
1562 m_states.Erase(node);
1563 delete state;
ef57d866
GRG
1564}
1565
1566//
1567// Timeout and flags
1568//
1569
17aa2bec
GRG
1570void wxSocketBase::SetTimeout(long seconds)
1571{
7fb0a11d 1572 m_timeout = seconds;
17aa2bec 1573
51fe4b60
VZ
1574 if (m_impl)
1575 m_impl->SetTimeout(m_timeout * 1000);
17aa2bec
GRG
1576}
1577
71622a7a 1578void wxSocketBase::SetFlags(wxSocketFlags flags)
f4ada568 1579{
cc0972a2
VZ
1580 // Do some sanity checking on the flags used: not all values can be used
1581 // together.
1582 wxASSERT_MSG( !(flags & wxSOCKET_NOWAIT) ||
1583 !(flags & (wxSOCKET_WAITALL | wxSOCKET_BLOCK)),
1584 "Using wxSOCKET_WAITALL or wxSOCKET_BLOCK with "
1585 "wxSOCKET_NOWAIT doesn't make sense" );
1586
7fb0a11d 1587 m_flags = flags;
f4ada568 1588}
f0a56ab0 1589
f187448d 1590
ef57d866 1591// --------------------------------------------------------------------------
f187448d 1592// Event handling
ef57d866 1593// --------------------------------------------------------------------------
a324a7bc 1594
bffc1eaa 1595void wxSocketBase::OnRequest(wxSocketNotify notification)
f4ada568 1596{
c2116a35 1597 wxSocketEventFlags flag = 0;
5c1193e0 1598 switch ( notification )
c2116a35 1599 {
5c1193e0
VZ
1600 case wxSOCKET_INPUT:
1601 flag = wxSOCKET_INPUT_FLAG;
1602 break;
1603
1604 case wxSOCKET_OUTPUT:
1605 flag = wxSOCKET_OUTPUT_FLAG;
1606 break;
1607
1608 case wxSOCKET_CONNECTION:
1609 flag = wxSOCKET_CONNECTION_FLAG;
40a983ad
VZ
1610
1611 // we're now successfully connected
1612 m_connected = true;
609aa390
VZ
1613 m_establishing = false;
1614
1615 // error was previously set to wxSOCKET_WOULDBLOCK, but this is not
1616 // the case any longer
1617 SetError(wxSOCKET_NOERROR);
5c1193e0
VZ
1618 break;
1619
1620 case wxSOCKET_LOST:
1621 flag = wxSOCKET_LOST_FLAG;
40a983ad 1622
9038fc94
VZ
1623 // if we lost the connection the socket is now closed and not
1624 // connected any more
1625 m_connected = false;
40a983ad 1626 m_closed = true;
5c1193e0
VZ
1627 break;
1628
c2116a35 1629 default:
5c1193e0 1630 wxFAIL_MSG( "unknown wxSocket notification" );
c2116a35
VZ
1631 }
1632
5c1193e0
VZ
1633 // remember the events which were generated for this socket, we're going to
1634 // use this in DoWait()
1635 m_eventsgot |= flag;
1636
1637 // send the wx event if enabled and we're interested in it
1638 if ( m_notify && (m_eventmask & flag) && m_handler )
c2116a35 1639 {
0ed00ab5
VZ
1640 // don't generate the events when we're inside DoWait() called from our
1641 // own code as we are going to consume the data that has just become
1642 // available ourselves and the user code won't see it at all
1643 if ( (notification == wxSOCKET_INPUT && m_reading) ||
1644 (notification == wxSOCKET_OUTPUT && m_writing) )
1645 {
1646 return;
1647 }
1648
5c1193e0
VZ
1649 wxSocketEvent event(m_id);
1650 event.m_event = notification;
1651 event.m_clientData = m_clientData;
1652 event.SetEventObject(this);
c2116a35 1653
5c1193e0 1654 m_handler->AddPendingEvent(event);
bffc1eaa 1655 }
f4ada568
GL
1656}
1657
f187448d
GRG
1658void wxSocketBase::Notify(bool notify)
1659{
7fb0a11d 1660 m_notify = notify;
f187448d
GRG
1661}
1662
1663void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1664{
7fb0a11d 1665 m_eventmask = flags;
f187448d
GRG
1666}
1667
71622a7a 1668void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
f4ada568 1669{
7fb0a11d
WS
1670 m_handler = &handler;
1671 m_id = id;
f4ada568
GL
1672}
1673
ef57d866
GRG
1674// --------------------------------------------------------------------------
1675// Pushback buffer
1676// --------------------------------------------------------------------------
db131261 1677
f187448d 1678void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
f4ada568 1679{
c2116a35 1680 if (!size) return;
dc5c1114 1681
c2116a35
VZ
1682 if (m_unread == NULL)
1683 m_unread = malloc(size);
1684 else
1685 {
1686 void *tmp;
f4ada568 1687
c2116a35
VZ
1688 tmp = malloc(m_unrd_size + size);
1689 memcpy((char *)tmp + size, m_unread, m_unrd_size);
1690 free(m_unread);
a324a7bc 1691
c2116a35
VZ
1692 m_unread = tmp;
1693 }
31528cd3 1694
c2116a35 1695 m_unrd_size += size;
a324a7bc 1696
c2116a35 1697 memcpy(m_unread, buffer, size);
f4ada568
GL
1698}
1699
f187448d 1700wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
f4ada568 1701{
cc0972a2
VZ
1702 wxCHECK_MSG( buffer, 0, "NULL buffer" );
1703
c2116a35
VZ
1704 if (!m_unrd_size)
1705 return 0;
f4ada568 1706
c2116a35
VZ
1707 if (size > (m_unrd_size-m_unrd_cur))
1708 size = m_unrd_size-m_unrd_cur;
96db102a 1709
c2116a35 1710 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
f4ada568 1711
c2116a35 1712 if (!peek)
dc5c1114 1713 {
c2116a35
VZ
1714 m_unrd_cur += size;
1715 if (m_unrd_size == m_unrd_cur)
1716 {
1717 free(m_unread);
1718 m_unread = NULL;
1719 m_unrd_size = 0;
1720 m_unrd_cur = 0;
1721 }
f4ada568 1722 }
f4ada568 1723
c2116a35 1724 return size;
f4ada568
GL
1725}
1726
f187448d 1727
ef57d866 1728// ==========================================================================
c3e646b4 1729// wxSocketServer
ef57d866 1730// ==========================================================================
f4ada568 1731
ef57d866
GRG
1732// --------------------------------------------------------------------------
1733// Ctor
1734// --------------------------------------------------------------------------
56d8adc0 1735
c9bccf23 1736wxSocketServer::wxSocketServer(const wxSockAddress& addr,
71622a7a
GRG
1737 wxSocketFlags flags)
1738 : wxSocketBase(flags, wxSOCKET_SERVER)
f4ada568 1739{
9a83f860 1740 wxLogTrace( wxTRACE_Socket, wxT("Opening wxSocketServer") );
f4ada568 1741
51fe4b60 1742 m_impl = wxSocketImpl::Create(*this);
384b4373 1743
51fe4b60 1744 if (!m_impl)
007c77ab 1745 {
9a83f860 1746 wxLogTrace( wxTRACE_Socket, wxT("*** Failed to create m_impl") );
007c77ab
RL
1747 return;
1748 }
a737331d 1749
2804f77d 1750 // Setup the socket as server
c9bccf23 1751 m_impl->SetLocal(addr.GetAddress());
d775fa82 1752
74c481d1 1753 if (GetFlags() & wxSOCKET_REUSEADDR) {
51fe4b60 1754 m_impl->SetReusable();
74c481d1 1755 }
60edcf45 1756 if (GetFlags() & wxSOCKET_BROADCAST) {
51fe4b60 1757 m_impl->SetBroadcast();
60edcf45
VZ
1758 }
1759 if (GetFlags() & wxSOCKET_NOBIND) {
51fe4b60 1760 m_impl->DontDoBind();
60edcf45 1761 }
74c481d1 1762
51fe4b60 1763 if (m_impl->CreateServer() != wxSOCKET_NOERROR)
007c77ab 1764 {
51fe4b60
VZ
1765 delete m_impl;
1766 m_impl = NULL;
007c77ab 1767
9a83f860 1768 wxLogTrace( wxTRACE_Socket, wxT("*** CreateServer() failed") );
007c77ab
RL
1769 return;
1770 }
1771
9a83f860 1772 wxLogTrace( wxTRACE_Socket, wxT("wxSocketServer on fd %d"), m_impl->m_fd );
f4ada568
GL
1773}
1774
ef57d866
GRG
1775// --------------------------------------------------------------------------
1776// Accept
1777// --------------------------------------------------------------------------
8c14576d 1778
d80d1aba 1779bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1780{
2b036c4b
VZ
1781 if ( !m_impl || (m_impl->m_fd == INVALID_SOCKET) || !m_impl->IsServer() )
1782 {
1783 wxFAIL_MSG( "can only be called for a valid server socket" );
1784
64b1cea0 1785 SetError(wxSOCKET_INVSOCK);
2b036c4b 1786
c2116a35 1787 return false;
2b036c4b
VZ
1788 }
1789
1790 if ( wait )
1791 {
1792 // wait until we get a connection
1793 if ( !m_impl->SelectWithTimeout(wxSOCKET_INPUT_FLAG) )
1794 {
64b1cea0 1795 SetError(wxSOCKET_TIMEDOUT);
2b036c4b
VZ
1796
1797 return false;
1798 }
1799 }
17aa2bec 1800
2b036c4b 1801 sock.m_impl = m_impl->Accept(sock);
d80d1aba 1802
51fe4b60 1803 if ( !sock.m_impl )
2b036c4b 1804 {
64b1cea0 1805 SetError(m_impl->GetLastError());
2b036c4b 1806
c2116a35 1807 return false;
2b036c4b 1808 }
d80d1aba 1809
c2116a35 1810 sock.m_type = wxSOCKET_BASE;
c2116a35 1811 sock.m_connected = true;
f4ada568 1812
c2116a35 1813 return true;
f4ada568
GL
1814}
1815
d80d1aba 1816wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568 1817{
c2116a35 1818 wxSocketBase* sock = new wxSocketBase();
f4ada568 1819
c2116a35 1820 sock->SetFlags(m_flags);
f4ada568 1821
c2116a35
VZ
1822 if (!AcceptWith(*sock, wait))
1823 {
1824 sock->Destroy();
1825 sock = NULL;
1826 }
f4ada568 1827
c2116a35 1828 return sock;
f4ada568
GL
1829}
1830
17aa2bec 1831bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1832{
ebbf7407 1833 return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG) == 1;
d80d1aba
GRG
1834}
1835
bfa7bf7d
VZ
1836bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1837{
9a83f860 1838 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
11734f8a 1839
735ac2bc 1840 SOCKOPTLEN_T lenreal = *optlen;
51fe4b60
VZ
1841 if ( getsockopt(m_impl->m_fd, level, optname,
1842 static_cast<char *>(optval), &lenreal) != 0 )
d775fa82 1843 return false;
51fe4b60
VZ
1844
1845 *optlen = lenreal;
1846
d775fa82 1847 return true;
bfa7bf7d
VZ
1848}
1849
51fe4b60
VZ
1850bool
1851wxSocketBase::SetOption(int level, int optname, const void *optval, int optlen)
bfa7bf7d 1852{
9a83f860 1853 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
8e3f3880 1854
51fe4b60
VZ
1855 return setsockopt(m_impl->m_fd, level, optname,
1856 static_cast<const char *>(optval), optlen) == 0;
bfa7bf7d
VZ
1857}
1858
72ac4e88 1859bool wxSocketBase::SetLocal(const wxIPV4address& local)
33d925b0 1860{
c9bccf23 1861 m_localAddress = local;
33d925b0 1862
c9bccf23 1863 return true;
33d925b0
KH
1864}
1865
ef57d866 1866// ==========================================================================
8c14576d 1867// wxSocketClient
ef57d866 1868// ==========================================================================
f4ada568 1869
ef57d866
GRG
1870// --------------------------------------------------------------------------
1871// Ctor and dtor
1872// --------------------------------------------------------------------------
56d8adc0 1873
71622a7a
GRG
1874wxSocketClient::wxSocketClient(wxSocketFlags flags)
1875 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568 1876{
089b23d0
VZ
1877 m_initialRecvBufferSize =
1878 m_initialSendBufferSize = -1;
f4ada568
GL
1879}
1880
ef57d866
GRG
1881// --------------------------------------------------------------------------
1882// Connect
1883// --------------------------------------------------------------------------
dc5c1114 1884
2b036c4b 1885bool wxSocketClient::DoConnect(const wxSockAddress& remote,
72ac4e88
VZ
1886 const wxSockAddress* local,
1887 bool wait)
f4ada568 1888{
2b036c4b 1889 if ( m_impl )
c2116a35 1890 {
2b036c4b 1891 // Shutdown and destroy the old socket
c2116a35 1892 Close();
51fe4b60 1893 delete m_impl;
c2116a35 1894 }
a324a7bc 1895
c2116a35
VZ
1896 m_connected = false;
1897 m_establishing = false;
384b4373 1898
2b036c4b
VZ
1899 // Create and set up the new one
1900 m_impl = wxSocketImpl::Create(*this);
1901 if ( !m_impl )
c2116a35 1902 return false;
384b4373 1903
c2116a35
VZ
1904 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1905 if (GetFlags() & wxSOCKET_REUSEADDR)
51fe4b60 1906 m_impl->SetReusable();
c2116a35 1907 if (GetFlags() & wxSOCKET_BROADCAST)
51fe4b60 1908 m_impl->SetBroadcast();
c2116a35 1909 if (GetFlags() & wxSOCKET_NOBIND)
51fe4b60 1910 m_impl->DontDoBind();
33d925b0 1911
2b036c4b
VZ
1912 // Bind to the local IP address and port, when provided or if one had been
1913 // set before
c9bccf23 1914 if ( !local && m_localAddress.GetAddress().IsOk() )
c2116a35 1915 local = &m_localAddress;
c2116a35 1916
2b036c4b
VZ
1917 if ( local )
1918 m_impl->SetLocal(local->GetAddress());
33d925b0 1919
51fe4b60 1920 m_impl->SetInitialSocketBuffers(m_initialRecvBufferSize, m_initialSendBufferSize);
8c029a5b 1921
2b036c4b
VZ
1922 m_impl->SetPeer(remote.GetAddress());
1923
1924 // Finally do create the socket and connect to the peer
1925 const wxSocketError err = m_impl->CreateClient(wait);
791b24c4 1926
2b036c4b 1927 if ( err != wxSOCKET_NOERROR )
c2116a35 1928 {
2b036c4b
VZ
1929 if ( err == wxSOCKET_WOULDBLOCK )
1930 {
1931 wxASSERT_MSG( !wait, "shouldn't get this for blocking connect" );
1932
c2116a35 1933 m_establishing = true;
2b036c4b 1934 }
56d8adc0 1935
c2116a35
VZ
1936 return false;
1937 }
9111db68 1938
c2116a35
VZ
1939 m_connected = true;
1940 return true;
f4ada568
GL
1941}
1942
2b036c4b 1943bool wxSocketClient::Connect(const wxSockAddress& remote, bool wait)
33d925b0 1944{
2b036c4b 1945 return DoConnect(remote, NULL, wait);
33d925b0
KH
1946}
1947
2b036c4b 1948bool wxSocketClient::Connect(const wxSockAddress& remote,
72ac4e88
VZ
1949 const wxSockAddress& local,
1950 bool wait)
33d925b0 1951{
2b036c4b 1952 return DoConnect(remote, &local, wait);
33d925b0
KH
1953}
1954
d80d1aba 1955bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1956{
60ee0172
VZ
1957 if ( m_connected )
1958 {
1959 // this happens if the initial attempt to connect succeeded without
1960 // blocking
7fb0a11d 1961 return true;
60ee0172 1962 }
d80d1aba 1963
51fe4b60 1964 wxCHECK_MSG( m_establishing && m_impl, false,
60ee0172 1965 "No connection establishment attempt in progress" );
d80d1aba 1966
ebbf7407
VZ
1967 // notice that we return true even if DoWait() returned -1, i.e. if an
1968 // error occurred and connection was lost: this is intentional as we should
1969 // return false only if timeout expired without anything happening
1970 return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG) != 0;
f4ada568
GL
1971}
1972
ef57d866 1973// ==========================================================================
dc5c1114 1974// wxDatagramSocket
ef57d866 1975// ==========================================================================
dc5c1114 1976
fbfb8bcc 1977wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
71622a7a
GRG
1978 wxSocketFlags flags )
1979 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114 1980{
7fb0a11d 1981 // Create the socket
51fe4b60 1982 m_impl = wxSocketImpl::Create(*this);
dc5c1114 1983
51fe4b60 1984 if (!m_impl)
7fb0a11d 1985 return;
53a161e1 1986
7fb0a11d 1987 // Setup the socket as non connection oriented
51fe4b60 1988 m_impl->SetLocal(addr.GetAddress());
28bf2f3c
VZ
1989 if (flags & wxSOCKET_REUSEADDR)
1990 {
51fe4b60 1991 m_impl->SetReusable();
28bf2f3c 1992 }
60edcf45
VZ
1993 if (GetFlags() & wxSOCKET_BROADCAST)
1994 {
51fe4b60 1995 m_impl->SetBroadcast();
60edcf45
VZ
1996 }
1997 if (GetFlags() & wxSOCKET_NOBIND)
1998 {
51fe4b60 1999 m_impl->DontDoBind();
60edcf45 2000 }
51fe4b60
VZ
2001
2002 if ( m_impl->CreateUDP() != wxSOCKET_NOERROR )
7fb0a11d 2003 {
51fe4b60
VZ
2004 delete m_impl;
2005 m_impl = NULL;
7fb0a11d
WS
2006 return;
2007 }
dc5c1114 2008
7fb0a11d
WS
2009 // Initialize all stuff
2010 m_connected = false;
2011 m_establishing = false;
dc5c1114
GRG
2012}
2013
2014wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 2015 void* buf,
dc5c1114
GRG
2016 wxUint32 nBytes )
2017{
2018 Read(buf, nBytes);
2019 GetPeer(addr);
2020 return (*this);
2021}
2022
fbfb8bcc 2023wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
f187448d 2024 const void* buf,
dc5c1114
GRG
2025 wxUint32 nBytes )
2026{
9a83f860 2027 wxASSERT_MSG( m_impl, wxT("Socket not initialised") );
8e3f3880 2028
51fe4b60 2029 m_impl->SetPeer(addr.GetAddress());
dc5c1114
GRG
2030 Write(buf, nBytes);
2031 return (*this);
2032}
2033
ef57d866 2034// ==========================================================================
a58d5df4 2035// wxSocketModule
ef57d866 2036// ==========================================================================
dc5c1114 2037
ed4c6c69 2038class wxSocketModule : public wxModule
dc5c1114 2039{
dc5c1114 2040public:
6c0d0845
VZ
2041 virtual bool OnInit()
2042 {
51fe4b60
VZ
2043 // wxSocketBase will call Initialize() itself only if sockets are
2044 // really used, don't do it from here
d775fa82 2045 return true;
6c0d0845
VZ
2046 }
2047
2048 virtual void OnExit()
2049 {
2050 if ( wxSocketBase::IsInitialized() )
2051 wxSocketBase::Shutdown();
2052 }
2053
2054private:
2055 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
2056};
2057
2058IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
2059
4f61df82 2060#if defined(wxUSE_SELECT_DISPATCHER) && wxUSE_SELECT_DISPATCHER
54e757fc
FM
2061// NOTE: we need to force linking against socketiohandler.cpp otherwise in
2062// static builds of wxWidgets the ManagerSetter::ManagerSetter ctor
2063// contained there wouldn't be ever called
2064wxFORCE_LINK_MODULE( socketiohandler )
4f61df82 2065#endif
54e757fc 2066
c2116a35 2067#endif // wxUSE_SOCKETS