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