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