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