]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/socket.cpp
WX_DECLARE_HASH() macro for type safe hashes
[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#ifdef __GNUG__
13#pragma implementation "socket.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#if wxUSE_SOCKETS
24
25// ==========================================================================
26// Headers and constants
27// ==========================================================================
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
39#if wxUSE_GUI
40 #include "wx/gdicmn.h" // for wxPendingDelete
41#endif // wxUSE_GUI
42
43#include "wx/sckaddr.h"
44#include "wx/socket.h"
45
46
47// discard buffer
48#define MAX_DISCARD_SIZE (10 * 1024)
49
50// what to do within waits
51#define PROCESS_EVENTS() wxYield()
52
53// use wxPostEvent or not
54#define USE_DELAYED_EVENTS 1
55
56// --------------------------------------------------------------------------
57// ClassInfos
58// --------------------------------------------------------------------------
59
60IMPLEMENT_CLASS(wxSocketBase, wxObject)
61IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
62IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
63IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
64IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
65
66class wxSocketState : public wxObject
67{
68public:
69 bool m_notify_state;
70 wxSocketEventFlags m_neededreq;
71 wxSockFlags m_flags;
72 wxSocketBase::wxSockCbk m_cbk;
73 char *m_cdata;
74
75public:
76 wxSocketState() : wxObject() {}
77};
78
79
80// ==========================================================================
81// wxSocketBase
82// ==========================================================================
83
84// --------------------------------------------------------------------------
85// Ctor and dtor
86// --------------------------------------------------------------------------
87
88wxSocketBase::wxSocketBase(wxSockFlags _flags, wxSockType _type) :
89 wxEvtHandler(),
90 m_socket(NULL), m_evt_handler(NULL), m_id(-1),
91 m_flags(_flags), m_type(_type),
92 m_neededreq(0), m_notify_state(FALSE),
93 m_connected(FALSE), m_establishing(FALSE),
94 m_reading(FALSE), m_writing(FALSE),
95 m_error(FALSE), m_lcount(0), m_timeout(600), m_states(),
96 m_unread(NULL), m_unrd_size(0), m_unrd_cur(0),
97 m_cbk(NULL), m_cdata(NULL)
98{
99}
100
101wxSocketBase::wxSocketBase() :
102 wxEvtHandler(),
103 m_socket(NULL), m_evt_handler(NULL), m_id(-1),
104 m_flags(NONE), m_type(SOCK_UNINIT),
105 m_neededreq(0), m_notify_state(FALSE),
106 m_connected(FALSE), m_establishing(FALSE),
107 m_reading(FALSE), m_writing(FALSE),
108 m_error(FALSE), m_lcount(0), m_timeout(600), m_states(),
109 m_unread(NULL), m_unrd_size(0), m_unrd_cur(0),
110 m_cbk(NULL), m_cdata(NULL)
111{
112}
113
114wxSocketBase::~wxSocketBase()
115{
116 if (m_unread)
117 free(m_unread);
118
119 // Shutdown and close the socket
120 Close();
121
122 // Destroy the GSocket object
123 if (m_socket)
124 GSocket_destroy(m_socket);
125}
126
127/*
128bool wxSocketBase::Destroy()
129{
130 // Delayed destruction: the socket will be deleted during the next
131 // idle loop iteration. This ensures that all pending events have
132 // been processed.
133
134 m_beingDeleted = TRUE;
135 Close();
136
137 if ( !wxPendingDelete.Member(this) )
138 wxPendingDelete.Append(this);
139
140 return TRUE;
141}
142*/
143
144// --------------------------------------------------------------------------
145// Basic IO operations
146// --------------------------------------------------------------------------
147
148// The following IO operations update m_error and m_lcount:
149// {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
150//
151// TODO: Should Connect, Accept and AcceptWith update m_error?
152
153bool wxSocketBase::Close()
154{
155 // Interrupt pending waits
156 InterruptAllWaits();
157
158 if (m_socket)
159 {
160 // Disable callbacks
161 GSocket_UnsetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
162 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
163
164 // Shutdown the connection
165 GSocket_Shutdown(m_socket);
166 }
167
168 m_connected = FALSE;
169 m_establishing = FALSE;
170 return TRUE;
171}
172
173wxSocketBase& wxSocketBase::Read(char* buffer, wxUint32 nbytes)
174{
175 // Mask read events
176 m_reading = TRUE;
177
178 m_lcount = _Read(buffer, nbytes);
179
180 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
181 if (m_flags & wxSOCKET_WAITALL)
182 m_error = (m_lcount != nbytes);
183 else
184 m_error = (m_lcount == 0);
185
186 // Allow read events from now on
187 m_reading = FALSE;
188
189 return *this;
190}
191
192wxUint32 wxSocketBase::_Read(char* buffer, wxUint32 nbytes)
193{
194 int total;
195 int ret = 1;
196
197 // Try the pushback buffer first
198 total = GetPushback(buffer, nbytes, FALSE);
199 nbytes -= total;
200 buffer += total;
201
202 // If the socket is invalid or we got all the data, return now
203 if (!m_socket || !nbytes)
204 return total;
205
206 // Possible combinations (they are checked in this order)
207 // wxSOCKET_NOWAIT
208 // wxSOCKET_WAITALL | wxSOCKET_BLOCK
209 // wxSOCKET_WAITALL
210 // wxSOCKET_BLOCK
211 // wxSOCKET_NONE
212 //
213 if (m_flags & wxSOCKET_NOWAIT)
214 {
215 GSocket_SetNonBlocking(m_socket, TRUE);
216 ret = GSocket_Read(m_socket, buffer, nbytes);
217 GSocket_SetNonBlocking(m_socket, FALSE);
218
219 if (ret > 0)
220 total += ret;
221 }
222 else if (m_flags & wxSOCKET_WAITALL)
223 {
224 while (ret > 0 && nbytes > 0)
225 {
226 if (!(m_flags & wxSOCKET_BLOCK) && !WaitForRead())
227 break;
228
229 ret = GSocket_Read(m_socket, buffer, nbytes);
230
231 if (ret > 0)
232 {
233 total += ret;
234 buffer += ret;
235 nbytes -= ret;
236 }
237 }
238 }
239 else
240 {
241 if ((m_flags & wxSOCKET_BLOCK) || WaitForRead())
242 {
243 ret = GSocket_Read(m_socket, buffer, nbytes);
244
245 if (ret > 0)
246 total += ret;
247 }
248 }
249
250 return total;
251}
252
253wxSocketBase& wxSocketBase::ReadMsg(char* buffer, wxUint32 nbytes)
254{
255 wxUint32 len, len2, sig, total;
256 bool error;
257 int old_flags;
258 struct
259 {
260 unsigned char sig[4];
261 unsigned char len[4];
262 } msg;
263
264 // Mask read events
265 m_reading = TRUE;
266
267 total = 0;
268 error = TRUE;
269 old_flags = m_flags;
270 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
271
272 if (_Read((char *)&msg, sizeof(msg)) != sizeof(msg))
273 goto exit;
274
275 sig = (wxUint32)msg.sig[0];
276 sig |= (wxUint32)(msg.sig[1] << 8);
277 sig |= (wxUint32)(msg.sig[2] << 16);
278 sig |= (wxUint32)(msg.sig[3] << 24);
279
280 if (sig != 0xfeeddead)
281 {
282 wxLogWarning( _("wxSocket: invalid signature in ReadMsg."));
283 goto exit;
284 }
285
286 len = (wxUint32)msg.len[0];
287 len |= (wxUint32)(msg.len[1] << 8);
288 len |= (wxUint32)(msg.len[2] << 16);
289 len |= (wxUint32)(msg.len[3] << 24);
290
291 if (len > nbytes)
292 {
293 len2 = len - nbytes;
294 len = nbytes;
295 }
296 else
297 len2 = 0;
298
299 // Don't attemp to read if the msg was zero bytes long.
300 if (len)
301 {
302 total = _Read(buffer, len);
303
304 if (total != len)
305 goto exit;
306 }
307 if (len2)
308 {
309 char *discard_buffer = new char[MAX_DISCARD_SIZE];
310 long discard_len;
311
312 // NOTE: discarded bytes don't add to m_lcount.
313 do
314 {
315 discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
316 discard_len = _Read(discard_buffer, (wxUint32)discard_len);
317 len2 -= (wxUint32)discard_len;
318 }
319 while ((discard_len > 0) && len2);
320
321 delete [] discard_buffer;
322
323 if (len2 != 0)
324 goto exit;
325 }
326 if (_Read((char *)&msg, sizeof(msg)) != sizeof(msg))
327 goto exit;
328
329 sig = (wxUint32)msg.sig[0];
330 sig |= (wxUint32)(msg.sig[1] << 8);
331 sig |= (wxUint32)(msg.sig[2] << 16);
332 sig |= (wxUint32)(msg.sig[3] << 24);
333
334 if (sig != 0xdeadfeed)
335 {
336 wxLogWarning( _("wxSocket: invalid signature in ReadMsg."));
337 goto exit;
338 }
339
340 // everything was OK
341 error = FALSE;
342
343exit:
344 m_error = error;
345 m_lcount = total;
346 m_reading = FALSE;
347 SetFlags(old_flags);
348
349 return *this;
350}
351
352wxSocketBase& wxSocketBase::Peek(char* buffer, wxUint32 nbytes)
353{
354 // Mask read events
355 m_reading = TRUE;
356
357 m_lcount = _Read(buffer, nbytes);
358 Pushback(buffer, m_lcount);
359
360 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
361 if (m_flags & wxSOCKET_WAITALL)
362 m_error = (m_lcount != nbytes);
363 else
364 m_error = (m_lcount == 0);
365
366 // Allow read events again
367 m_reading = FALSE;
368
369 return *this;
370}
371
372wxSocketBase& wxSocketBase::Write(const char *buffer, wxUint32 nbytes)
373{
374 // Mask write events
375 m_writing = TRUE;
376
377 m_lcount = _Write(buffer, nbytes);
378
379 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
380 if (m_flags & wxSOCKET_WAITALL)
381 m_error = (m_lcount != nbytes);
382 else
383 m_error = (m_lcount == 0);
384
385 // Allow write events again
386 m_writing = FALSE;
387
388 return *this;
389}
390
391wxUint32 wxSocketBase::_Write(const char *buffer, wxUint32 nbytes)
392{
393 wxUint32 total = 0;
394 int ret = 1;
395
396 // If the socket is invalid, return immediately
397 if (!m_socket)
398 return 0;
399
400 // Possible combinations (they are checked in this order)
401 // wxSOCKET_NOWAIT
402 // wxSOCKET_WAITALL | wxSOCKET_BLOCK
403 // wxSOCKET_WAITALL
404 // wxSOCKET_BLOCK
405 // wxSOCKET_NONE
406 //
407 if (m_flags & wxSOCKET_NOWAIT)
408 {
409 GSocket_SetNonBlocking(m_socket, TRUE);
410 ret = GSocket_Write(m_socket, buffer, nbytes);
411 GSocket_SetNonBlocking(m_socket, FALSE);
412
413 if (ret > 0)
414 total = ret;
415 }
416 else if (m_flags & wxSOCKET_WAITALL)
417 {
418 while (ret > 0 && nbytes > 0)
419 {
420 if (!(m_flags & wxSOCKET_BLOCK) && !WaitForWrite())
421 break;
422
423 ret = GSocket_Write(m_socket, buffer, nbytes);
424
425 if (ret > 0)
426 {
427 total += ret;
428 buffer += ret;
429 nbytes -= ret;
430 }
431 }
432 }
433 else
434 {
435 if ((m_flags & wxSOCKET_BLOCK) || WaitForWrite())
436 {
437 ret = GSocket_Write(m_socket, buffer, nbytes);
438
439 if (ret > 0)
440 total = ret;
441 }
442 }
443
444 return total;
445}
446
447wxSocketBase& wxSocketBase::WriteMsg(const char *buffer, wxUint32 nbytes)
448{
449 wxUint32 total;
450 bool error;
451 int old_flags;
452 struct {
453 unsigned char sig[4];
454 unsigned char len[4];
455 } msg;
456
457 // Mask write events
458 m_writing = TRUE;
459
460 error = TRUE;
461 total = 0;
462 old_flags = m_flags;
463 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
464
465 msg.sig[0] = (unsigned char) 0xad;
466 msg.sig[1] = (unsigned char) 0xde;
467 msg.sig[2] = (unsigned char) 0xed;
468 msg.sig[3] = (unsigned char) 0xfe;
469
470 msg.len[0] = (unsigned char) (nbytes & 0xff);
471 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
472 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
473 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
474
475 if (_Write((char *)&msg, sizeof(msg)) < sizeof(msg))
476 goto exit;
477
478 total = _Write(buffer, nbytes);
479
480 if (total < nbytes)
481 goto exit;
482
483 msg.sig[0] = (unsigned char) 0xed;
484 msg.sig[1] = (unsigned char) 0xfe;
485 msg.sig[2] = (unsigned char) 0xad;
486 msg.sig[3] = (unsigned char) 0xde;
487 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
488
489 if ((_Write((char *)&msg, sizeof(msg))) < sizeof(msg))
490 goto exit;
491
492 // everything was OK
493 error = FALSE;
494
495exit:
496 m_error = error;
497 m_lcount = total;
498 m_writing = FALSE;
499
500 return *this;
501}
502
503wxSocketBase& wxSocketBase::Unread(const char *buffer, wxUint32 nbytes)
504{
505 if (nbytes != 0)
506 Pushback(buffer, nbytes);
507
508 m_error = FALSE;
509 m_lcount = nbytes;
510
511 return *this;
512}
513
514wxSocketBase& wxSocketBase::Discard()
515{
516 int old_flags;
517 char *buffer = new char[MAX_DISCARD_SIZE];
518 wxUint32 ret;
519 wxUint32 total = 0;
520
521 // Mask read events
522 m_reading = TRUE;
523
524 old_flags = m_flags;
525 SetFlags(wxSOCKET_NOWAIT);
526
527 do
528 {
529 ret = _Read(buffer, MAX_DISCARD_SIZE);
530 total += ret;
531 }
532 while (ret == MAX_DISCARD_SIZE);
533
534 delete[] buffer;
535 m_lcount = total;
536 m_error = FALSE;
537
538 // Allow read events again
539 m_reading = FALSE;
540
541 return *this;
542}
543
544// --------------------------------------------------------------------------
545// Wait functions
546// --------------------------------------------------------------------------
547
548// All Wait functions poll the socket using GSocket_Select() to
549// check for the specified combination of conditions, until one
550// of these conditions become true, an error occurs, or the
551// timeout elapses. The polling loop calls PROCESS_EVENTS(), so
552// this won't block the GUI.
553
554#if wxUSE_GUI
555
556class _wxSocketInternalTimer: public wxTimer
557{
558public:
559 int *m_state;
560 unsigned long m_new_val;
561
562 void Notify()
563 {
564 *m_state = (int)m_new_val; // Change the value
565 }
566};
567
568#endif // wxUSE_GUI
569
570bool wxSocketBase::_Wait(long seconds, long milliseconds,
571 wxSocketEventFlags flags)
572{
573 GSocketEventFlags result;
574#if wxUSE_GUI
575 _wxSocketInternalTimer timer;
576 wxTimerRunner runTimer(timer);
577#endif // wxUSE_GUI
578
579 long timeout;
580 int state = -1;
581
582 // Set this to TRUE to interrupt ongoing waits
583 m_interrupt = FALSE;
584
585 // Check for valid socket
586 if (!m_socket)
587 return FALSE;
588
589 // Check for valid timeout value
590 if (seconds != -1)
591 timeout = seconds * 1000 + milliseconds;
592 else
593 timeout = m_timeout * 1000;
594
595 // Activate timer
596 if (timeout)
597 {
598#if wxUSE_GUI
599 timer.m_state = &state;
600 timer.m_new_val = 0;
601 runTimer.Start((int)timeout, TRUE);
602#endif // wxUSE_GUI
603 }
604
605 // Active polling (without using events)
606 //
607 // NOTE: this duplicates some of the code in OnRequest (lost
608 // connection and connection establishment handling) but
609 // this doesn't hurt. It has to be here because the event
610 // might be a bit delayed, and it has to be in OnRequest
611 // as well because maybe the Wait functions are not being
612 // used.
613 //
614 // Do this at least once (important if timeout == 0, when
615 // we are just polling). Also, if just polling, do not yield.
616
617 while (state == -1)
618 {
619 result = GSocket_Select(m_socket, flags | GSOCK_LOST_FLAG);
620
621 // Incoming connection (server) or connection established (client)
622 if (result & GSOCK_CONNECTION_FLAG)
623 {
624 m_connected = TRUE;
625 m_establishing = FALSE;
626 return TRUE;
627 }
628
629 // Data available or output buffer ready
630 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
631 {
632 return TRUE;
633 }
634
635 // Connection lost
636 if (result & GSOCK_LOST_FLAG)
637 {
638 m_connected = FALSE;
639 m_establishing = FALSE;
640 return (flags & GSOCK_LOST_FLAG);
641 }
642
643 // Wait more?
644 if ((timeout == 0) || (m_interrupt))
645 break;
646 else
647 PROCESS_EVENTS();
648 }
649
650 return FALSE;
651}
652
653bool wxSocketBase::Wait(long seconds, long milliseconds)
654{
655 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
656 GSOCK_OUTPUT_FLAG |
657 GSOCK_CONNECTION_FLAG |
658 GSOCK_LOST_FLAG);
659}
660
661bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
662{
663 // Check pushback buffer before entering _Wait
664 if (m_unread)
665 return TRUE;
666
667 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
668 // _Wait becuase of the semantics of WaitForRead: a return
669 // value of TRUE means that a GSocket_Read call will return
670 // immediately, not that there is actually data to read.
671
672 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
673 GSOCK_LOST_FLAG);
674}
675
676bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
677{
678 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
679}
680
681bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
682{
683 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
684}
685
686// --------------------------------------------------------------------------
687// Miscellaneous
688// --------------------------------------------------------------------------
689
690//
691// Get local or peer address
692//
693
694bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
695{
696 GAddress *peer;
697
698 if (!m_socket)
699 return FALSE;
700
701 peer = GSocket_GetPeer(m_socket);
702 addr_man.SetAddress(peer);
703 GAddress_destroy(peer);
704
705 return TRUE;
706}
707
708bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
709{
710 GAddress *local;
711
712 if (!m_socket)
713 return FALSE;
714
715 local = GSocket_GetLocal(m_socket);
716 addr_man.SetAddress(local);
717 GAddress_destroy(local);
718
719 return TRUE;
720}
721
722//
723// Save and restore socket state
724//
725
726void wxSocketBase::SaveState()
727{
728 wxSocketState *state;
729
730 state = new wxSocketState();
731
732 state->m_notify_state = m_notify_state;
733 state->m_neededreq = m_neededreq;
734 state->m_flags = m_flags;
735 state->m_cbk = m_cbk;
736 state->m_cdata = m_cdata;
737
738 m_states.Append(state);
739}
740
741void wxSocketBase::RestoreState()
742{
743 wxNode *node;
744 wxSocketState *state;
745
746 node = m_states.Last();
747 if (!node)
748 return;
749
750 state = (wxSocketState *)node->Data();
751
752 SetFlags(state->m_flags);
753 m_cbk = state->m_cbk;
754 m_cdata = state->m_cdata;
755 m_neededreq = state->m_neededreq;
756 Notify(state->m_notify_state);
757
758 delete node;
759 delete state;
760}
761
762//
763// Timeout and flags
764//
765
766void wxSocketBase::SetTimeout(long seconds)
767{
768 m_timeout = seconds;
769
770 if (m_socket)
771 GSocket_SetTimeout(m_socket, m_timeout * 1000);
772}
773
774void wxSocketBase::SetFlags(wxSockFlags _flags)
775{
776 m_flags = _flags;
777}
778
779// --------------------------------------------------------------------------
780// Callbacks (now obsolete - use events instead)
781// --------------------------------------------------------------------------
782
783wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_)
784{
785 wxSockCbk old_cbk = cbk_;
786
787 m_cbk = cbk_;
788 return old_cbk;
789}
790
791char *wxSocketBase::CallbackData(char *data)
792{
793 char *old_data = m_cdata;
794
795 m_cdata = data;
796 return old_data;
797}
798
799// --------------------------------------------------------------------------
800// Event system
801// --------------------------------------------------------------------------
802
803// All events (INPUT, OUTPUT, CONNECTION, LOST) are now always
804// internally watched; but users will only be notified of those
805// events they are interested in.
806
807static void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
808 GSocketEvent event,
809 char *cdata)
810{
811 wxSocketBase *sckobj = (wxSocketBase *)cdata;
812
813 sckobj->OnRequest((wxSocketNotify)event);
814}
815
816wxSocketEventFlags wxSocketBase::EventToNotify(wxSocketNotify evt)
817{
818 switch (evt)
819 {
820 case GSOCK_INPUT: return GSOCK_INPUT_FLAG;
821 case GSOCK_OUTPUT: return GSOCK_OUTPUT_FLAG;
822 case GSOCK_CONNECTION: return GSOCK_CONNECTION_FLAG;
823 case GSOCK_LOST: return GSOCK_LOST_FLAG;
824 }
825 return 0;
826}
827
828void wxSocketBase::SetNotify(wxSocketEventFlags flags)
829{
830 m_neededreq = flags;
831}
832
833void wxSocketBase::Notify(bool notify)
834{
835 m_notify_state = notify;
836}
837
838void wxSocketBase::OnRequest(wxSocketNotify req_evt)
839{
840 wxSocketEvent event(m_id);
841 wxSocketEventFlags flag = EventToNotify(req_evt);
842
843 // This duplicates some code in _Wait, but this doesn't
844 // hurt. It has to be here because we don't know whether
845 // the Wait functions will be used, and it has to be in
846 // _Wait as well because the event might be a bit delayed.
847
848 switch(req_evt)
849 {
850 case wxSOCKET_CONNECTION:
851 m_establishing = FALSE;
852 m_connected = TRUE;
853 break;
854
855 // If we are in the middle of a R/W operation, do not
856 // propagate events to users. Also, filter 'late' events
857 // which are no longer valid.
858
859 case wxSOCKET_INPUT:
860 if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
861 return;
862 break;
863
864 case wxSOCKET_OUTPUT:
865 if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
866 return;
867 break;
868
869 case wxSOCKET_LOST:
870 m_connected = FALSE;
871 m_establishing = FALSE;
872 break;
873
874 default:
875 break;
876 }
877
878 if (((m_neededreq & flag) == flag) && m_notify_state)
879 {
880 event.m_socket = this;
881 event.m_skevt = req_evt;
882
883 if (m_evt_handler)
884 {
885#if USE_DELAYED_EVENTS
886 wxPostEvent(m_evt_handler, event);
887#else
888 ProcessEvent(event);
889#endif
890 }
891
892 OldOnNotify(req_evt);
893 if (m_cbk)
894 m_cbk(*this, req_evt, m_cdata);
895 }
896}
897
898void wxSocketBase::OldOnNotify(wxSocketNotify WXUNUSED(evt))
899{
900}
901
902void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id)
903{
904 m_evt_handler = &h_evt;
905 m_id = id;
906
907 SetNextHandler(&h_evt);
908}
909
910// --------------------------------------------------------------------------
911// Pushback buffer
912// --------------------------------------------------------------------------
913
914void wxSocketBase::Pushback(const char *buffer, wxUint32 size)
915{
916 if (!size) return;
917
918 if (m_unread == NULL)
919 m_unread = (char *)malloc(size);
920 else
921 {
922 char *tmp;
923
924 tmp = (char *)malloc(m_unrd_size + size);
925 memcpy(tmp+size, m_unread, m_unrd_size);
926 free(m_unread);
927
928 m_unread = tmp;
929 }
930
931 m_unrd_size += size;
932
933 memcpy(m_unread, buffer, size);
934}
935
936wxUint32 wxSocketBase::GetPushback(char *buffer, wxUint32 size, bool peek)
937{
938 if (!m_unrd_size)
939 return 0;
940
941 if (size > (m_unrd_size-m_unrd_cur))
942 size = m_unrd_size-m_unrd_cur;
943
944 memcpy(buffer, (m_unread+m_unrd_cur), size);
945
946 if (!peek)
947 {
948 m_unrd_cur += size;
949 if (m_unrd_size == m_unrd_cur)
950 {
951 free(m_unread);
952 m_unread = NULL;
953 m_unrd_size = 0;
954 m_unrd_cur = 0;
955 }
956 }
957
958 return size;
959}
960
961// ==========================================================================
962// wxSocketServer
963// ==========================================================================
964
965// --------------------------------------------------------------------------
966// Ctor
967// --------------------------------------------------------------------------
968
969wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
970 wxSockFlags flags)
971 : wxSocketBase(flags, SOCK_SERVER)
972{
973 // Create the socket
974 m_socket = GSocket_new();
975
976 if (!m_socket)
977 return;
978
979 // Setup the socket as server
980 GSocket_SetLocal(m_socket, addr_man.GetAddress());
981 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
982 {
983 GSocket_destroy(m_socket);
984 m_socket = NULL;
985 return;
986 }
987
988 GSocket_SetTimeout(m_socket, m_timeout * 1000);
989 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
990 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
991 wx_socket_callback, (char *)this);
992
993}
994
995// --------------------------------------------------------------------------
996// Accept
997// --------------------------------------------------------------------------
998
999bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
1000{
1001 GSocket *child_socket;
1002
1003 if (!m_socket)
1004 return FALSE;
1005
1006 // If wait == FALSE, then the call should be nonblocking.
1007 // When we are finished, we put the socket to blocking mode
1008 // again.
1009
1010 if (!wait)
1011 GSocket_SetNonBlocking(m_socket, TRUE);
1012
1013 child_socket = GSocket_WaitConnection(m_socket);
1014
1015 if (!wait)
1016 GSocket_SetNonBlocking(m_socket, FALSE);
1017
1018 if (!child_socket)
1019 return FALSE;
1020
1021 sock.m_type = SOCK_INTERNAL;
1022 sock.m_socket = child_socket;
1023 sock.m_connected = TRUE;
1024
1025 GSocket_SetTimeout(sock.m_socket, sock.m_timeout * 1000);
1026 GSocket_SetCallback(sock.m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1027 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1028 wx_socket_callback, (char *)&sock);
1029
1030 return TRUE;
1031}
1032
1033wxSocketBase *wxSocketServer::Accept(bool wait)
1034{
1035 wxSocketBase* sock = new wxSocketBase();
1036
1037 sock->SetFlags((wxSockFlags)m_flags);
1038
1039 if (!AcceptWith(*sock, wait))
1040 return NULL;
1041
1042 return sock;
1043}
1044
1045bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
1046{
1047 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
1048}
1049
1050// ==========================================================================
1051// wxSocketClient
1052// ==========================================================================
1053
1054// --------------------------------------------------------------------------
1055// Ctor and dtor
1056// --------------------------------------------------------------------------
1057
1058wxSocketClient::wxSocketClient(wxSockFlags _flags)
1059 : wxSocketBase(_flags, SOCK_CLIENT)
1060{
1061}
1062
1063// XXX: What is this for ?
1064wxSocketClient::~wxSocketClient()
1065{
1066}
1067
1068// --------------------------------------------------------------------------
1069// Connect
1070// --------------------------------------------------------------------------
1071
1072bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
1073{
1074 GSocketError err;
1075
1076 if (m_socket)
1077 {
1078 // Shutdown and destroy the socket
1079 Close();
1080 GSocket_destroy(m_socket);
1081 }
1082
1083 m_socket = GSocket_new();
1084 m_connected = FALSE;
1085 m_establishing = FALSE;
1086
1087 if (!m_socket)
1088 return FALSE;
1089
1090 GSocket_SetTimeout(m_socket, m_timeout * 1000);
1091 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1092 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1093 wx_socket_callback, (char *)this);
1094
1095 // If wait == FALSE, then the call should be nonblocking.
1096 // When we are finished, we put the socket to blocking mode
1097 // again.
1098
1099 if (!wait)
1100 GSocket_SetNonBlocking(m_socket, TRUE);
1101
1102 GSocket_SetPeer(m_socket, addr_man.GetAddress());
1103 err = GSocket_Connect(m_socket, GSOCK_STREAMED);
1104
1105 if (!wait)
1106 GSocket_SetNonBlocking(m_socket, FALSE);
1107
1108 if (err != GSOCK_NOERROR)
1109 {
1110 if (err == GSOCK_WOULDBLOCK)
1111 m_establishing = TRUE;
1112
1113 return FALSE;
1114 }
1115
1116 m_connected = TRUE;
1117 return TRUE;
1118}
1119
1120bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
1121{
1122 if (m_connected) // Already connected
1123 return TRUE;
1124
1125 if (!m_establishing || !m_socket) // No connection in progress
1126 return FALSE;
1127
1128 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
1129}
1130
1131// ==========================================================================
1132// wxDatagramSocket
1133// ==========================================================================
1134
1135/* NOTE: experimental stuff - might change */
1136
1137wxDatagramSocket::wxDatagramSocket( wxSockAddress& addr, wxSockFlags flags )
1138 : wxSocketBase( flags, SOCK_DATAGRAM )
1139{
1140 // Create the socket
1141 m_socket = GSocket_new();
1142
1143 if(!m_socket)
1144 return;
1145
1146 // Setup the socket as non connection oriented
1147 GSocket_SetLocal(m_socket, addr.GetAddress());
1148 if( GSocket_SetNonOriented(m_socket) != GSOCK_NOERROR )
1149 {
1150 GSocket_destroy(m_socket);
1151 m_socket = NULL;
1152 return;
1153 }
1154
1155 // Initialize all stuff
1156 m_connected = FALSE;
1157 m_establishing = FALSE;
1158 GSocket_SetTimeout( m_socket, m_timeout );
1159 GSocket_SetCallback( m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1160 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1161 wx_socket_callback, (char*)this );
1162
1163}
1164
1165wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
1166 char* buf,
1167 wxUint32 nBytes )
1168{
1169 Read(buf, nBytes);
1170 GetPeer(addr);
1171 return (*this);
1172}
1173
1174wxDatagramSocket& wxDatagramSocket::SendTo( wxSockAddress& addr,
1175 const char* buf,
1176 wxUint32 nBytes )
1177{
1178 GSocket_SetPeer(m_socket, addr.GetAddress());
1179 Write(buf, nBytes);
1180 return (*this);
1181}
1182
1183// ==========================================================================
1184// wxSocketEvent
1185// ==========================================================================
1186
1187// XXX: Should be moved to event.cpp ?
1188
1189wxSocketEvent::wxSocketEvent(int id)
1190 : wxEvent(id)
1191{
1192 wxEventType type = (wxEventType)wxEVT_SOCKET;
1193
1194 SetEventType(type);
1195}
1196
1197void wxSocketEvent::CopyObject(wxObject& obj_d) const
1198{
1199 wxSocketEvent *event = (wxSocketEvent *)&obj_d;
1200
1201 wxEvent::CopyObject(obj_d);
1202
1203 event->m_skevt = m_skevt;
1204 event->m_socket = m_socket;
1205}
1206
1207// ==========================================================================
1208// wxSocketModule
1209// ==========================================================================
1210
1211class WXDLLEXPORT wxSocketModule: public wxModule
1212{
1213 DECLARE_DYNAMIC_CLASS(wxSocketModule)
1214
1215public:
1216 bool OnInit() { return GSocket_Init(); }
1217 void OnExit() { GSocket_Cleanup(); }
1218};
1219
1220IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1221
1222#endif
1223 // wxUSE_SOCKETS