]> git.saurik.com Git - wxWidgets.git/blame - src/common/socket.cpp
PCH-less build fixes
[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
ef57d866
GRG
506// ==========================================================================
507// wxSocketBase
508// ==========================================================================
509
6c0d0845
VZ
510// --------------------------------------------------------------------------
511// Initialization and shutdown
512// --------------------------------------------------------------------------
513
514// FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
515// to m_countInit with a crit section
516size_t wxSocketBase::m_countInit = 0;
517
518bool wxSocketBase::IsInitialized()
519{
520 return m_countInit > 0;
521}
522
523bool wxSocketBase::Initialize()
524{
525 if ( !m_countInit++ )
526 {
51fe4b60
VZ
527 wxSocketManager * const manager = wxSocketManager::Get();
528 if ( !manager || !manager->OnInit() )
6c0d0845
VZ
529 {
530 m_countInit--;
531
d775fa82 532 return false;
6c0d0845
VZ
533 }
534 }
535
d775fa82 536 return true;
6c0d0845
VZ
537}
538
539void wxSocketBase::Shutdown()
540{
541 // we should be initialized
2804f77d 542 wxASSERT_MSG( m_countInit > 0, _T("extra call to Shutdown()") );
8d7eaf91 543 if ( --m_countInit == 0 )
6c0d0845 544 {
51fe4b60
VZ
545 wxSocketManager * const manager = wxSocketManager::Get();
546 wxCHECK_RET( manager, "should have a socket manager" );
547
548 manager->OnExit();
6c0d0845
VZ
549 }
550}
551
ef57d866
GRG
552// --------------------------------------------------------------------------
553// Ctor and dtor
554// --------------------------------------------------------------------------
56d8adc0 555
71622a7a 556void wxSocketBase::Init()
f4ada568 557{
51fe4b60 558 m_impl = NULL;
c2116a35
VZ
559 m_type = wxSOCKET_UNINIT;
560
561 // state
562 m_flags = 0;
563 m_connected =
564 m_establishing =
565 m_reading =
566 m_writing =
567 m_error =
568 m_closed = false;
569 m_lcount = 0;
570 m_timeout = 600;
571 m_beingDeleted = false;
572
573 // pushback buffer
574 m_unread = NULL;
575 m_unrd_size = 0;
576 m_unrd_cur = 0;
577
578 // events
579 m_id = wxID_ANY;
580 m_handler = NULL;
581 m_clientData = NULL;
582 m_notify = false;
583 m_eventmask = 0;
584
585 if ( !IsInitialized() )
586 {
587 // this Initialize() will be undone by wxSocketModule::OnExit(), all
588 // the other calls to it should be matched by a call to Shutdown()
589 Initialize();
590 }
f4ada568
GL
591}
592
f187448d
GRG
593wxSocketBase::wxSocketBase()
594{
c2116a35 595 Init();
f187448d 596}
71622a7a
GRG
597
598wxSocketBase::wxSocketBase(wxSocketFlags flags, wxSocketType type)
f4ada568 599{
c2116a35 600 Init();
71622a7a 601
cc0972a2
VZ
602 SetFlags(flags);
603
604 m_type = type;
f4ada568
GL
605}
606
f4ada568
GL
607wxSocketBase::~wxSocketBase()
608{
c2116a35
VZ
609 // Just in case the app called Destroy() *and* then deleted the socket
610 // immediately: don't leave dangling pointers.
611 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
612 if ( traits )
613 traits->RemoveFromPendingDelete(this);
f4ada568 614
c2116a35
VZ
615 // Shutdown and close the socket
616 if (!m_beingDeleted)
617 Close();
9181a383 618
51fe4b60
VZ
619 // Destroy the implementation object
620 delete m_impl;
c2116a35
VZ
621
622 // Free the pushback buffer
623 if (m_unread)
624 free(m_unread);
f4ada568
GL
625}
626
ef57d866
GRG
627bool wxSocketBase::Destroy()
628{
c2116a35
VZ
629 // Delayed destruction: the socket will be deleted during the next idle
630 // loop iteration. This ensures that all pending events have been
631 // processed.
632 m_beingDeleted = true;
633
634 // Shutdown and close the socket
635 Close();
636
637 // Supress events from now on
638 Notify(false);
639
640 // schedule this object for deletion
641 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
642 if ( traits )
643 {
644 // let the traits object decide what to do with us
645 traits->ScheduleForDestroy(this);
646 }
647 else // no app or no traits
648 {
649 // in wxBase we might have no app object at all, don't leak memory
650 delete this;
651 }
652
653 return true;
ef57d866 654}
9181a383 655
51fe4b60
VZ
656// ----------------------------------------------------------------------------
657// simply accessors
658// ----------------------------------------------------------------------------
659
660wxSocketError wxSocketBase::LastError() const
661{
662 return m_impl->GetError();
663}
664
ef57d866 665// --------------------------------------------------------------------------
bffc1eaa 666// Basic IO calls
ef57d866
GRG
667// --------------------------------------------------------------------------
668
669// The following IO operations update m_error and m_lcount:
670// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
671//
672// TODO: Should Connect, Accept and AcceptWith update m_error?
673
f4ada568
GL
674bool wxSocketBase::Close()
675{
c2116a35
VZ
676 // Interrupt pending waits
677 InterruptWait();
678
51fe4b60
VZ
679 if (m_impl)
680 m_impl->Shutdown();
c2116a35
VZ
681
682 m_connected = false;
683 m_establishing = false;
684 return true;
f4ada568
GL
685}
686
f187448d 687wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
f4ada568 688{
c2116a35
VZ
689 // Mask read events
690 m_reading = true;
a324a7bc 691
cc0972a2 692 m_lcount = DoRead(buffer, nbytes);
17aa2bec 693
c2116a35
VZ
694 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
695 if (m_flags & wxSOCKET_WAITALL)
696 m_error = (m_lcount != nbytes);
697 else
698 m_error = (m_lcount == 0);
f4ada568 699
c2116a35
VZ
700 // Allow read events from now on
701 m_reading = false;
17aa2bec 702
c2116a35 703 return *this;
96db102a
GRG
704}
705
cc0972a2 706wxUint32 wxSocketBase::DoRead(void* buffer_, wxUint32 nbytes)
96db102a 707{
cc0972a2
VZ
708 // We use pointer arithmetic here which doesn't work with void pointers.
709 char *buffer = static_cast<char *>(buffer_);
c2116a35 710
cc0972a2
VZ
711 // Try the push back buffer first, even before checking whether the socket
712 // is valid to allow reading previously pushed back data from an already
713 // closed socket.
714 wxUint32 total = GetPushback(buffer, nbytes, false);
c2116a35 715 nbytes -= total;
cc0972a2 716 buffer += total;
c2116a35 717
cc0972a2 718 // If it's indeed closed or if read everything, there is nothing more to do.
51fe4b60 719 if ( !m_impl || !nbytes )
c2116a35
VZ
720 return total;
721
cc0972a2
VZ
722 wxCHECK_MSG( buffer, 0, "NULL buffer" );
723
c9157492 724
cc0972a2
VZ
725 // wxSOCKET_NOWAIT overrides all the other flags and means that we are
726 // polling the socket and don't block at all.
727 if ( m_flags & wxSOCKET_NOWAIT )
728 {
51fe4b60
VZ
729 wxSocketUnblocker unblock(m_impl);
730 int ret = m_impl->Read(buffer, nbytes);
c2116a35
VZ
731 if ( ret < 0 )
732 return 0;
a324a7bc 733
c2116a35
VZ
734 total += ret;
735 }
736 else // blocking socket
737 {
738 for ( ;; )
739 {
cc0972a2
VZ
740 // Wait until socket becomes ready for reading dispatching the GUI
741 // events in the meanwhile unless wxSOCKET_BLOCK was explicitly
742 // specified to disable this.
c2116a35
VZ
743 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
744 break;
745
51fe4b60 746 const int ret = m_impl->Read(buffer, nbytes);
c2116a35
VZ
747 if ( ret == 0 )
748 {
749 // for connection-oriented (e.g. TCP) sockets we can only read
750 // 0 bytes if the other end has been closed, and for
751 // connectionless ones (UDP) this flag doesn't make sense
752 // anyhow so we can set it to true too without doing any harm
753 m_closed = true;
754 break;
755 }
756
757 if ( ret < 0 )
758 {
759 // this will be always interpreted as error by Read()
760 return 0;
761 }
762
763 total += ret;
764
cc0972a2
VZ
765 // If wxSOCKET_WAITALL is not set, we can leave now as we did read
766 // something and we don't need to wait for all nbytes bytes to be
767 // read.
c2116a35
VZ
768 if ( !(m_flags & wxSOCKET_WAITALL) )
769 break;
770
cc0972a2 771 // Otherwise continue reading until we do read everything.
c2116a35
VZ
772 nbytes -= ret;
773 if ( !nbytes )
774 break;
775
cc0972a2 776 buffer += ret;
c2116a35
VZ
777 }
778 }
96db102a 779
96db102a 780 return total;
c2116a35 781}
f4ada568 782
c2116a35
VZ
783wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
784{
785 wxUint32 len, len2, sig, total;
786 bool error;
787 int old_flags;
788 struct
789 {
790 unsigned char sig[4];
791 unsigned char len[4];
792 } msg;
793
794 // Mask read events
795 m_reading = true;
796
797 total = 0;
798 error = true;
799 old_flags = m_flags;
800 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
c9157492 801
cc0972a2 802 if (DoRead(&msg, sizeof(msg)) != sizeof(msg))
c2116a35
VZ
803 goto exit;
804
805 sig = (wxUint32)msg.sig[0];
806 sig |= (wxUint32)(msg.sig[1] << 8);
807 sig |= (wxUint32)(msg.sig[2] << 16);
808 sig |= (wxUint32)(msg.sig[3] << 24);
809
810 if (sig != 0xfeeddead)
56d8adc0 811 {
c2116a35
VZ
812 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
813 goto exit;
81b92e17 814 }
f4ada568 815
c2116a35
VZ
816 len = (wxUint32)msg.len[0];
817 len |= (wxUint32)(msg.len[1] << 8);
818 len |= (wxUint32)(msg.len[2] << 16);
819 len |= (wxUint32)(msg.len[3] << 24);
f4ada568 820
c2116a35
VZ
821 if (len > nbytes)
822 {
823 len2 = len - nbytes;
824 len = nbytes;
825 }
826 else
827 len2 = 0;
828
829 // Don't attempt to read if the msg was zero bytes long.
830 if (len)
17aa2bec 831 {
cc0972a2 832 total = DoRead(buffer, len);
c2116a35
VZ
833
834 if (total != len)
835 goto exit;
17aa2bec 836 }
17aa2bec 837
c2116a35
VZ
838 if (len2)
839 {
840 char *discard_buffer = new char[MAX_DISCARD_SIZE];
841 long discard_len;
842
843 // NOTE: discarded bytes don't add to m_lcount.
844 do
845 {
846 discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
cc0972a2 847 discard_len = DoRead(discard_buffer, (wxUint32)discard_len);
c2116a35
VZ
848 len2 -= (wxUint32)discard_len;
849 }
850 while ((discard_len > 0) && len2);
851
852 delete [] discard_buffer;
17aa2bec 853
c2116a35
VZ
854 if (len2 != 0)
855 goto exit;
856 }
cc0972a2 857 if (DoRead(&msg, sizeof(msg)) != sizeof(msg))
c2116a35 858 goto exit;
062c4861 859
c2116a35
VZ
860 sig = (wxUint32)msg.sig[0];
861 sig |= (wxUint32)(msg.sig[1] << 8);
862 sig |= (wxUint32)(msg.sig[2] << 16);
863 sig |= (wxUint32)(msg.sig[3] << 24);
a324a7bc 864
c2116a35
VZ
865 if (sig != 0xdeadfeed)
866 {
867 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
868 goto exit;
869 }
062c4861 870
c2116a35
VZ
871 // everything was OK
872 error = false;
96db102a
GRG
873
874exit:
c2116a35
VZ
875 m_error = error;
876 m_lcount = total;
877 m_reading = false;
878 SetFlags(old_flags);
96db102a 879
c2116a35 880 return *this;
062c4861
GL
881}
882
f187448d 883wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
f4ada568 884{
c2116a35
VZ
885 // Mask read events
886 m_reading = true;
96db102a 887
cc0972a2 888 m_lcount = DoRead(buffer, nbytes);
c2116a35 889 Pushback(buffer, m_lcount);
96db102a 890
c2116a35
VZ
891 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
892 if (m_flags & wxSOCKET_WAITALL)
893 m_error = (m_lcount != nbytes);
894 else
895 m_error = (m_lcount == 0);
96db102a 896
c2116a35
VZ
897 // Allow read events again
898 m_reading = false;
f4ada568 899
c2116a35 900 return *this;
f4ada568
GL
901}
902
f187448d 903wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
f4ada568 904{
c2116a35
VZ
905 // Mask write events
906 m_writing = true;
56d8adc0 907
cc0972a2 908 m_lcount = DoWrite(buffer, nbytes);
96db102a 909
c2116a35
VZ
910 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
911 if (m_flags & wxSOCKET_WAITALL)
912 m_error = (m_lcount != nbytes);
913 else
914 m_error = (m_lcount == 0);
96db102a 915
c2116a35
VZ
916 // Allow write events again
917 m_writing = false;
96db102a 918
c2116a35 919 return *this;
96db102a
GRG
920}
921
cc0972a2
VZ
922// This function is a mirror image of DoRead() except that it doesn't use the
923// push back buffer, please see comments there
924wxUint32 wxSocketBase::DoWrite(const void *buffer_, wxUint32 nbytes)
96db102a 925{
cc0972a2 926 const char *buffer = static_cast<const char *>(buffer_);
c2116a35 927
cc0972a2 928 // Return if there is nothing to read or the socket is (already?) closed.
51fe4b60 929 if ( !m_impl || !nbytes )
c2116a35
VZ
930 return 0;
931
cc0972a2 932 wxCHECK_MSG( buffer, 0, "NULL buffer" );
81b92e17 933
cc0972a2
VZ
934 wxUint32 total = 0;
935 if ( m_flags & wxSOCKET_NOWAIT )
936 {
51fe4b60
VZ
937 wxSocketUnblocker unblock(m_impl);
938 const int ret = m_impl->Write(buffer, nbytes);
cc0972a2
VZ
939 if ( ret > 0 )
940 total += ret;
c2116a35
VZ
941 }
942 else // blocking socket
943 {
944 for ( ;; )
945 {
946 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
947 break;
948
51fe4b60 949 const int ret = m_impl->Write(buffer, nbytes);
c2116a35
VZ
950 if ( ret == 0 )
951 {
952 m_closed = true;
953 break;
954 }
5c9eff30 955
c2116a35 956 if ( ret < 0 )
c2116a35 957 return 0;
a324a7bc 958
c2116a35
VZ
959 total += ret;
960 if ( !(m_flags & wxSOCKET_WAITALL) )
961 break;
c9157492 962
c2116a35
VZ
963 nbytes -= ret;
964 if ( !nbytes )
965 break;
c9157492 966
cc0972a2 967 buffer += ret;
c2116a35 968 }
81b92e17 969 }
a324a7bc 970
c2116a35 971 return total;
f4ada568
GL
972}
973
f187448d 974wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
062c4861 975{
c2116a35
VZ
976 wxUint32 total;
977 bool error;
978 struct
979 {
980 unsigned char sig[4];
981 unsigned char len[4];
982 } msg;
062c4861 983
c2116a35
VZ
984 // Mask write events
985 m_writing = true;
96db102a 986
c2116a35
VZ
987 error = true;
988 total = 0;
989 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
96db102a 990
c2116a35
VZ
991 msg.sig[0] = (unsigned char) 0xad;
992 msg.sig[1] = (unsigned char) 0xde;
993 msg.sig[2] = (unsigned char) 0xed;
994 msg.sig[3] = (unsigned char) 0xfe;
062c4861 995
c2116a35
VZ
996 msg.len[0] = (unsigned char) (nbytes & 0xff);
997 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
998 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
999 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
17aa2bec 1000
cc0972a2 1001 if (DoWrite(&msg, sizeof(msg)) < sizeof(msg))
c2116a35 1002 goto exit;
96db102a 1003
cc0972a2 1004 total = DoWrite(buffer, nbytes);
96db102a 1005
c2116a35
VZ
1006 if (total < nbytes)
1007 goto exit;
062c4861 1008
c2116a35
VZ
1009 msg.sig[0] = (unsigned char) 0xed;
1010 msg.sig[1] = (unsigned char) 0xfe;
1011 msg.sig[2] = (unsigned char) 0xad;
1012 msg.sig[3] = (unsigned char) 0xde;
1013 msg.len[0] =
1014 msg.len[1] =
1015 msg.len[2] =
1016 msg.len[3] = (char) 0;
062c4861 1017
cc0972a2 1018 if ((DoWrite(&msg, sizeof(msg))) < sizeof(msg))
c2116a35 1019 goto exit;
17aa2bec 1020
c2116a35
VZ
1021 // everything was OK
1022 error = false;
96db102a
GRG
1023
1024exit:
c2116a35
VZ
1025 m_error = error;
1026 m_lcount = total;
1027 m_writing = false;
96db102a 1028
c2116a35 1029 return *this;
062c4861
GL
1030}
1031
f187448d 1032wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
f4ada568 1033{
c2116a35
VZ
1034 if (nbytes != 0)
1035 Pushback(buffer, nbytes);
f4ada568 1036
c2116a35
VZ
1037 m_error = false;
1038 m_lcount = nbytes;
f4ada568 1039
c2116a35 1040 return *this;
a324a7bc
GL
1041}
1042
96db102a 1043wxSocketBase& wxSocketBase::Discard()
f4ada568 1044{
c2116a35
VZ
1045 char *buffer = new char[MAX_DISCARD_SIZE];
1046 wxUint32 ret;
1047 wxUint32 total = 0;
f4ada568 1048
c2116a35
VZ
1049 // Mask read events
1050 m_reading = true;
96db102a 1051
c2116a35 1052 SetFlags(wxSOCKET_NOWAIT);
384b4373 1053
c2116a35
VZ
1054 do
1055 {
cc0972a2 1056 ret = DoRead(buffer, MAX_DISCARD_SIZE);
c2116a35
VZ
1057 total += ret;
1058 }
1059 while (ret == MAX_DISCARD_SIZE);
f4ada568 1060
c2116a35
VZ
1061 delete[] buffer;
1062 m_lcount = total;
1063 m_error = false;
17aa2bec 1064
c2116a35
VZ
1065 // Allow read events again
1066 m_reading = false;
96db102a 1067
c2116a35 1068 return *this;
f4ada568
GL
1069}
1070
ef57d866
GRG
1071// --------------------------------------------------------------------------
1072// Wait functions
1073// --------------------------------------------------------------------------
f4ada568 1074
51fe4b60 1075/*
f0db5d75
VZ
1076 * Polls the socket to determine its status. This function will
1077 * check for the events specified in the 'flags' parameter, and
1078 * it will return a mask indicating which operations can be
1079 * performed. This function won't block, regardless of the
1080 * mode (blocking | nonblocking) of the socket.
1081 */
51fe4b60 1082wxSocketEventFlags wxSocketImpl::Select(wxSocketEventFlags flags)
f0db5d75
VZ
1083{
1084 assert(this);
1085
51fe4b60 1086 wxSocketEventFlags result = 0;
f0db5d75
VZ
1087 fd_set readfds;
1088 fd_set writefds;
1089 fd_set exceptfds;
1090 struct timeval tv;
1091
1092 if (m_fd == -1)
51fe4b60 1093 return (wxSOCKET_LOST_FLAG & flags);
f0db5d75
VZ
1094
1095 /* Do not use a static struct, Linux can garble it */
1096 tv.tv_sec = 0;
1097 tv.tv_usec = 0;
1098
1099 wxFD_ZERO(&readfds);
1100 wxFD_ZERO(&writefds);
1101 wxFD_ZERO(&exceptfds);
1102 wxFD_SET(m_fd, &readfds);
51fe4b60 1103 if (flags & wxSOCKET_OUTPUT_FLAG || flags & wxSOCKET_CONNECTION_FLAG)
f0db5d75
VZ
1104 wxFD_SET(m_fd, &writefds);
1105 wxFD_SET(m_fd, &exceptfds);
1106
1107 /* Check 'sticky' CONNECTION flag first */
51fe4b60 1108 result |= wxSOCKET_CONNECTION_FLAG & m_detected;
f0db5d75
VZ
1109
1110 /* If we have already detected a LOST event, then don't try
1111 * to do any further processing.
1112 */
51fe4b60 1113 if ((m_detected & wxSOCKET_LOST_FLAG) != 0)
f0db5d75
VZ
1114 {
1115 m_establishing = false;
51fe4b60 1116 return (wxSOCKET_LOST_FLAG & flags);
f0db5d75
VZ
1117 }
1118
1119 /* Try select now */
1120 if (select(m_fd + 1, &readfds, &writefds, &exceptfds, &tv) < 0)
1121 {
1122 /* What to do here? */
1123 return (result & flags);
1124 }
1125
1126 /* Check for exceptions and errors */
1127 if (wxFD_ISSET(m_fd, &exceptfds))
1128 {
1129 m_establishing = false;
51fe4b60 1130 m_detected = wxSOCKET_LOST_FLAG;
f0db5d75
VZ
1131
1132 /* LOST event: Abort any further processing */
51fe4b60 1133 return (wxSOCKET_LOST_FLAG & flags);
f0db5d75
VZ
1134 }
1135
1136 /* Check for readability */
1137 if (wxFD_ISSET(m_fd, &readfds))
1138 {
51fe4b60 1139 result |= wxSOCKET_INPUT_FLAG;
f0db5d75
VZ
1140
1141 if (m_server && m_stream)
1142 {
1143 /* This is a TCP server socket that detected a connection.
1144 While the INPUT_FLAG is also set, it doesn't matter on
1145 this kind of sockets, as we can only Accept() from them. */
51fe4b60 1146 m_detected |= wxSOCKET_CONNECTION_FLAG;
f0db5d75
VZ
1147 }
1148 }
1149
1150 /* Check for writability */
1151 if (wxFD_ISSET(m_fd, &writefds))
1152 {
1153 if (m_establishing && !m_server)
1154 {
1155 int error;
1156 SOCKOPTLEN_T len = sizeof(error);
1157 m_establishing = false;
1158 getsockopt(m_fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len);
1159
1160 if (error)
1161 {
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 else
1168 {
51fe4b60 1169 m_detected |= wxSOCKET_CONNECTION_FLAG;
f0db5d75
VZ
1170 }
1171 }
1172 else
1173 {
51fe4b60 1174 result |= wxSOCKET_OUTPUT_FLAG;
f0db5d75
VZ
1175 }
1176 }
1177
1178 return (result | m_detected) & flags;
1179}
1180
51fe4b60 1181// All Wait functions poll the socket using Select() to
ef57d866
GRG
1182// check for the specified combination of conditions, until one
1183// of these conditions become true, an error occurs, or the
b8d1915d 1184// timeout elapses. The polling loop runs the event loop so that
ef57d866 1185// this won't block the GUI.
f4ada568 1186
60ee0172
VZ
1187bool
1188wxSocketBase::DoWait(long seconds, long milliseconds, wxSocketEventFlags flags)
375abe3d 1189{
51fe4b60 1190 wxCHECK_MSG( m_impl, false, "can't wait on invalid socket" );
375abe3d 1191
60ee0172 1192 // This can be set to true from Interrupt() to exit this function a.s.a.p.
c2116a35 1193 m_interrupt = false;
81b92e17 1194
af2fd961 1195
60ee0172
VZ
1196 // Use either the provided timeout or the default timeout value associated
1197 // with this socket.
1198 //
1199 // TODO: allow waiting forever, see #9443
1200 const long timeout = seconds == -1 ? m_timeout * 1000
1201 : seconds * 1000 + milliseconds;
1202 const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
1203
1204 // Get the active event loop which we'll use for the message dispatching
1205 // when running in the main thread
1206 wxEventLoopBase *eventLoop;
1207 if ( wxIsMainThread() )
1208 {
1209 eventLoop = wxEventLoop::GetActive();
60ee0172
VZ
1210 }
1211 else // in worker thread
af2fd961 1212 {
60ee0172
VZ
1213 // We never dispatch messages from threads other than the main one.
1214 eventLoop = NULL;
af2fd961
GRG
1215 }
1216
60ee0172
VZ
1217 // Wait in an active polling loop: notice that the loop is executed at
1218 // least once, even if timeout is 0 (i.e. polling).
1219 bool gotEvent = false;
1220 for ( ;; )
af2fd961 1221 {
60ee0172 1222 // We always stop waiting when the connection is lost as it doesn't
51fe4b60 1223 // make sense to continue further, even if wxSOCKET_LOST_FLAG is not
60ee0172 1224 // specified in flags to wait for.
51fe4b60
VZ
1225 const wxSocketEventFlags
1226 result = m_impl->Select(flags | wxSOCKET_LOST_FLAG);
60ee0172
VZ
1227
1228 // Incoming connection (server) or connection established (client)?
51fe4b60 1229 if ( result & wxSOCKET_CONNECTION_FLAG )
c2116a35
VZ
1230 {
1231 m_connected = true;
1232 m_establishing = false;
60ee0172 1233 gotEvent = true;
c2116a35
VZ
1234 break;
1235 }
c0043a50 1236
60ee0172 1237 // Data available or output buffer ready?
51fe4b60 1238 if ( (result & wxSOCKET_INPUT_FLAG) || (result & wxSOCKET_OUTPUT_FLAG) )
b8d1915d 1239 {
60ee0172 1240 gotEvent = true;
c2116a35 1241 break;
b8d1915d 1242 }
c2116a35
VZ
1243
1244 // Connection lost
51fe4b60 1245 if ( result & wxSOCKET_LOST_FLAG )
c2116a35
VZ
1246 {
1247 m_connected = false;
1248 m_establishing = false;
51fe4b60 1249 if ( flags & wxSOCKET_LOST_FLAG )
60ee0172 1250 gotEvent = true;
c2116a35
VZ
1251 break;
1252 }
1253
60ee0172
VZ
1254 if ( m_interrupt )
1255 break;
1256
c2116a35 1257 // Wait more?
60ee0172
VZ
1258 const wxMilliClock_t timeNow = wxGetLocalTimeMillis();
1259 if ( timeNow >= timeEnd )
1260 break;
1261
1262 if ( eventLoop )
c2116a35 1263 {
f0db5d75
VZ
1264 // This function is only called if wxSOCKET_BLOCK flag was not used
1265 // and so we should dispatch the events if there is an event loop
1266 // capable of doing it.
60ee0172
VZ
1267 if ( eventLoop->Pending() )
1268 eventLoop->Dispatch();
1269 }
c2116a35 1270#if wxUSE_THREADS
60ee0172
VZ
1271 else // no event loop or waiting in another thread
1272 {
1273 // We're busy waiting but at least give up the rest of our current
1274 // time slice.
1275 wxThread::Yield();
c2116a35 1276 }
60ee0172 1277#endif // wxUSE_THREADS
f01bca89 1278 }
f4ada568 1279
60ee0172 1280 return gotEvent;
f4ada568 1281}
f4ada568 1282
a737331d 1283bool wxSocketBase::Wait(long seconds, long milliseconds)
f4ada568 1284{
60ee0172 1285 return DoWait(seconds, milliseconds,
51fe4b60
VZ
1286 wxSOCKET_INPUT_FLAG |
1287 wxSOCKET_OUTPUT_FLAG |
1288 wxSOCKET_CONNECTION_FLAG |
1289 wxSOCKET_LOST_FLAG
60ee0172 1290 );
f4ada568 1291}
f4ada568 1292
a737331d 1293bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
f4ada568 1294{
60ee0172
VZ
1295 // Check pushback buffer before entering DoWait
1296 if ( m_unread )
c2116a35 1297 return true;
96db102a 1298
51fe4b60 1299 // Note that wxSOCKET_INPUT_LOST has to be explicitly passed to DoWait
60ee0172 1300 // because of the semantics of WaitForRead: a return value of true means
51fe4b60 1301 // that a Read call will return immediately, not that there is
60ee0172 1302 // actually data to read.
51fe4b60 1303 return DoWait(seconds, milliseconds, wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
f4ada568
GL
1304}
1305
bfa7bf7d 1306
a737331d 1307bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
f4ada568 1308{
51fe4b60 1309 return DoWait(seconds, milliseconds, wxSOCKET_OUTPUT_FLAG | wxSOCKET_LOST_FLAG);
a737331d 1310}
f4ada568 1311
a737331d
GL
1312bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
1313{
51fe4b60 1314 return DoWait(seconds, milliseconds, wxSOCKET_LOST_FLAG);
f4ada568 1315}
a737331d 1316
ef57d866
GRG
1317// --------------------------------------------------------------------------
1318// Miscellaneous
1319// --------------------------------------------------------------------------
1320
1321//
1322// Get local or peer address
1323//
1324
1325bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
1326{
c2116a35 1327 GAddress *peer;
ef57d866 1328
51fe4b60 1329 if (!m_impl)
c2116a35 1330 return false;
ef57d866 1331
51fe4b60 1332 peer = m_impl->GetPeer();
007c77ab
RL
1333
1334 // copying a null address would just trigger an assert anyway
1335
c2116a35
VZ
1336 if (!peer)
1337 return false;
007c77ab 1338
c2116a35
VZ
1339 addr_man.SetAddress(peer);
1340 GAddress_destroy(peer);
ef57d866 1341
c2116a35 1342 return true;
ef57d866
GRG
1343}
1344
1345bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
1346{
7fb0a11d 1347 GAddress *local;
ef57d866 1348
51fe4b60 1349 if (!m_impl)
7fb0a11d 1350 return false;
ef57d866 1351
51fe4b60 1352 local = m_impl->GetLocal();
7fb0a11d
WS
1353 addr_man.SetAddress(local);
1354 GAddress_destroy(local);
ef57d866 1355
7fb0a11d 1356 return true;
ef57d866
GRG
1357}
1358
1359//
1360// Save and restore socket state
1361//
1362
1363void wxSocketBase::SaveState()
1364{
7fb0a11d 1365 wxSocketState *state;
ef57d866 1366
7fb0a11d 1367 state = new wxSocketState();
ef57d866 1368
7fb0a11d
WS
1369 state->m_flags = m_flags;
1370 state->m_notify = m_notify;
1371 state->m_eventmask = m_eventmask;
1372 state->m_clientData = m_clientData;
ef57d866 1373
7fb0a11d 1374 m_states.Append(state);
ef57d866
GRG
1375}
1376
1377void wxSocketBase::RestoreState()
1378{
7fb0a11d
WS
1379 wxList::compatibility_iterator node;
1380 wxSocketState *state;
ef57d866 1381
7fb0a11d
WS
1382 node = m_states.GetLast();
1383 if (!node)
1384 return;
ef57d866 1385
7fb0a11d 1386 state = (wxSocketState *)node->GetData();
ef57d866 1387
7fb0a11d
WS
1388 m_flags = state->m_flags;
1389 m_notify = state->m_notify;
1390 m_eventmask = state->m_eventmask;
1391 m_clientData = state->m_clientData;
37340c48 1392
7fb0a11d
WS
1393 m_states.Erase(node);
1394 delete state;
ef57d866
GRG
1395}
1396
1397//
1398// Timeout and flags
1399//
1400
17aa2bec
GRG
1401void wxSocketBase::SetTimeout(long seconds)
1402{
7fb0a11d 1403 m_timeout = seconds;
17aa2bec 1404
51fe4b60
VZ
1405 if (m_impl)
1406 m_impl->SetTimeout(m_timeout * 1000);
17aa2bec
GRG
1407}
1408
71622a7a 1409void wxSocketBase::SetFlags(wxSocketFlags flags)
f4ada568 1410{
cc0972a2
VZ
1411 // Do some sanity checking on the flags used: not all values can be used
1412 // together.
1413 wxASSERT_MSG( !(flags & wxSOCKET_NOWAIT) ||
1414 !(flags & (wxSOCKET_WAITALL | wxSOCKET_BLOCK)),
1415 "Using wxSOCKET_WAITALL or wxSOCKET_BLOCK with "
1416 "wxSOCKET_NOWAIT doesn't make sense" );
1417
7fb0a11d 1418 m_flags = flags;
f4ada568 1419}
f0a56ab0 1420
f187448d 1421
ef57d866 1422// --------------------------------------------------------------------------
f187448d 1423// Event handling
ef57d866 1424// --------------------------------------------------------------------------
a324a7bc 1425
bffc1eaa 1426void wxSocketBase::OnRequest(wxSocketNotify notification)
f4ada568 1427{
c2116a35 1428 switch(notification)
bffc1eaa 1429 {
c2116a35
VZ
1430 case wxSOCKET_CONNECTION:
1431 m_establishing = false;
1432 m_connected = true;
1433 break;
1434
1435 // If we are in the middle of a R/W operation, do not
1436 // propagate events to users. Also, filter 'late' events
1437 // which are no longer valid.
1438
1439 case wxSOCKET_INPUT:
51fe4b60 1440 if (m_reading || !m_impl->Select(wxSOCKET_INPUT_FLAG))
c2116a35
VZ
1441 return;
1442 break;
1443
1444 case wxSOCKET_OUTPUT:
51fe4b60 1445 if (m_writing || !m_impl->Select(wxSOCKET_OUTPUT_FLAG))
c2116a35
VZ
1446 return;
1447 break;
1448
1449 case wxSOCKET_LOST:
1450 m_connected = false;
1451 m_establishing = false;
1452 break;
51fe4b60
VZ
1453
1454 case wxSOCKET_MAX_EVENT:
1455 wxFAIL_MSG( "unexpected notification" );
1456 return;
c2116a35
VZ
1457 }
1458
1459 // Schedule the event
bffc1eaa 1460
c2116a35
VZ
1461 wxSocketEventFlags flag = 0;
1462 wxUnusedVar(flag);
1463 switch (notification)
1464 {
51fe4b60
VZ
1465 case wxSOCKET_INPUT: flag = wxSOCKET_INPUT_FLAG; break;
1466 case wxSOCKET_OUTPUT: flag = wxSOCKET_OUTPUT_FLAG; break;
1467 case wxSOCKET_CONNECTION: flag = wxSOCKET_CONNECTION_FLAG; break;
1468 case wxSOCKET_LOST: flag = wxSOCKET_LOST_FLAG; break;
c2116a35
VZ
1469 default:
1470 wxLogWarning(_("wxSocket: unknown event!."));
1471 return;
1472 }
1473
1474 if (((m_eventmask & flag) == flag) && m_notify)
1475 {
1476 if (m_handler)
1477 {
1478 wxSocketEvent event(m_id);
1479 event.m_event = notification;
1480 event.m_clientData = m_clientData;
1481 event.SetEventObject(this);
1482
1483 m_handler->AddPendingEvent(event);
1484 }
bffc1eaa 1485 }
f4ada568
GL
1486}
1487
f187448d
GRG
1488void wxSocketBase::Notify(bool notify)
1489{
7fb0a11d 1490 m_notify = notify;
51fe4b60
VZ
1491 if (m_impl)
1492 m_impl->Notify(notify);
f187448d
GRG
1493}
1494
1495void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1496{
7fb0a11d 1497 m_eventmask = flags;
f187448d
GRG
1498}
1499
71622a7a 1500void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
f4ada568 1501{
7fb0a11d
WS
1502 m_handler = &handler;
1503 m_id = id;
f4ada568
GL
1504}
1505
ef57d866
GRG
1506// --------------------------------------------------------------------------
1507// Pushback buffer
1508// --------------------------------------------------------------------------
db131261 1509
f187448d 1510void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
f4ada568 1511{
c2116a35 1512 if (!size) return;
dc5c1114 1513
c2116a35
VZ
1514 if (m_unread == NULL)
1515 m_unread = malloc(size);
1516 else
1517 {
1518 void *tmp;
f4ada568 1519
c2116a35
VZ
1520 tmp = malloc(m_unrd_size + size);
1521 memcpy((char *)tmp + size, m_unread, m_unrd_size);
1522 free(m_unread);
a324a7bc 1523
c2116a35
VZ
1524 m_unread = tmp;
1525 }
31528cd3 1526
c2116a35 1527 m_unrd_size += size;
a324a7bc 1528
c2116a35 1529 memcpy(m_unread, buffer, size);
f4ada568
GL
1530}
1531
f187448d 1532wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
f4ada568 1533{
cc0972a2
VZ
1534 wxCHECK_MSG( buffer, 0, "NULL buffer" );
1535
c2116a35
VZ
1536 if (!m_unrd_size)
1537 return 0;
f4ada568 1538
c2116a35
VZ
1539 if (size > (m_unrd_size-m_unrd_cur))
1540 size = m_unrd_size-m_unrd_cur;
96db102a 1541
c2116a35 1542 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
f4ada568 1543
c2116a35 1544 if (!peek)
dc5c1114 1545 {
c2116a35
VZ
1546 m_unrd_cur += size;
1547 if (m_unrd_size == m_unrd_cur)
1548 {
1549 free(m_unread);
1550 m_unread = NULL;
1551 m_unrd_size = 0;
1552 m_unrd_cur = 0;
1553 }
f4ada568 1554 }
f4ada568 1555
c2116a35 1556 return size;
f4ada568
GL
1557}
1558
f187448d 1559
ef57d866 1560// ==========================================================================
c3e646b4 1561// wxSocketServer
ef57d866 1562// ==========================================================================
f4ada568 1563
ef57d866
GRG
1564// --------------------------------------------------------------------------
1565// Ctor
1566// --------------------------------------------------------------------------
56d8adc0 1567
fbfb8bcc 1568wxSocketServer::wxSocketServer(const wxSockAddress& addr_man,
71622a7a
GRG
1569 wxSocketFlags flags)
1570 : wxSocketBase(flags, wxSOCKET_SERVER)
f4ada568 1571{
007c77ab 1572 wxLogTrace( wxTRACE_Socket, _T("Opening wxSocketServer") );
f4ada568 1573
51fe4b60 1574 m_impl = wxSocketImpl::Create(*this);
384b4373 1575
51fe4b60 1576 if (!m_impl)
007c77ab 1577 {
51fe4b60 1578 wxLogTrace( wxTRACE_Socket, _T("*** Failed to create m_impl") );
007c77ab
RL
1579 return;
1580 }
a737331d 1581
2804f77d 1582 // Setup the socket as server
51fe4b60
VZ
1583 m_impl->Notify(m_notify);
1584 m_impl->SetLocal(addr_man.GetAddress());
d775fa82 1585
74c481d1 1586 if (GetFlags() & wxSOCKET_REUSEADDR) {
51fe4b60 1587 m_impl->SetReusable();
74c481d1 1588 }
60edcf45 1589 if (GetFlags() & wxSOCKET_BROADCAST) {
51fe4b60 1590 m_impl->SetBroadcast();
60edcf45
VZ
1591 }
1592 if (GetFlags() & wxSOCKET_NOBIND) {
51fe4b60 1593 m_impl->DontDoBind();
60edcf45 1594 }
74c481d1 1595
51fe4b60 1596 if (m_impl->CreateServer() != wxSOCKET_NOERROR)
007c77ab 1597 {
51fe4b60
VZ
1598 delete m_impl;
1599 m_impl = NULL;
007c77ab 1600
51fe4b60 1601 wxLogTrace( wxTRACE_Socket, _T("*** CreateServer() failed") );
007c77ab
RL
1602 return;
1603 }
1604
51fe4b60 1605 wxLogTrace( wxTRACE_Socket, _T("wxSocketServer on fd %d"), m_impl->m_fd );
f4ada568
GL
1606}
1607
ef57d866
GRG
1608// --------------------------------------------------------------------------
1609// Accept
1610// --------------------------------------------------------------------------
8c14576d 1611
d80d1aba 1612bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
f4ada568 1613{
51fe4b60 1614 if (!m_impl)
c2116a35 1615 return false;
17aa2bec 1616
c2116a35
VZ
1617 // If wait == false, then the call should be nonblocking.
1618 // When we are finished, we put the socket to blocking mode
1619 // again.
51fe4b60
VZ
1620 wxSocketUnblocker unblock(m_impl, !wait);
1621 sock.m_impl = m_impl->WaitConnection(sock);
d80d1aba 1622
51fe4b60 1623 if ( !sock.m_impl )
c2116a35 1624 return false;
d80d1aba 1625
c2116a35 1626 sock.m_type = wxSOCKET_BASE;
c2116a35 1627 sock.m_connected = true;
f4ada568 1628
c2116a35 1629 return true;
f4ada568
GL
1630}
1631
d80d1aba 1632wxSocketBase *wxSocketServer::Accept(bool wait)
f4ada568 1633{
c2116a35 1634 wxSocketBase* sock = new wxSocketBase();
f4ada568 1635
c2116a35 1636 sock->SetFlags(m_flags);
f4ada568 1637
c2116a35
VZ
1638 if (!AcceptWith(*sock, wait))
1639 {
1640 sock->Destroy();
1641 sock = NULL;
1642 }
f4ada568 1643
c2116a35 1644 return sock;
f4ada568
GL
1645}
1646
17aa2bec 1647bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
d80d1aba 1648{
51fe4b60 1649 return DoWait(seconds, milliseconds, wxSOCKET_CONNECTION_FLAG);
d80d1aba
GRG
1650}
1651
bfa7bf7d
VZ
1652bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1653{
51fe4b60 1654 wxASSERT_MSG( m_impl, _T("Socket not initialised") );
11734f8a 1655
51fe4b60
VZ
1656 SOCKOPTLEN_T lenreal;
1657 if ( getsockopt(m_impl->m_fd, level, optname,
1658 static_cast<char *>(optval), &lenreal) != 0 )
d775fa82 1659 return false;
51fe4b60
VZ
1660
1661 *optlen = lenreal;
1662
d775fa82 1663 return true;
bfa7bf7d
VZ
1664}
1665
51fe4b60
VZ
1666bool
1667wxSocketBase::SetOption(int level, int optname, const void *optval, int optlen)
bfa7bf7d 1668{
51fe4b60 1669 wxASSERT_MSG( m_impl, _T("Socket not initialised") );
8e3f3880 1670
51fe4b60
VZ
1671 return setsockopt(m_impl->m_fd, level, optname,
1672 static_cast<const char *>(optval), optlen) == 0;
bfa7bf7d
VZ
1673}
1674
72ac4e88 1675bool wxSocketBase::SetLocal(const wxIPV4address& local)
33d925b0 1676{
c2116a35 1677 GAddress* la = local.GetAddress();
33d925b0 1678
c2116a35
VZ
1679 // If the address is valid, save it for use when we call Connect
1680 if (la && la->m_addr)
1681 {
1682 m_localAddress = local;
33d925b0 1683
c2116a35
VZ
1684 return true;
1685 }
33d925b0 1686
c2116a35 1687 return false;
33d925b0
KH
1688}
1689
ef57d866 1690// ==========================================================================
8c14576d 1691// wxSocketClient
ef57d866 1692// ==========================================================================
f4ada568 1693
ef57d866
GRG
1694// --------------------------------------------------------------------------
1695// Ctor and dtor
1696// --------------------------------------------------------------------------
56d8adc0 1697
71622a7a
GRG
1698wxSocketClient::wxSocketClient(wxSocketFlags flags)
1699 : wxSocketBase(flags, wxSOCKET_CLIENT)
f4ada568 1700{
089b23d0
VZ
1701 m_initialRecvBufferSize =
1702 m_initialSendBufferSize = -1;
f4ada568
GL
1703}
1704
f4ada568
GL
1705wxSocketClient::~wxSocketClient()
1706{
1707}
1708
ef57d866
GRG
1709// --------------------------------------------------------------------------
1710// Connect
1711// --------------------------------------------------------------------------
dc5c1114 1712
72ac4e88
VZ
1713bool wxSocketClient::DoConnect(const wxSockAddress& addr_man,
1714 const wxSockAddress* local,
1715 bool wait)
f4ada568 1716{
51fe4b60 1717 if (m_impl)
c2116a35
VZ
1718 {
1719 // Shutdown and destroy the socket
1720 Close();
51fe4b60 1721 delete m_impl;
c2116a35 1722 }
a324a7bc 1723
51fe4b60 1724 m_impl = wxSocketImpl::Create(*this);
c2116a35
VZ
1725 m_connected = false;
1726 m_establishing = false;
384b4373 1727
51fe4b60 1728 if (!m_impl)
c2116a35 1729 return false;
384b4373 1730
c2116a35
VZ
1731 // If wait == false, then the call should be nonblocking. When we are
1732 // finished, we put the socket to blocking mode again.
51fe4b60 1733 wxSocketUnblocker unblock(m_impl, !wait);
c2116a35
VZ
1734
1735 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1736 if (GetFlags() & wxSOCKET_REUSEADDR)
1737 {
51fe4b60 1738 m_impl->SetReusable();
c2116a35
VZ
1739 }
1740 if (GetFlags() & wxSOCKET_BROADCAST)
1741 {
51fe4b60 1742 m_impl->SetBroadcast();
c2116a35
VZ
1743 }
1744 if (GetFlags() & wxSOCKET_NOBIND)
1745 {
51fe4b60 1746 m_impl->DontDoBind();
c2116a35 1747 }
33d925b0 1748
c2116a35
VZ
1749 // If no local address was passed and one has been set, use the one that was Set
1750 if (!local && m_localAddress.GetAddress())
1751 {
1752 local = &m_localAddress;
1753 }
1754
1755 // Bind to the local IP address and port, when provided
1756 if (local)
1757 {
1758 GAddress* la = local->GetAddress();
1759
1760 if (la && la->m_addr)
51fe4b60 1761 m_impl->SetLocal(la);
c2116a35 1762 }
33d925b0 1763
51fe4b60 1764 m_impl->SetInitialSocketBuffers(m_initialRecvBufferSize, m_initialSendBufferSize);
8c029a5b 1765
51fe4b60
VZ
1766 m_impl->SetPeer(addr_man.GetAddress());
1767 const wxSocketError err = m_impl->CreateClient();
791b24c4 1768
51fe4b60
VZ
1769 //this will register for callbacks - must be called after m_impl->m_fd was initialized
1770 m_impl->Notify(m_notify);
2804f77d 1771
51fe4b60 1772 if (err != wxSOCKET_NOERROR)
c2116a35 1773 {
51fe4b60 1774 if (err == wxSOCKET_WOULDBLOCK)
c2116a35 1775 m_establishing = true;
56d8adc0 1776
c2116a35
VZ
1777 return false;
1778 }
9111db68 1779
c2116a35
VZ
1780 m_connected = true;
1781 return true;
f4ada568
GL
1782}
1783
72ac4e88 1784bool wxSocketClient::Connect(const wxSockAddress& addr_man, bool wait)
33d925b0 1785{
72ac4e88 1786 return DoConnect(addr_man, NULL, wait);
33d925b0
KH
1787}
1788
72ac4e88
VZ
1789bool wxSocketClient::Connect(const wxSockAddress& addr_man,
1790 const wxSockAddress& local,
1791 bool wait)
33d925b0 1792{
72ac4e88 1793 return DoConnect(addr_man, &local, wait);
33d925b0
KH
1794}
1795
d80d1aba 1796bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
f4ada568 1797{
60ee0172
VZ
1798 if ( m_connected )
1799 {
1800 // this happens if the initial attempt to connect succeeded without
1801 // blocking
7fb0a11d 1802 return true;
60ee0172 1803 }
d80d1aba 1804
51fe4b60 1805 wxCHECK_MSG( m_establishing && m_impl, false,
60ee0172 1806 "No connection establishment attempt in progress" );
d80d1aba 1807
51fe4b60 1808 // we must specify wxSOCKET_LOST_FLAG here explicitly because we must return
60ee0172
VZ
1809 // true if the connection establishment process is finished, whether it is
1810 // over because we successfully connected or because we were not able to
1811 // connect
1812 return DoWait(seconds, milliseconds,
51fe4b60 1813 wxSOCKET_CONNECTION_FLAG | wxSOCKET_LOST_FLAG);
f4ada568
GL
1814}
1815
ef57d866 1816// ==========================================================================
dc5c1114 1817// wxDatagramSocket
ef57d866 1818// ==========================================================================
dc5c1114 1819
fbfb8bcc 1820wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
71622a7a
GRG
1821 wxSocketFlags flags )
1822 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
dc5c1114 1823{
7fb0a11d 1824 // Create the socket
51fe4b60 1825 m_impl = wxSocketImpl::Create(*this);
dc5c1114 1826
51fe4b60 1827 if (!m_impl)
7fb0a11d 1828 return;
53a161e1 1829
51fe4b60 1830 m_impl->Notify(m_notify);
7fb0a11d 1831 // Setup the socket as non connection oriented
51fe4b60 1832 m_impl->SetLocal(addr.GetAddress());
28bf2f3c
VZ
1833 if (flags & wxSOCKET_REUSEADDR)
1834 {
51fe4b60 1835 m_impl->SetReusable();
28bf2f3c 1836 }
60edcf45
VZ
1837 if (GetFlags() & wxSOCKET_BROADCAST)
1838 {
51fe4b60 1839 m_impl->SetBroadcast();
60edcf45
VZ
1840 }
1841 if (GetFlags() & wxSOCKET_NOBIND)
1842 {
51fe4b60 1843 m_impl->DontDoBind();
60edcf45 1844 }
51fe4b60
VZ
1845
1846 if ( m_impl->CreateUDP() != wxSOCKET_NOERROR )
7fb0a11d 1847 {
51fe4b60
VZ
1848 delete m_impl;
1849 m_impl = NULL;
7fb0a11d
WS
1850 return;
1851 }
dc5c1114 1852
7fb0a11d
WS
1853 // Initialize all stuff
1854 m_connected = false;
1855 m_establishing = false;
dc5c1114
GRG
1856}
1857
1858wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
f187448d 1859 void* buf,
dc5c1114
GRG
1860 wxUint32 nBytes )
1861{
1862 Read(buf, nBytes);
1863 GetPeer(addr);
1864 return (*this);
1865}
1866
fbfb8bcc 1867wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
f187448d 1868 const void* buf,
dc5c1114
GRG
1869 wxUint32 nBytes )
1870{
51fe4b60 1871 wxASSERT_MSG( m_impl, _T("Socket not initialised") );
8e3f3880 1872
51fe4b60 1873 m_impl->SetPeer(addr.GetAddress());
dc5c1114
GRG
1874 Write(buf, nBytes);
1875 return (*this);
1876}
1877
ef57d866 1878// ==========================================================================
a58d5df4 1879// wxSocketModule
ef57d866 1880// ==========================================================================
dc5c1114 1881
ed4c6c69 1882class wxSocketModule : public wxModule
dc5c1114 1883{
dc5c1114 1884public:
6c0d0845
VZ
1885 virtual bool OnInit()
1886 {
51fe4b60
VZ
1887 // wxSocketBase will call Initialize() itself only if sockets are
1888 // really used, don't do it from here
d775fa82 1889 return true;
6c0d0845
VZ
1890 }
1891
1892 virtual void OnExit()
1893 {
1894 if ( wxSocketBase::IsInitialized() )
1895 wxSocketBase::Shutdown();
1896 }
1897
1898private:
1899 DECLARE_DYNAMIC_CLASS(wxSocketModule)
a58d5df4
GL
1900};
1901
1902IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1903
c2116a35 1904#endif // wxUSE_SOCKETS