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