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