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