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