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