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