]> git.saurik.com Git - wxWidgets.git/blob - src/common/socket.cpp
Implemented wxStatusBar::Push/PopStatusText.
[wxWidgets.git] / src / common / socket.cpp
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
83 IMPLEMENT_CLASS(wxSocketBase, wxObject)
84 IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
85 IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
86 IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
87 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
88
89 // --------------------------------------------------------------------------
90 // private classes
91 // --------------------------------------------------------------------------
92
93 class wxSocketState : public wxObject
94 {
95 public:
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
105 public:
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
119 size_t wxSocketBase::m_countInit = 0;
120
121 bool wxSocketBase::IsInitialized()
122 {
123 return m_countInit > 0;
124 }
125
126 bool 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
141 void 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
155 void 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
195 wxSocketBase::wxSocketBase()
196 {
197 Init();
198 }
199
200 wxSocketBase::wxSocketBase(wxSocketFlags flags, wxSocketType type)
201 {
202 Init();
203
204 m_flags = flags;
205 m_type = type;
206 }
207
208 wxSocketBase::~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
229 bool 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
261 bool 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
281 wxSocketBase& 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
300 wxUint32 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
363 wxSocketBase& 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
453 exit:
454 m_error = error;
455 m_lcount = total;
456 m_reading = FALSE;
457 SetFlags(old_flags);
458
459 return *this;
460 }
461
462 wxSocketBase& 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
482 wxSocketBase& 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
501 wxUint32 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
554 wxSocketBase& 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
603 exit:
604 m_error = error;
605 m_lcount = total;
606 m_writing = FALSE;
607
608 return *this;
609 }
610
611 wxSocketBase& 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
622 wxSocketBase& 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
662 bool 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
731 bool 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
739 bool 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
754 bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
755 {
756 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
757 }
758
759 bool 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
772 bool 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
786 bool 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
804 void 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
822 void 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
850 void wxSocketBase::SetTimeout(long seconds)
851 {
852 m_timeout = seconds;
853
854 if (m_socket)
855 GSocket_SetTimeout(m_socket, m_timeout * 1000);
856 }
857
858 void 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
870 wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_)
871 {
872 wxSockCbk old_cbk = cbk_;
873
874 m_cbk = cbk_;
875 return old_cbk;
876 }
877
878 char *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
910 extern "C"
911 void 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
920 void 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
990 void wxSocketBase::Notify(bool notify)
991 {
992 m_notify = notify;
993 }
994
995 void wxSocketBase::SetNotify(wxSocketEventFlags flags)
996 {
997 m_eventmask = flags;
998 }
999
1000 void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
1001 {
1002 m_handler = &handler;
1003 m_id = id;
1004 }
1005
1006 // --------------------------------------------------------------------------
1007 // Pushback buffer
1008 // --------------------------------------------------------------------------
1009
1010 void 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
1032 wxUint32 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
1066 wxSocketServer::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
1096 bool 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
1130 wxSocketBase *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
1145 bool 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
1158 wxSocketClient::wxSocketClient(wxSocketFlags flags)
1159 : wxSocketBase(flags, wxSOCKET_CLIENT)
1160 {
1161 }
1162
1163 wxSocketClient::~wxSocketClient()
1164 {
1165 }
1166
1167 // --------------------------------------------------------------------------
1168 // Connect
1169 // --------------------------------------------------------------------------
1170
1171 bool 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
1219 bool 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
1237 wxDatagramSocket::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
1266 wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
1267 void* buf,
1268 wxUint32 nBytes )
1269 {
1270 Read(buf, nBytes);
1271 GetPeer(addr);
1272 return (*this);
1273 }
1274
1275 wxDatagramSocket& 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
1288 class WXDLLEXPORT wxSocketModule : public wxModule
1289 {
1290 public:
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
1303 private:
1304 DECLARE_DYNAMIC_CLASS(wxSocketModule)
1305 };
1306
1307 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1308
1309 #endif
1310 // wxUSE_SOCKETS