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