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