]> git.saurik.com Git - wxWidgets.git/blob - src/common/socket.cpp
wxSocekt now uses wxPostEvent.
[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 // 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
61 IMPLEMENT_CLASS(wxSocketBase, wxObject)
62 IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
63 IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
64 IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
65 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
66
67 class wxSocketState : public wxObject
68 {
69 public:
70 bool m_notify_state;
71 GSocketEventFlags m_neededreq;
72 wxSockFlags m_flags;
73 wxSocketBase::wxSockCbk m_cbk;
74 char *m_cdata;
75
76 public:
77 wxSocketState() : wxObject() {}
78 };
79
80 // --------------------------------------------------------------
81 // wxSocketBase ctor and dtor
82 // --------------------------------------------------------------
83
84 wxSocketBase::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
97 wxSocketBase::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
110 wxSocketBase::~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
123 bool 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
152 class _wxSocketInternalTimer: public wxTimer
153 {
154 public:
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
164 wxSocketBase& 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
183 wxUint32 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
245 wxSocketBase& 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
339 exit:
340 m_error = error;
341 m_lcount = total;
342 m_reading = FALSE;
343 SetFlags(old_flags);
344
345 return *this;
346 }
347
348 wxSocketBase& 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
368 wxSocketBase& 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
387 wxUint32 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
442 wxSocketBase& 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
503 exit:
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
515 wxSocketBase& 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
526 wxSocketBase& 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
559 bool 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
573 bool 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
591 void 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
606 void 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
639 bool 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
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 // 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
877 void wxSocketBase::OldOnNotify(wxSocketNotify WXUNUSED(evt))
878 {
879 }
880
881 // --------------------------------------------------------------
882 // wxSocketBase set event handler
883 // --------------------------------------------------------------
884
885 void 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
897 void 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
919 wxUint32 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
952 wxSocketServer::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
982 bool 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
1017 wxSocketBase *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
1029 bool 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
1042 wxSocketClient::wxSocketClient(wxSockFlags _flags) :
1043 wxSocketBase(_flags, SOCK_CLIENT)
1044 {
1045 }
1046
1047 wxSocketClient::~wxSocketClient()
1048 {
1049 }
1050
1051 // --------------------------------------------------------------
1052 // wxSocketClient Connect functions
1053 // --------------------------------------------------------------
1054
1055 bool 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
1104 bool 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
1121 wxDatagramSocket::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
1149 wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
1150 char* buf,
1151 wxUint32 nBytes )
1152 {
1153 Read(buf, nBytes);
1154 GetPeer(addr);
1155 return (*this);
1156 }
1157
1158 wxDatagramSocket& 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
1171 wxSocketEvent::wxSocketEvent(int id)
1172 : wxEvent(id)
1173 {
1174 wxEventType type = (wxEventType)wxEVT_SOCKET;
1175
1176 SetEventType(type);
1177 }
1178
1179 void 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
1193 class WXDLLEXPORT wxSocketModule: public wxModule
1194 {
1195 DECLARE_DYNAMIC_CLASS(wxSocketModule)
1196 public:
1197 bool OnInit()
1198 {
1199 return GSocket_Init();
1200 }
1201 void OnExit()
1202 {
1203 GSocket_Cleanup();
1204 }
1205 };
1206
1207 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1208
1209 #endif
1210 // wxUSE_SOCKETS