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