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