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