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