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