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