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