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