]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/socket.cpp
[ 1473731 ] 'wxColourBase and wxString <-> wxColour implementation'
[wxWidgets.git] / src / common / socket.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/socket.cpp
3// Purpose: Socket handler classes
4// Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
5// Created: April 1997
6// Copyright: (C) 1999-1997, Guilhem Lavaux
7// (C) 2000-1999, Guillermo Rodriguez Garcia
8// RCS_ID: $Id$
9// License: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ==========================================================================
13// Declarations
14// ==========================================================================
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
23#if wxUSE_SOCKETS
24
25#include "wx/socket.h"
26
27#ifndef WX_PRECOMP
28 #include "wx/object.h"
29 #include "wx/string.h"
30#endif
31
32#include "wx/app.h"
33#include "wx/apptrait.h"
34#include "wx/timer.h"
35#include "wx/utils.h"
36#include "wx/module.h"
37#include "wx/log.h"
38#include "wx/intl.h"
39#include "wx/event.h"
40
41#include "wx/sckaddr.h"
42#include "wx/datetime.h"
43
44// DLL options compatibility check:
45#include "wx/build.h"
46WX_CHECK_BUILD_OPTIONS("wxNet")
47
48// --------------------------------------------------------------------------
49// macros and constants
50// --------------------------------------------------------------------------
51
52// discard buffer
53#define MAX_DISCARD_SIZE (10 * 1024)
54
55// what to do within waits: we have 2 cases: from the main thread itself we
56// have to call wxYield() to let the events (including the GUI events and the
57// low-level (not wxWidgets) events from GSocket) be processed. From another
58// thread it is enough to just call wxThread::Yield() which will give away the
59// rest of our time slice: the explanation is that the events will be processed
60// by the main thread anyhow, without calling wxYield(), but we don't want to
61// eat the CPU time uselessly while sitting in the loop waiting for the data
62#if wxUSE_THREADS
63 #define PROCESS_EVENTS() \
64 { \
65 if ( wxThread::IsMain() ) \
66 wxYield(); \
67 else \
68 wxThread::Yield(); \
69 }
70#else // !wxUSE_THREADS
71 #define PROCESS_EVENTS() wxYield()
72#endif // wxUSE_THREADS/!wxUSE_THREADS
73
74#define wxTRACE_Socket _T("wxSocket")
75
76// --------------------------------------------------------------------------
77// wxWin macros
78// --------------------------------------------------------------------------
79
80IMPLEMENT_CLASS(wxSocketBase, wxObject)
81IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
82IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
83IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
84IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
85
86// --------------------------------------------------------------------------
87// private classes
88// --------------------------------------------------------------------------
89
90class wxSocketState : public wxObject
91{
92public:
93 wxSocketFlags m_flags;
94 wxSocketEventFlags m_eventmask;
95 bool m_notify;
96 void *m_clientData;
97
98public:
99 wxSocketState() : wxObject() {}
100
101 DECLARE_NO_COPY_CLASS(wxSocketState)
102};
103
104// ==========================================================================
105// wxSocketBase
106// ==========================================================================
107
108// --------------------------------------------------------------------------
109// Initialization and shutdown
110// --------------------------------------------------------------------------
111
112// FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
113// to m_countInit with a crit section
114size_t wxSocketBase::m_countInit = 0;
115
116bool wxSocketBase::IsInitialized()
117{
118 return m_countInit > 0;
119}
120
121bool wxSocketBase::Initialize()
122{
123 if ( !m_countInit++ )
124 {
125 /*
126 Details: Initialize() creates a hidden window as a sink for socket
127 events, such as 'read completed'. wxMSW has only one message loop
128 for the main thread. If Initialize is called in a secondary thread,
129 the socket window will be created for the secondary thread, but
130 since there is no message loop on this thread, it will never
131 receive events and all socket operations will time out.
132 BTW, the main thread must not be stopped using sleep or block
133 on a semaphore (a bad idea in any case) or socket operations
134 will time out.
135
136 On the Mac side, Initialize() stores a pointer to the CFRunLoop for
137 the main thread. Because secondary threads do not have run loops,
138 adding event notifications to the "Current" loop would have no
139 effect at all, events would never fire.
140 */
141 wxASSERT_MSG( wxIsMainThread(),
142 wxT("Call wxSocketBase::Initialize() from the main thread first!"));
143
144 wxAppTraits *traits = wxAppConsole::GetInstance() ?
145 wxAppConsole::GetInstance()->GetTraits() : NULL;
146 GSocketGUIFunctionsTable *functions =
147 traits ? traits->GetSocketGUIFunctionsTable() : NULL;
148 GSocket_SetGUIFunctions(functions);
149
150 if ( !GSocket_Init() )
151 {
152 m_countInit--;
153
154 return false;
155 }
156 }
157
158 return true;
159}
160
161void wxSocketBase::Shutdown()
162{
163 // we should be initialized
164 wxASSERT_MSG( m_countInit, _T("extra call to Shutdown()") );
165 if ( --m_countInit == 0 )
166 {
167 GSocket_Cleanup();
168 }
169}
170
171// --------------------------------------------------------------------------
172// Ctor and dtor
173// --------------------------------------------------------------------------
174
175void wxSocketBase::Init()
176{
177 m_socket = NULL;
178 m_type = wxSOCKET_UNINIT;
179
180 // state
181 m_flags = 0;
182 m_connected =
183 m_establishing =
184 m_reading =
185 m_writing =
186 m_error = false;
187 m_lcount = 0;
188 m_timeout = 600;
189 m_beingDeleted = false;
190
191 // pushback buffer
192 m_unread = NULL;
193 m_unrd_size = 0;
194 m_unrd_cur = 0;
195
196 // events
197 m_id = wxID_ANY;
198 m_handler = NULL;
199 m_clientData = NULL;
200 m_notify = false;
201 m_eventmask = 0;
202
203 if ( !IsInitialized() )
204 {
205 // this Initialize() will be undone by wxSocketModule::OnExit(), all the
206 // other calls to it should be matched by a call to Shutdown()
207 Initialize();
208 }
209}
210
211wxSocketBase::wxSocketBase()
212{
213 Init();
214}
215
216wxSocketBase::wxSocketBase(wxSocketFlags flags, wxSocketType type)
217{
218 Init();
219
220 m_flags = flags;
221 m_type = type;
222}
223
224wxSocketBase::~wxSocketBase()
225{
226 // Just in case the app called Destroy() *and* then deleted
227 // the socket immediately: don't leave dangling pointers.
228 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
229 if ( traits )
230 traits->RemoveFromPendingDelete(this);
231
232 // Shutdown and close the socket
233 if (!m_beingDeleted)
234 Close();
235
236 // Destroy the GSocket object
237 if (m_socket)
238 delete m_socket;
239
240 // Free the pushback buffer
241 if (m_unread)
242 free(m_unread);
243}
244
245bool wxSocketBase::Destroy()
246{
247 // Delayed destruction: the socket will be deleted during the next
248 // idle loop iteration. This ensures that all pending events have
249 // been processed.
250 m_beingDeleted = true;
251
252 // Shutdown and close the socket
253 Close();
254
255 // Supress events from now on
256 Notify(false);
257
258 // schedule this object for deletion
259 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
260 if ( traits )
261 {
262 // let the traits object decide what to do with us
263 traits->ScheduleForDestroy(this);
264 }
265 else // no app or no traits
266 {
267 // in wxBase we might have no app object at all, don't leak memory
268 delete this;
269 }
270
271 return true;
272}
273
274// --------------------------------------------------------------------------
275// Basic IO calls
276// --------------------------------------------------------------------------
277
278// The following IO operations update m_error and m_lcount:
279// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
280//
281// TODO: Should Connect, Accept and AcceptWith update m_error?
282
283bool wxSocketBase::Close()
284{
285 // Interrupt pending waits
286 InterruptWait();
287
288 if (m_socket)
289 {
290 // Disable callbacks
291 m_socket->UnsetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
292 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
293
294 // Shutdown the connection
295 m_socket->Shutdown();
296 }
297
298 m_connected = false;
299 m_establishing = false;
300 return true;
301}
302
303wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
304{
305 // Mask read events
306 m_reading = true;
307
308 m_lcount = _Read(buffer, nbytes);
309
310 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
311 if (m_flags & wxSOCKET_WAITALL)
312 m_error = (m_lcount != nbytes);
313 else
314 m_error = (m_lcount == 0);
315
316 // Allow read events from now on
317 m_reading = false;
318
319 return *this;
320}
321
322wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
323{
324 int total;
325
326 // Try the pushback buffer first
327 total = GetPushback(buffer, nbytes, false);
328 nbytes -= total;
329 buffer = (char *)buffer + total;
330
331 // Return now in one of the following cases:
332 // - the socket is invalid,
333 // - we got all the data,
334 // - we got *some* data and we are not using wxSOCKET_WAITALL.
335 if ( !m_socket ||
336 !nbytes ||
337 ((total != 0) && !(m_flags & wxSOCKET_WAITALL)) )
338 return total;
339
340 // Possible combinations (they are checked in this order)
341 // wxSOCKET_NOWAIT
342 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
343 // wxSOCKET_BLOCK
344 // wxSOCKET_NONE
345 //
346 int ret;
347 if (m_flags & wxSOCKET_NOWAIT)
348 {
349 m_socket->SetNonBlocking(1);
350 ret = m_socket->Read((char *)buffer, nbytes);
351 m_socket->SetNonBlocking(0);
352
353 if (ret > 0)
354 total += ret;
355 }
356 else
357 {
358 bool more = true;
359
360 while (more)
361 {
362 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
363 break;
364
365 ret = m_socket->Read((char *)buffer, nbytes);
366
367 if (ret > 0)
368 {
369 total += ret;
370 nbytes -= ret;
371 buffer = (char *)buffer + ret;
372 }
373
374 // If we got here and wxSOCKET_WAITALL is not set, we can leave
375 // now. Otherwise, wait until we recv all the data or until there
376 // is an error.
377 //
378 more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
379 }
380 }
381
382 return total;
383}
384
385wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
386{
387 wxUint32 len, len2, sig, total;
388 bool error;
389 int old_flags;
390 struct
391 {
392 unsigned char sig[4];
393 unsigned char len[4];
394 } msg;
395
396 // Mask read events
397 m_reading = true;
398
399 total = 0;
400 error = true;
401 old_flags = m_flags;
402 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
403
404 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
405 goto exit;
406
407 sig = (wxUint32)msg.sig[0];
408 sig |= (wxUint32)(msg.sig[1] << 8);
409 sig |= (wxUint32)(msg.sig[2] << 16);
410 sig |= (wxUint32)(msg.sig[3] << 24);
411
412 if (sig != 0xfeeddead)
413 {
414 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
415 goto exit;
416 }
417
418 len = (wxUint32)msg.len[0];
419 len |= (wxUint32)(msg.len[1] << 8);
420 len |= (wxUint32)(msg.len[2] << 16);
421 len |= (wxUint32)(msg.len[3] << 24);
422
423 if (len > nbytes)
424 {
425 len2 = len - nbytes;
426 len = nbytes;
427 }
428 else
429 len2 = 0;
430
431 // Don't attemp to read if the msg was zero bytes long.
432 if (len)
433 {
434 total = _Read(buffer, len);
435
436 if (total != len)
437 goto exit;
438 }
439 if (len2)
440 {
441 char *discard_buffer = new char[MAX_DISCARD_SIZE];
442 long discard_len;
443
444 // NOTE: discarded bytes don't add to m_lcount.
445 do
446 {
447 discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
448 discard_len = _Read(discard_buffer, (wxUint32)discard_len);
449 len2 -= (wxUint32)discard_len;
450 }
451 while ((discard_len > 0) && len2);
452
453 delete [] discard_buffer;
454
455 if (len2 != 0)
456 goto exit;
457 }
458 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
459 goto exit;
460
461 sig = (wxUint32)msg.sig[0];
462 sig |= (wxUint32)(msg.sig[1] << 8);
463 sig |= (wxUint32)(msg.sig[2] << 16);
464 sig |= (wxUint32)(msg.sig[3] << 24);
465
466 if (sig != 0xdeadfeed)
467 {
468 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
469 goto exit;
470 }
471
472 // everything was OK
473 error = false;
474
475exit:
476 m_error = error;
477 m_lcount = total;
478 m_reading = false;
479 SetFlags(old_flags);
480
481 return *this;
482}
483
484wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
485{
486 // Mask read events
487 m_reading = true;
488
489 m_lcount = _Read(buffer, nbytes);
490 Pushback(buffer, m_lcount);
491
492 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
493 if (m_flags & wxSOCKET_WAITALL)
494 m_error = (m_lcount != nbytes);
495 else
496 m_error = (m_lcount == 0);
497
498 // Allow read events again
499 m_reading = false;
500
501 return *this;
502}
503
504wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
505{
506 // Mask write events
507 m_writing = true;
508
509 m_lcount = _Write(buffer, nbytes);
510
511 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
512 if (m_flags & wxSOCKET_WAITALL)
513 m_error = (m_lcount != nbytes);
514 else
515 m_error = (m_lcount == 0);
516
517 // Allow write events again
518 m_writing = false;
519
520 return *this;
521}
522
523wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
524{
525 wxUint32 total = 0;
526
527 // If the socket is invalid or parameters are ill, return immediately
528 if (!m_socket || !buffer || !nbytes)
529 return 0;
530
531 // Possible combinations (they are checked in this order)
532 // wxSOCKET_NOWAIT
533 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
534 // wxSOCKET_BLOCK
535 // wxSOCKET_NONE
536 //
537 int ret;
538 if (m_flags & wxSOCKET_NOWAIT)
539 {
540 m_socket->SetNonBlocking(1);
541 ret = m_socket->Write((const char *)buffer, nbytes);
542 m_socket->SetNonBlocking(0);
543
544 if (ret > 0)
545 total = ret;
546 }
547 else
548 {
549 bool more = true;
550
551 while (more)
552 {
553 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
554 break;
555
556 ret = m_socket->Write((const char *)buffer, nbytes);
557
558 if (ret > 0)
559 {
560 total += ret;
561 nbytes -= ret;
562 buffer = (const char *)buffer + ret;
563 }
564
565 // If we got here and wxSOCKET_WAITALL is not set, we can leave
566 // now. Otherwise, wait until we send all the data or until there
567 // is an error.
568 //
569 more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
570 }
571 }
572
573 return total;
574}
575
576wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
577{
578 wxUint32 total;
579 bool error;
580 struct
581 {
582 unsigned char sig[4];
583 unsigned char len[4];
584 } msg;
585
586 // Mask write events
587 m_writing = true;
588
589 error = true;
590 total = 0;
591 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
592
593 msg.sig[0] = (unsigned char) 0xad;
594 msg.sig[1] = (unsigned char) 0xde;
595 msg.sig[2] = (unsigned char) 0xed;
596 msg.sig[3] = (unsigned char) 0xfe;
597
598 msg.len[0] = (unsigned char) (nbytes & 0xff);
599 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
600 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
601 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
602
603 if (_Write(&msg, sizeof(msg)) < sizeof(msg))
604 goto exit;
605
606 total = _Write(buffer, nbytes);
607
608 if (total < nbytes)
609 goto exit;
610
611 msg.sig[0] = (unsigned char) 0xed;
612 msg.sig[1] = (unsigned char) 0xfe;
613 msg.sig[2] = (unsigned char) 0xad;
614 msg.sig[3] = (unsigned char) 0xde;
615 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
616
617 if ((_Write(&msg, sizeof(msg))) < sizeof(msg))
618 goto exit;
619
620 // everything was OK
621 error = false;
622
623exit:
624 m_error = error;
625 m_lcount = total;
626 m_writing = false;
627
628 return *this;
629}
630
631wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
632{
633 if (nbytes != 0)
634 Pushback(buffer, nbytes);
635
636 m_error = false;
637 m_lcount = nbytes;
638
639 return *this;
640}
641
642wxSocketBase& wxSocketBase::Discard()
643{
644 char *buffer = new char[MAX_DISCARD_SIZE];
645 wxUint32 ret;
646 wxUint32 total = 0;
647
648 // Mask read events
649 m_reading = true;
650
651 SetFlags(wxSOCKET_NOWAIT);
652
653 do
654 {
655 ret = _Read(buffer, MAX_DISCARD_SIZE);
656 total += ret;
657 }
658 while (ret == MAX_DISCARD_SIZE);
659
660 delete[] buffer;
661 m_lcount = total;
662 m_error = false;
663
664 // Allow read events again
665 m_reading = false;
666
667 return *this;
668}
669
670// --------------------------------------------------------------------------
671// Wait functions
672// --------------------------------------------------------------------------
673
674// All Wait functions poll the socket using GSocket_Select() to
675// check for the specified combination of conditions, until one
676// of these conditions become true, an error occurs, or the
677// timeout elapses. The polling loop calls PROCESS_EVENTS(), so
678// this won't block the GUI.
679
680bool wxSocketBase::_Wait(long seconds,
681 long milliseconds,
682 wxSocketEventFlags flags)
683{
684 GSocketEventFlags result;
685 long timeout;
686
687 // Set this to true to interrupt ongoing waits
688 m_interrupt = false;
689
690 // Check for valid socket
691 if (!m_socket)
692 return false;
693
694 // Check for valid timeout value.
695 if (seconds != -1)
696 timeout = seconds * 1000 + milliseconds;
697 else
698 timeout = m_timeout * 1000;
699
700 bool has_event_loop = wxTheApp->GetTraits() ? (wxTheApp->GetTraits()->GetSocketGUIFunctionsTable() ? true : false) : false;
701
702 // Wait in an active polling loop.
703 //
704 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
705 // hurt. It has to be here because the (GSocket) event might arrive
706 // a bit delayed, and it has to be in OnRequest as well because we
707 // don't know whether the Wait functions are being used.
708 //
709 // Do this at least once (important if timeout == 0, when
710 // we are just polling). Also, if just polling, do not yield.
711
712 wxDateTime current_time = wxDateTime::UNow();
713 unsigned int time_limit = (current_time.GetTicks() * 1000) + current_time.GetMillisecond() + timeout;
714 bool done = false;
715 bool valid_result = false;
716
717 if (!has_event_loop)
718 {
719 // This is used to avoid a busy loop on wxBase - having a select
720 // timeout of 50 ms per iteration should be enough.
721 if (timeout > 50)
722 m_socket->SetTimeout(50);
723 else
724 m_socket->SetTimeout(timeout);
725 }
726
727 while (!done)
728 {
729 result = m_socket->Select(flags | GSOCK_LOST_FLAG);
730
731 // Incoming connection (server) or connection established (client)
732 if (result & GSOCK_CONNECTION_FLAG)
733 {
734 m_connected = true;
735 m_establishing = false;
736 valid_result = true;
737 break;
738 }
739
740 // Data available or output buffer ready
741 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
742 {
743 valid_result = true;
744 break;
745 }
746
747 // Connection lost
748 if (result & GSOCK_LOST_FLAG)
749 {
750 m_connected = false;
751 m_establishing = false;
752 valid_result = ((flags & GSOCK_LOST_FLAG) != 0);
753 break;
754 }
755
756 // Wait more?
757 current_time = wxDateTime::UNow();
758 int time_left = time_limit - ((current_time.GetTicks() * 1000) + current_time.GetMillisecond());
759 if ((!timeout) || (time_left <= 0) || (m_interrupt))
760 done = true;
761 else
762 {
763 if (has_event_loop)
764 {
765 PROCESS_EVENTS();
766 }
767 else
768 {
769 // If there's less than 50 ms left, just call select with that timeout.
770 if (time_left < 50)
771 m_socket->SetTimeout(time_left);
772 }
773 }
774 }
775
776 // Set timeout back to original value (we overwrote it for polling)
777 if (!has_event_loop)
778 m_socket->SetTimeout(m_timeout*1000);
779
780 return valid_result;
781}
782
783bool wxSocketBase::Wait(long seconds, long milliseconds)
784{
785 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
786 GSOCK_OUTPUT_FLAG |
787 GSOCK_CONNECTION_FLAG |
788 GSOCK_LOST_FLAG);
789}
790
791bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
792{
793 // Check pushback buffer before entering _Wait
794 if (m_unread)
795 return true;
796
797 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
798 // _Wait because of the semantics of WaitForRead: a return
799 // value of true means that a GSocket_Read call will return
800 // immediately, not that there is actually data to read.
801
802 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
803 GSOCK_LOST_FLAG);
804}
805
806
807bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
808{
809 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
810}
811
812bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
813{
814 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
815}
816
817// --------------------------------------------------------------------------
818// Miscellaneous
819// --------------------------------------------------------------------------
820
821//
822// Get local or peer address
823//
824
825bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
826{
827 GAddress *peer;
828
829 if (!m_socket)
830 return false;
831
832 peer = m_socket->GetPeer();
833
834 // copying a null address would just trigger an assert anyway
835
836 if (!peer)
837 return false;
838
839 addr_man.SetAddress(peer);
840 GAddress_destroy(peer);
841
842 return true;
843}
844
845bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
846{
847 GAddress *local;
848
849 if (!m_socket)
850 return false;
851
852 local = m_socket->GetLocal();
853 addr_man.SetAddress(local);
854 GAddress_destroy(local);
855
856 return true;
857}
858
859//
860// Save and restore socket state
861//
862
863void wxSocketBase::SaveState()
864{
865 wxSocketState *state;
866
867 state = new wxSocketState();
868
869 state->m_flags = m_flags;
870 state->m_notify = m_notify;
871 state->m_eventmask = m_eventmask;
872 state->m_clientData = m_clientData;
873
874 m_states.Append(state);
875}
876
877void wxSocketBase::RestoreState()
878{
879 wxList::compatibility_iterator node;
880 wxSocketState *state;
881
882 node = m_states.GetLast();
883 if (!node)
884 return;
885
886 state = (wxSocketState *)node->GetData();
887
888 m_flags = state->m_flags;
889 m_notify = state->m_notify;
890 m_eventmask = state->m_eventmask;
891 m_clientData = state->m_clientData;
892
893 m_states.Erase(node);
894 delete state;
895}
896
897//
898// Timeout and flags
899//
900
901void wxSocketBase::SetTimeout(long seconds)
902{
903 m_timeout = seconds;
904
905 if (m_socket)
906 m_socket->SetTimeout(m_timeout * 1000);
907}
908
909void wxSocketBase::SetFlags(wxSocketFlags flags)
910{
911 m_flags = flags;
912}
913
914
915// --------------------------------------------------------------------------
916// Event handling
917// --------------------------------------------------------------------------
918
919// A note on how events are processed, which is probably the most
920// difficult thing to get working right while keeping the same API
921// and functionality for all platforms.
922//
923// When GSocket detects an event, it calls wx_socket_callback, which in
924// turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
925// object. OnRequest does some housekeeping, and if the event is to be
926// propagated to the user, it creates a new wxSocketEvent object and
927// posts it. The event is not processed immediately, but delayed with
928// AddPendingEvent instead. This is necessary in order to decouple the
929// event processing from wx_socket_callback; otherwise, subsequent IO
930// calls made from the user event handler would fail, as gtk callbacks
931// are not reentrant.
932//
933// Note that, unlike events, user callbacks (now deprecated) are _not_
934// decoupled from wx_socket_callback and thus they suffer from a variety
935// of problems. Avoid them where possible and use events instead.
936
937extern "C"
938void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
939 GSocketEvent notification,
940 char *cdata)
941{
942 wxSocketBase *sckobj = (wxSocketBase *)cdata;
943
944 sckobj->OnRequest((wxSocketNotify) notification);
945}
946
947void wxSocketBase::OnRequest(wxSocketNotify notification)
948{
949 // NOTE: We duplicate some of the code in _Wait, but this doesn't
950 // hurt. It has to be here because the (GSocket) event might arrive
951 // a bit delayed, and it has to be in _Wait as well because we don't
952 // know whether the Wait functions are being used.
953
954 switch(notification)
955 {
956 case wxSOCKET_CONNECTION:
957 m_establishing = false;
958 m_connected = true;
959 break;
960
961 // If we are in the middle of a R/W operation, do not
962 // propagate events to users. Also, filter 'late' events
963 // which are no longer valid.
964
965 case wxSOCKET_INPUT:
966 if (m_reading || !m_socket->Select(GSOCK_INPUT_FLAG))
967 return;
968 break;
969
970 case wxSOCKET_OUTPUT:
971 if (m_writing || !m_socket->Select(GSOCK_OUTPUT_FLAG))
972 return;
973 break;
974
975 case wxSOCKET_LOST:
976 m_connected = false;
977 m_establishing = false;
978 break;
979
980 default:
981 break;
982 }
983
984 // Schedule the event
985
986 wxSocketEventFlags flag = 0;
987 wxUnusedVar(flag);
988 switch (notification)
989 {
990 case GSOCK_INPUT: flag = GSOCK_INPUT_FLAG; break;
991 case GSOCK_OUTPUT: flag = GSOCK_OUTPUT_FLAG; break;
992 case GSOCK_CONNECTION: flag = GSOCK_CONNECTION_FLAG; break;
993 case GSOCK_LOST: flag = GSOCK_LOST_FLAG; break;
994 default:
995 wxLogWarning(_("wxSocket: unknown event!."));
996 return;
997 }
998
999 if (((m_eventmask & flag) == flag) && m_notify)
1000 {
1001 if (m_handler)
1002 {
1003 wxSocketEvent event(m_id);
1004 event.m_event = notification;
1005 event.m_clientData = m_clientData;
1006 event.SetEventObject(this);
1007
1008 m_handler->AddPendingEvent(event);
1009 }
1010 }
1011}
1012
1013void wxSocketBase::Notify(bool notify)
1014{
1015 m_notify = notify;
1016}
1017
1018void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1019{
1020 m_eventmask = flags;
1021}
1022
1023void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
1024{
1025 m_handler = &handler;
1026 m_id = id;
1027}
1028
1029// --------------------------------------------------------------------------
1030// Pushback buffer
1031// --------------------------------------------------------------------------
1032
1033void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
1034{
1035 if (!size) return;
1036
1037 if (m_unread == NULL)
1038 m_unread = malloc(size);
1039 else
1040 {
1041 void *tmp;
1042
1043 tmp = malloc(m_unrd_size + size);
1044 memcpy((char *)tmp + size, m_unread, m_unrd_size);
1045 free(m_unread);
1046
1047 m_unread = tmp;
1048 }
1049
1050 m_unrd_size += size;
1051
1052 memcpy(m_unread, buffer, size);
1053}
1054
1055wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
1056{
1057 if (!m_unrd_size)
1058 return 0;
1059
1060 if (size > (m_unrd_size-m_unrd_cur))
1061 size = m_unrd_size-m_unrd_cur;
1062
1063 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
1064
1065 if (!peek)
1066 {
1067 m_unrd_cur += size;
1068 if (m_unrd_size == m_unrd_cur)
1069 {
1070 free(m_unread);
1071 m_unread = NULL;
1072 m_unrd_size = 0;
1073 m_unrd_cur = 0;
1074 }
1075 }
1076
1077 return size;
1078}
1079
1080
1081// ==========================================================================
1082// wxSocketServer
1083// ==========================================================================
1084
1085// --------------------------------------------------------------------------
1086// Ctor
1087// --------------------------------------------------------------------------
1088
1089wxSocketServer::wxSocketServer(const wxSockAddress& addr_man,
1090 wxSocketFlags flags)
1091 : wxSocketBase(flags, wxSOCKET_SERVER)
1092{
1093 wxLogTrace( wxTRACE_Socket, _T("Opening wxSocketServer") );
1094
1095 m_socket = GSocket_new();
1096
1097 if (!m_socket)
1098 {
1099 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_new failed") );
1100 return;
1101 }
1102
1103 // Setup the socket as server
1104
1105 m_socket->SetLocal(addr_man.GetAddress());
1106
1107 if (GetFlags() & wxSOCKET_REUSEADDR) {
1108 m_socket->SetReusable();
1109 }
1110
1111 if (m_socket->SetServer() != GSOCK_NOERROR)
1112 {
1113 delete m_socket;
1114 m_socket = NULL;
1115
1116 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_SetServer failed") );
1117 return;
1118 }
1119
1120 m_socket->SetTimeout(m_timeout * 1000);
1121 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1122 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1123 wx_socket_callback, (char *)this);
1124}
1125
1126// --------------------------------------------------------------------------
1127// Accept
1128// --------------------------------------------------------------------------
1129
1130bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
1131{
1132 GSocket *child_socket;
1133
1134 if (!m_socket)
1135 return false;
1136
1137 // If wait == false, then the call should be nonblocking.
1138 // When we are finished, we put the socket to blocking mode
1139 // again.
1140
1141 if (!wait)
1142 m_socket->SetNonBlocking(1);
1143
1144 child_socket = m_socket->WaitConnection();
1145
1146 if (!wait)
1147 m_socket->SetNonBlocking(0);
1148
1149 if (!child_socket)
1150 return false;
1151
1152 sock.m_type = wxSOCKET_BASE;
1153 sock.m_socket = child_socket;
1154 sock.m_connected = true;
1155
1156 sock.m_socket->SetTimeout(sock.m_timeout * 1000);
1157 sock.m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1158 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1159 wx_socket_callback, (char *)&sock);
1160
1161 return true;
1162}
1163
1164wxSocketBase *wxSocketServer::Accept(bool wait)
1165{
1166 wxSocketBase* sock = new wxSocketBase();
1167
1168 sock->SetFlags(m_flags);
1169
1170 if (!AcceptWith(*sock, wait))
1171 {
1172 sock->Destroy();
1173 sock = NULL;
1174 }
1175
1176 return sock;
1177}
1178
1179bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
1180{
1181 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
1182}
1183
1184bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1185{
1186 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1187
1188 if (m_socket->GetSockOpt(level, optname, optval, optlen)
1189 != GSOCK_NOERROR)
1190 {
1191 return false;
1192 }
1193 return true;
1194}
1195
1196bool wxSocketBase::SetOption(int level, int optname, const void *optval,
1197 int optlen)
1198{
1199 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1200
1201 if (m_socket->SetSockOpt(level, optname, optval, optlen)
1202 != GSOCK_NOERROR)
1203 {
1204 return false;
1205 }
1206 return true;
1207}
1208
1209bool wxSocketBase::SetLocal(wxIPV4address& local)
1210{
1211 GAddress* la = local.GetAddress();
1212
1213 // If the address is valid, save it for use when we call Connect
1214 if (la && la->m_addr)
1215 {
1216 m_localAddress = local;
1217
1218 return true;
1219 }
1220
1221 return false;
1222}
1223
1224// ==========================================================================
1225// wxSocketClient
1226// ==========================================================================
1227
1228// --------------------------------------------------------------------------
1229// Ctor and dtor
1230// --------------------------------------------------------------------------
1231
1232wxSocketClient::wxSocketClient(wxSocketFlags flags)
1233 : wxSocketBase(flags, wxSOCKET_CLIENT)
1234{
1235}
1236
1237wxSocketClient::~wxSocketClient()
1238{
1239}
1240
1241// --------------------------------------------------------------------------
1242// Connect
1243// --------------------------------------------------------------------------
1244
1245bool wxSocketClient::DoConnect(wxSockAddress& addr_man, wxSockAddress* local, bool wait)
1246{
1247 GSocketError err;
1248
1249 if (m_socket)
1250 {
1251 // Shutdown and destroy the socket
1252 Close();
1253 delete m_socket;
1254 }
1255
1256 m_socket = GSocket_new();
1257 m_connected = false;
1258 m_establishing = false;
1259
1260 if (!m_socket)
1261 return false;
1262
1263 m_socket->SetTimeout(m_timeout * 1000);
1264 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1265 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1266 wx_socket_callback, (char *)this);
1267
1268 // If wait == false, then the call should be nonblocking.
1269 // When we are finished, we put the socket to blocking mode
1270 // again.
1271
1272 if (!wait)
1273 m_socket->SetNonBlocking(1);
1274
1275 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1276 if (GetFlags() & wxSOCKET_REUSEADDR)
1277 {
1278 m_socket->SetReusable();
1279 }
1280
1281 // If no local address was passed and one has been set, use the one that was Set
1282 if (!local && m_localAddress.GetAddress())
1283 {
1284 local = &m_localAddress;
1285 }
1286
1287 // Bind to the local IP address and port, when provided
1288 if (local)
1289 {
1290 GAddress* la = local->GetAddress();
1291
1292 if (la && la->m_addr)
1293 m_socket->SetLocal(la);
1294 }
1295
1296 m_socket->SetPeer(addr_man.GetAddress());
1297 err = m_socket->Connect(GSOCK_STREAMED);
1298
1299 if (!wait)
1300 m_socket->SetNonBlocking(0);
1301
1302 if (err != GSOCK_NOERROR)
1303 {
1304 if (err == GSOCK_WOULDBLOCK)
1305 m_establishing = true;
1306
1307 return false;
1308 }
1309
1310 m_connected = true;
1311 return true;
1312}
1313
1314bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
1315{
1316 return (DoConnect(addr_man, NULL, wait));
1317}
1318
1319bool wxSocketClient::Connect(wxSockAddress& addr_man, wxSockAddress& local, bool wait)
1320{
1321 return (DoConnect(addr_man, &local, wait));
1322}
1323
1324bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
1325{
1326 if (m_connected) // Already connected
1327 return true;
1328
1329 if (!m_establishing || !m_socket) // No connection in progress
1330 return false;
1331
1332 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG |
1333 GSOCK_LOST_FLAG);
1334}
1335
1336// ==========================================================================
1337// wxDatagramSocket
1338// ==========================================================================
1339
1340/* NOTE: experimental stuff - might change */
1341
1342wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
1343 wxSocketFlags flags )
1344 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
1345{
1346 // Create the socket
1347 m_socket = GSocket_new();
1348
1349 if(!m_socket)
1350 {
1351 wxFAIL_MSG( _T("datagram socket not new'd") );
1352 return;
1353 }
1354 // Setup the socket as non connection oriented
1355 m_socket->SetLocal(addr.GetAddress());
1356 if( m_socket->SetNonOriented() != GSOCK_NOERROR )
1357 {
1358 delete m_socket;
1359 m_socket = NULL;
1360 return;
1361 }
1362
1363 // Initialize all stuff
1364 m_connected = false;
1365 m_establishing = false;
1366 m_socket->SetTimeout( m_timeout );
1367 m_socket->SetCallback( GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1368 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1369 wx_socket_callback, (char*)this );
1370}
1371
1372wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
1373 void* buf,
1374 wxUint32 nBytes )
1375{
1376 Read(buf, nBytes);
1377 GetPeer(addr);
1378 return (*this);
1379}
1380
1381wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
1382 const void* buf,
1383 wxUint32 nBytes )
1384{
1385 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1386
1387 m_socket->SetPeer(addr.GetAddress());
1388 Write(buf, nBytes);
1389 return (*this);
1390}
1391
1392// ==========================================================================
1393// wxSocketModule
1394// ==========================================================================
1395
1396class wxSocketModule : public wxModule
1397{
1398public:
1399 virtual bool OnInit()
1400 {
1401 // wxSocketBase will call GSocket_Init() itself when/if needed
1402 return true;
1403 }
1404
1405 virtual void OnExit()
1406 {
1407 if ( wxSocketBase::IsInitialized() )
1408 wxSocketBase::Shutdown();
1409 }
1410
1411private:
1412 DECLARE_DYNAMIC_CLASS(wxSocketModule)
1413};
1414
1415IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1416
1417#endif
1418 // wxUSE_SOCKETS