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