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