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