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