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