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