]> git.saurik.com Git - wxWidgets.git/blob - src/common/socket.cpp
GSocket:
[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, long milliseconds,
639 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). Also, if just polling, do not yield.
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 else
713 PROCESS_EVENTS();
714 }
715
716 timer.Stop();
717 return FALSE;
718 }
719
720 bool 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
728 bool 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
737 bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
738 {
739 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
740 }
741
742 bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
743 {
744 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
745 }
746
747 void 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
759 void wxSocketBase::SetFlags(wxSockFlags _flags)
760 {
761 m_flags = _flags;
762 }
763
764 // --------------------------------------------------------------
765 // wxSocketBase callback management
766 // --------------------------------------------------------------
767
768 wxSocketBase::wxSockCbk wxSocketBase::Callback(wxSockCbk cbk_)
769 {
770 wxSockCbk old_cbk = cbk_;
771
772 m_cbk = cbk_;
773 return old_cbk;
774 }
775
776 char *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
792 static 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
800 wxSocketEventFlags 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
812 void wxSocketBase::SetNotify(wxSocketEventFlags flags)
813 {
814 m_neededreq = flags;
815 }
816
817 void wxSocketBase::Notify(bool notify)
818 {
819 m_notify_state = notify;
820 }
821
822 void wxSocketBase::OnRequest(wxSocketNotify req_evt)
823 {
824 wxSocketEvent event(m_id);
825 wxSocketEventFlags flag = EventToNotify(req_evt);
826
827 // dbg("Entering OnRequest (evt %d)\n", req_evt);
828
829 switch (req_evt)
830 {
831 // This duplicates some code in _Wait(), but this doesn't
832 // hurt. It has to be here because we don't know whether
833 // WaitXXX will be used, and it has to be in _Wait as well
834 // because the event might be a bit delayed.
835 //
836 case wxSOCKET_CONNECTION :
837 m_establishing = FALSE;
838 m_connected = TRUE;
839 break;
840 case wxSOCKET_LOST:
841 Close();
842 break;
843
844 // If we are in the middle of a R/W operation, do not
845 // propagate events to users. Also, filter 'late' events
846 // which are no longer valid.
847 //
848 case wxSOCKET_INPUT:
849 if (m_reading || !GSocket_Select(m_socket, GSOCK_INPUT_FLAG))
850 return;
851 else
852 break;
853
854 case wxSOCKET_OUTPUT:
855 if (m_writing || !GSocket_Select(m_socket, GSOCK_OUTPUT_FLAG))
856 return;
857 else
858 break;
859 }
860
861 if (((m_neededreq & flag) == flag) && m_notify_state)
862 {
863 // dbg("Evt %d delivered\n", req_evt);
864 event.m_socket = this;
865 event.m_skevt = req_evt;
866
867 if (m_evt_handler)
868 #if EXPERIMENTAL_USE_POST
869 wxPostEvent(m_evt_handler, event);
870 #else
871 ProcessEvent(event);
872 #endif
873
874 OldOnNotify(req_evt);
875 if (m_cbk)
876 m_cbk(*this, req_evt, m_cdata);
877
878 }
879
880 // dbg("Exiting OnRequest (evt %d)\n", req_evt);
881 }
882
883 void wxSocketBase::OldOnNotify(wxSocketNotify WXUNUSED(evt))
884 {
885 }
886
887 // --------------------------------------------------------------
888 // wxSocketBase set event handler
889 // --------------------------------------------------------------
890
891 void wxSocketBase::SetEventHandler(wxEvtHandler& h_evt, int id)
892 {
893 m_evt_handler = &h_evt;
894 m_id = id;
895
896 SetNextHandler(&h_evt);
897 }
898
899 // --------------------------------------------------------------
900 // wxSocketBase pushback
901 // --------------------------------------------------------------
902
903 void wxSocketBase::Pushback(const char *buffer, wxUint32 size)
904 {
905 if (!size) return;
906
907 if (m_unread == NULL)
908 m_unread = (char *)malloc(size);
909 else
910 {
911 char *tmp;
912
913 tmp = (char *)malloc(m_unrd_size + size);
914 memcpy(tmp+size, m_unread, m_unrd_size);
915 free(m_unread);
916
917 m_unread = tmp;
918 }
919
920 m_unrd_size += size;
921
922 memcpy(m_unread, buffer, size);
923 }
924
925 wxUint32 wxSocketBase::GetPushback(char *buffer, wxUint32 size, bool peek)
926 {
927 if (!m_unrd_size)
928 return 0;
929
930 if (size > (m_unrd_size-m_unrd_cur))
931 size = m_unrd_size-m_unrd_cur;
932
933 memcpy(buffer, (m_unread+m_unrd_cur), size);
934
935 if (!peek)
936 {
937 m_unrd_cur += size;
938 if (m_unrd_size == m_unrd_cur)
939 {
940 free(m_unread);
941 m_unread = NULL;
942 m_unrd_size = 0;
943 m_unrd_cur = 0;
944 }
945 }
946
947 return size;
948 }
949
950 // --------------------------------------------------------------
951 // wxSocketServer
952 // --------------------------------------------------------------
953
954 // --------------------------------------------------------------
955 // wxSocketServer ctor and dtor
956 // --------------------------------------------------------------
957
958 wxSocketServer::wxSocketServer(wxSockAddress& addr_man,
959 wxSockFlags flags) :
960 wxSocketBase(flags, SOCK_SERVER)
961 {
962 // Create the socket
963 m_socket = GSocket_new();
964
965 if (!m_socket)
966 return;
967
968 // Setup the socket as server
969 GSocket_SetLocal(m_socket, addr_man.GetAddress());
970 if (GSocket_SetServer(m_socket) != GSOCK_NOERROR)
971 {
972 GSocket_destroy(m_socket);
973 m_socket = NULL;
974 return;
975 }
976
977 GSocket_SetTimeout(m_socket, m_timeout * 1000);
978 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
979 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
980 wx_socket_callback, (char *)this);
981
982 }
983
984 // --------------------------------------------------------------
985 // wxSocketServer Accept
986 // --------------------------------------------------------------
987
988 bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
989 {
990 GSocket *child_socket;
991
992 if (!m_socket)
993 return FALSE;
994
995 // GRG: If wait == FALSE, then the call should be nonblocking.
996 // When we are finished, we put the socket to blocking mode
997 // again.
998
999 if (!wait)
1000 GSocket_SetNonBlocking(m_socket, TRUE);
1001
1002 child_socket = GSocket_WaitConnection(m_socket);
1003
1004 if (!wait)
1005 GSocket_SetNonBlocking(m_socket, FALSE);
1006
1007 // GRG: this was not being handled!
1008 if (child_socket == NULL)
1009 return FALSE;
1010
1011 sock.m_type = SOCK_INTERNAL;
1012 sock.m_socket = child_socket;
1013 sock.m_connected = TRUE;
1014
1015 GSocket_SetTimeout(sock.m_socket, sock.m_timeout * 1000);
1016 GSocket_SetCallback(sock.m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1017 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1018 wx_socket_callback, (char *)&sock);
1019
1020 return TRUE;
1021 }
1022
1023 wxSocketBase *wxSocketServer::Accept(bool wait)
1024 {
1025 wxSocketBase* sock = new wxSocketBase();
1026
1027 sock->SetFlags((wxSockFlags)m_flags);
1028
1029 if (!AcceptWith(*sock, wait))
1030 return NULL;
1031
1032 return sock;
1033 }
1034
1035 bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
1036 {
1037 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
1038 }
1039
1040 // --------------------------------------------------------------
1041 // wxSocketClient
1042 // --------------------------------------------------------------
1043
1044 // --------------------------------------------------------------
1045 // wxSocketClient ctor and dtor
1046 // --------------------------------------------------------------
1047
1048 wxSocketClient::wxSocketClient(wxSockFlags _flags) :
1049 wxSocketBase(_flags, SOCK_CLIENT)
1050 {
1051 }
1052
1053 wxSocketClient::~wxSocketClient()
1054 {
1055 }
1056
1057 // --------------------------------------------------------------
1058 // wxSocketClient Connect functions
1059 // --------------------------------------------------------------
1060
1061 bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
1062 {
1063 GSocketError err;
1064
1065 if (IsConnected())
1066 Close();
1067
1068 // This should never happen.
1069 if (m_socket)
1070 GSocket_destroy(m_socket);
1071
1072 // Initialize all socket stuff ...
1073 m_socket = GSocket_new();
1074 m_connected = FALSE;
1075 m_establishing = FALSE;
1076
1077 if (!m_socket)
1078 return FALSE;
1079
1080 GSocket_SetTimeout(m_socket, m_timeout * 1000);
1081 GSocket_SetCallback(m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1082 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1083 wx_socket_callback, (char *)this);
1084
1085 // GRG: If wait == FALSE, then the call should be nonblocking.
1086 // When we are finished, we put the socket to blocking mode
1087 // again.
1088
1089 if (!wait)
1090 GSocket_SetNonBlocking(m_socket, TRUE);
1091
1092 GSocket_SetPeer(m_socket, addr_man.GetAddress());
1093 err = GSocket_Connect(m_socket, GSOCK_STREAMED);
1094
1095 if (!wait)
1096 GSocket_SetNonBlocking(m_socket, FALSE);
1097
1098 if (err != GSOCK_NOERROR)
1099 {
1100 if (err == GSOCK_WOULDBLOCK)
1101 m_establishing = TRUE;
1102
1103 return FALSE;
1104 }
1105
1106 m_connected = TRUE;
1107 return TRUE;
1108 }
1109
1110 bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
1111 {
1112 if (m_connected) // Already connected
1113 return TRUE;
1114
1115 if (!m_establishing || !m_socket) // No connection in progress
1116 return FALSE;
1117
1118 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
1119 }
1120
1121 // --------------------------------------------------------------
1122 // wxDatagramSocket
1123 // --------------------------------------------------------------
1124
1125 /* NOTE: experimental stuff - might change */
1126
1127 wxDatagramSocket::wxDatagramSocket( wxSockAddress& addr, wxSockFlags flags )
1128 : wxSocketBase( flags, SOCK_DATAGRAM )
1129 {
1130 // Create the socket
1131 m_socket = GSocket_new();
1132
1133 if(!m_socket)
1134 return;
1135
1136 // Setup the socket as non connection oriented
1137 GSocket_SetLocal(m_socket, addr.GetAddress());
1138 if( GSocket_SetNonOriented(m_socket) != GSOCK_NOERROR )
1139 {
1140 GSocket_destroy(m_socket);
1141 m_socket = NULL;
1142 return;
1143 }
1144
1145 // Initialize all stuff
1146 m_connected = FALSE;
1147 m_establishing = FALSE;
1148 GSocket_SetTimeout( m_socket, m_timeout );
1149 GSocket_SetCallback( m_socket, GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1150 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1151 wx_socket_callback, (char*)this );
1152
1153 }
1154
1155 wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
1156 char* buf,
1157 wxUint32 nBytes )
1158 {
1159 Read(buf, nBytes);
1160 GetPeer(addr);
1161 return (*this);
1162 }
1163
1164 wxDatagramSocket& wxDatagramSocket::SendTo( wxSockAddress& addr,
1165 const char* buf,
1166 wxUint32 nBytes )
1167 {
1168 GSocket_SetPeer(m_socket, addr.GetAddress());
1169 Write(buf, nBytes);
1170 return (*this);
1171 }
1172
1173 // --------------------------------------------------------------
1174 // wxSocketEvent
1175 // --------------------------------------------------------------
1176
1177 wxSocketEvent::wxSocketEvent(int id)
1178 : wxEvent(id)
1179 {
1180 wxEventType type = (wxEventType)wxEVT_SOCKET;
1181
1182 SetEventType(type);
1183 }
1184
1185 void wxSocketEvent::CopyObject(wxObject& obj_d) const
1186 {
1187 wxSocketEvent *event = (wxSocketEvent *)&obj_d;
1188
1189 wxEvent::CopyObject(obj_d);
1190
1191 event->m_skevt = m_skevt;
1192 event->m_socket = m_socket;
1193 }
1194
1195 // --------------------------------------------------------------------------
1196 // wxSocketModule
1197 // --------------------------------------------------------------------------
1198
1199 class WXDLLEXPORT wxSocketModule: public wxModule
1200 {
1201 DECLARE_DYNAMIC_CLASS(wxSocketModule)
1202 public:
1203 bool OnInit()
1204 {
1205 return GSocket_Init();
1206 }
1207 void OnExit()
1208 {
1209 GSocket_Cleanup();
1210 }
1211 };
1212
1213 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1214
1215 #endif
1216 // wxUSE_SOCKETS