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