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