]> git.saurik.com Git - wxWidgets.git/blob - src/common/socket.cpp
Use memcpy instead of strcpy.
[wxWidgets.git] / src / common / socket.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/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: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ==========================================================================
13 // Declarations
14 // ==========================================================================
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 #include "wx/app.h"
26 #include "wx/apptrait.h"
27 #include "wx/object.h"
28 #include "wx/string.h"
29 #include "wx/timer.h"
30 #include "wx/utils.h"
31 #include "wx/module.h"
32 #include "wx/log.h"
33 #include "wx/intl.h"
34 #include "wx/event.h"
35
36 #include "wx/sckaddr.h"
37 #include "wx/socket.h"
38 #include "wx/datetime.h"
39
40 // DLL options compatibility check:
41 #include "wx/build.h"
42 WX_CHECK_BUILD_OPTIONS("wxNet")
43
44 // --------------------------------------------------------------------------
45 // macros and constants
46 // --------------------------------------------------------------------------
47
48 // discard buffer
49 #define MAX_DISCARD_SIZE (10 * 1024)
50
51 // what to do within waits: we have 2 cases: from the main thread itself we
52 // have to call wxYield() to let the events (including the GUI events and the
53 // low-level (not wxWidgets) events from GSocket) be processed. From another
54 // thread it is enough to just call wxThread::Yield() which will give away the
55 // rest of our time slice: the explanation is that the events will be processed
56 // by the main thread anyhow, without calling wxYield(), but we don't want to
57 // eat the CPU time uselessly while sitting in the loop waiting for the data
58 #if wxUSE_THREADS
59 #define PROCESS_EVENTS() \
60 { \
61 if ( wxThread::IsMain() ) \
62 wxYield(); \
63 else \
64 wxThread::Yield(); \
65 }
66 #else // !wxUSE_THREADS
67 #define PROCESS_EVENTS() wxYield()
68 #endif // wxUSE_THREADS/!wxUSE_THREADS
69
70 #define wxTRACE_Socket _T("wxSocket")
71
72 // --------------------------------------------------------------------------
73 // wxWin macros
74 // --------------------------------------------------------------------------
75
76 IMPLEMENT_CLASS(wxSocketBase, wxObject)
77 IMPLEMENT_CLASS(wxSocketServer, wxSocketBase)
78 IMPLEMENT_CLASS(wxSocketClient, wxSocketBase)
79 IMPLEMENT_CLASS(wxDatagramSocket, wxSocketBase)
80 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent, wxEvent)
81
82 // --------------------------------------------------------------------------
83 // private classes
84 // --------------------------------------------------------------------------
85
86 class wxSocketState : public wxObject
87 {
88 public:
89 wxSocketFlags m_flags;
90 wxSocketEventFlags m_eventmask;
91 bool m_notify;
92 void *m_clientData;
93
94 public:
95 wxSocketState() : wxObject() {}
96
97 DECLARE_NO_COPY_CLASS(wxSocketState)
98 };
99
100 // ==========================================================================
101 // wxSocketBase
102 // ==========================================================================
103
104 // --------------------------------------------------------------------------
105 // Initialization and shutdown
106 // --------------------------------------------------------------------------
107
108 // FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
109 // to m_countInit with a crit section
110 size_t wxSocketBase::m_countInit = 0;
111
112 bool wxSocketBase::IsInitialized()
113 {
114 return m_countInit > 0;
115 }
116
117 bool wxSocketBase::Initialize()
118 {
119 if ( !m_countInit++ )
120 {
121 /*
122 Details: Initialize() creates a hidden window as a sink for socket
123 events, such as 'read completed'. wxMSW has only one message loop
124 for the main thread. If Initialize is called in a secondary thread,
125 the socket window will be created for the secondary thread, but
126 since there is no message loop on this thread, it will never
127 receive events and all socket operations will time out.
128 BTW, the main thread must not be stopped using sleep or block
129 on a semaphore (a bad idea in any case) or socket operations
130 will time out.
131
132 On the Mac side, Initialize() stores a pointer to the CFRunLoop for
133 the main thread. Because secondary threads do not have run loops,
134 adding event notifications to the "Current" loop would have no
135 effect at all, events would never fire.
136 */
137 wxASSERT_MSG( wxIsMainThread(),
138 wxT("Call wxSocketBase::Initialize() from the main thread first!"));
139
140 wxAppTraits *traits = wxAppConsole::GetInstance() ?
141 wxAppConsole::GetInstance()->GetTraits() : NULL;
142 GSocketGUIFunctionsTable *functions =
143 traits ? traits->GetSocketGUIFunctionsTable() : NULL;
144 GSocket_SetGUIFunctions(functions);
145
146 if ( !GSocket_Init() )
147 {
148 m_countInit--;
149
150 return false;
151 }
152 }
153
154 return true;
155 }
156
157 void wxSocketBase::Shutdown()
158 {
159 // we should be initialized
160 wxASSERT_MSG( m_countInit, _T("extra call to Shutdown()") );
161 if ( --m_countInit == 0 )
162 {
163 GSocket_Cleanup();
164 }
165 }
166
167 // --------------------------------------------------------------------------
168 // Ctor and dtor
169 // --------------------------------------------------------------------------
170
171 void wxSocketBase::Init()
172 {
173 m_socket = NULL;
174 m_type = wxSOCKET_UNINIT;
175
176 // state
177 m_flags = 0;
178 m_connected =
179 m_establishing =
180 m_reading =
181 m_writing =
182 m_error = false;
183 m_lcount = 0;
184 m_timeout = 600;
185 m_beingDeleted = false;
186
187 // pushback buffer
188 m_unread = NULL;
189 m_unrd_size = 0;
190 m_unrd_cur = 0;
191
192 // events
193 m_id = wxID_ANY;
194 m_handler = NULL;
195 m_clientData = NULL;
196 m_notify = false;
197 m_eventmask = 0;
198
199 if ( !IsInitialized() )
200 {
201 // this Initialize() will be undone by wxSocketModule::OnExit(), all the
202 // other calls to it should be matched by a call to Shutdown()
203 Initialize();
204 }
205 }
206
207 wxSocketBase::wxSocketBase()
208 {
209 Init();
210 }
211
212 wxSocketBase::wxSocketBase(wxSocketFlags flags, wxSocketType type)
213 {
214 Init();
215
216 m_flags = flags;
217 m_type = type;
218 }
219
220 wxSocketBase::~wxSocketBase()
221 {
222 // Just in case the app called Destroy() *and* then deleted
223 // the socket immediately: don't leave dangling pointers.
224 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
225 if ( traits )
226 traits->RemoveFromPendingDelete(this);
227
228 // Shutdown and close the socket
229 if (!m_beingDeleted)
230 Close();
231
232 // Destroy the GSocket object
233 if (m_socket)
234 delete m_socket;
235
236 // Free the pushback buffer
237 if (m_unread)
238 free(m_unread);
239 }
240
241 bool wxSocketBase::Destroy()
242 {
243 // Delayed destruction: the socket will be deleted during the next
244 // idle loop iteration. This ensures that all pending events have
245 // been processed.
246 m_beingDeleted = true;
247
248 // Shutdown and close the socket
249 Close();
250
251 // Supress events from now on
252 Notify(false);
253
254 // schedule this object for deletion
255 wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
256 if ( traits )
257 {
258 // let the traits object decide what to do with us
259 traits->ScheduleForDestroy(this);
260 }
261 else // no app or no traits
262 {
263 // in wxBase we might have no app object at all, don't leak memory
264 delete this;
265 }
266
267 return true;
268 }
269
270 // --------------------------------------------------------------------------
271 // Basic IO calls
272 // --------------------------------------------------------------------------
273
274 // The following IO operations update m_error and m_lcount:
275 // {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
276 //
277 // TODO: Should Connect, Accept and AcceptWith update m_error?
278
279 bool wxSocketBase::Close()
280 {
281 // Interrupt pending waits
282 InterruptWait();
283
284 if (m_socket)
285 {
286 // Disable callbacks
287 m_socket->UnsetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
288 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG);
289
290 // Shutdown the connection
291 m_socket->Shutdown();
292 }
293
294 m_connected = false;
295 m_establishing = false;
296 return true;
297 }
298
299 wxSocketBase& wxSocketBase::Read(void* buffer, wxUint32 nbytes)
300 {
301 // Mask read events
302 m_reading = true;
303
304 m_lcount = _Read(buffer, nbytes);
305
306 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
307 if (m_flags & wxSOCKET_WAITALL)
308 m_error = (m_lcount != nbytes);
309 else
310 m_error = (m_lcount == 0);
311
312 // Allow read events from now on
313 m_reading = false;
314
315 return *this;
316 }
317
318 wxUint32 wxSocketBase::_Read(void* buffer, wxUint32 nbytes)
319 {
320 int total;
321
322 // Try the pushback buffer first
323 total = GetPushback(buffer, nbytes, false);
324 nbytes -= total;
325 buffer = (char *)buffer + total;
326
327 // Return now in one of the following cases:
328 // - the socket is invalid,
329 // - we got all the data,
330 // - we got *some* data and we are not using wxSOCKET_WAITALL.
331 if ( !m_socket ||
332 !nbytes ||
333 ((total != 0) && !(m_flags & wxSOCKET_WAITALL)) )
334 return total;
335
336 // Possible combinations (they are checked in this order)
337 // wxSOCKET_NOWAIT
338 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
339 // wxSOCKET_BLOCK
340 // wxSOCKET_NONE
341 //
342 int ret;
343 if (m_flags & wxSOCKET_NOWAIT)
344 {
345 m_socket->SetNonBlocking(1);
346 ret = m_socket->Read((char *)buffer, nbytes);
347 m_socket->SetNonBlocking(0);
348
349 if (ret > 0)
350 total += ret;
351 }
352 else
353 {
354 bool more = true;
355
356 while (more)
357 {
358 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForRead() )
359 break;
360
361 ret = m_socket->Read((char *)buffer, nbytes);
362
363 if (ret > 0)
364 {
365 total += ret;
366 nbytes -= ret;
367 buffer = (char *)buffer + ret;
368 }
369
370 // If we got here and wxSOCKET_WAITALL is not set, we can leave
371 // now. Otherwise, wait until we recv all the data or until there
372 // is an error.
373 //
374 more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
375 }
376 }
377
378 return total;
379 }
380
381 wxSocketBase& wxSocketBase::ReadMsg(void* buffer, wxUint32 nbytes)
382 {
383 wxUint32 len, len2, sig, total;
384 bool error;
385 int old_flags;
386 struct
387 {
388 unsigned char sig[4];
389 unsigned char len[4];
390 } msg;
391
392 // Mask read events
393 m_reading = true;
394
395 total = 0;
396 error = true;
397 old_flags = m_flags;
398 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
399
400 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
401 goto exit;
402
403 sig = (wxUint32)msg.sig[0];
404 sig |= (wxUint32)(msg.sig[1] << 8);
405 sig |= (wxUint32)(msg.sig[2] << 16);
406 sig |= (wxUint32)(msg.sig[3] << 24);
407
408 if (sig != 0xfeeddead)
409 {
410 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
411 goto exit;
412 }
413
414 len = (wxUint32)msg.len[0];
415 len |= (wxUint32)(msg.len[1] << 8);
416 len |= (wxUint32)(msg.len[2] << 16);
417 len |= (wxUint32)(msg.len[3] << 24);
418
419 if (len > nbytes)
420 {
421 len2 = len - nbytes;
422 len = nbytes;
423 }
424 else
425 len2 = 0;
426
427 // Don't attemp to read if the msg was zero bytes long.
428 if (len)
429 {
430 total = _Read(buffer, len);
431
432 if (total != len)
433 goto exit;
434 }
435 if (len2)
436 {
437 char *discard_buffer = new char[MAX_DISCARD_SIZE];
438 long discard_len;
439
440 // NOTE: discarded bytes don't add to m_lcount.
441 do
442 {
443 discard_len = ((len2 > MAX_DISCARD_SIZE)? MAX_DISCARD_SIZE : len2);
444 discard_len = _Read(discard_buffer, (wxUint32)discard_len);
445 len2 -= (wxUint32)discard_len;
446 }
447 while ((discard_len > 0) && len2);
448
449 delete [] discard_buffer;
450
451 if (len2 != 0)
452 goto exit;
453 }
454 if (_Read(&msg, sizeof(msg)) != sizeof(msg))
455 goto exit;
456
457 sig = (wxUint32)msg.sig[0];
458 sig |= (wxUint32)(msg.sig[1] << 8);
459 sig |= (wxUint32)(msg.sig[2] << 16);
460 sig |= (wxUint32)(msg.sig[3] << 24);
461
462 if (sig != 0xdeadfeed)
463 {
464 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
465 goto exit;
466 }
467
468 // everything was OK
469 error = false;
470
471 exit:
472 m_error = error;
473 m_lcount = total;
474 m_reading = false;
475 SetFlags(old_flags);
476
477 return *this;
478 }
479
480 wxSocketBase& wxSocketBase::Peek(void* buffer, wxUint32 nbytes)
481 {
482 // Mask read events
483 m_reading = true;
484
485 m_lcount = _Read(buffer, nbytes);
486 Pushback(buffer, m_lcount);
487
488 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
489 if (m_flags & wxSOCKET_WAITALL)
490 m_error = (m_lcount != nbytes);
491 else
492 m_error = (m_lcount == 0);
493
494 // Allow read events again
495 m_reading = false;
496
497 return *this;
498 }
499
500 wxSocketBase& wxSocketBase::Write(const void *buffer, wxUint32 nbytes)
501 {
502 // Mask write events
503 m_writing = true;
504
505 m_lcount = _Write(buffer, nbytes);
506
507 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
508 if (m_flags & wxSOCKET_WAITALL)
509 m_error = (m_lcount != nbytes);
510 else
511 m_error = (m_lcount == 0);
512
513 // Allow write events again
514 m_writing = false;
515
516 return *this;
517 }
518
519 wxUint32 wxSocketBase::_Write(const void *buffer, wxUint32 nbytes)
520 {
521 wxUint32 total = 0;
522
523 // If the socket is invalid or parameters are ill, return immediately
524 if (!m_socket || !buffer || !nbytes)
525 return 0;
526
527 // Possible combinations (they are checked in this order)
528 // wxSOCKET_NOWAIT
529 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
530 // wxSOCKET_BLOCK
531 // wxSOCKET_NONE
532 //
533 int ret;
534 if (m_flags & wxSOCKET_NOWAIT)
535 {
536 m_socket->SetNonBlocking(1);
537 ret = m_socket->Write((const char *)buffer, nbytes);
538 m_socket->SetNonBlocking(0);
539
540 if (ret > 0)
541 total = ret;
542 }
543 else
544 {
545 bool more = true;
546
547 while (more)
548 {
549 if ( !(m_flags & wxSOCKET_BLOCK) && !WaitForWrite() )
550 break;
551
552 ret = m_socket->Write((const char *)buffer, nbytes);
553
554 if (ret > 0)
555 {
556 total += ret;
557 nbytes -= ret;
558 buffer = (const char *)buffer + ret;
559 }
560
561 // If we got here and wxSOCKET_WAITALL is not set, we can leave
562 // now. Otherwise, wait until we send all the data or until there
563 // is an error.
564 //
565 more = (ret > 0 && nbytes > 0 && (m_flags & wxSOCKET_WAITALL));
566 }
567 }
568
569 return total;
570 }
571
572 wxSocketBase& wxSocketBase::WriteMsg(const void *buffer, wxUint32 nbytes)
573 {
574 wxUint32 total;
575 bool error;
576 struct
577 {
578 unsigned char sig[4];
579 unsigned char len[4];
580 } msg;
581
582 // Mask write events
583 m_writing = true;
584
585 error = true;
586 total = 0;
587 SetFlags((m_flags & wxSOCKET_BLOCK) | wxSOCKET_WAITALL);
588
589 msg.sig[0] = (unsigned char) 0xad;
590 msg.sig[1] = (unsigned char) 0xde;
591 msg.sig[2] = (unsigned char) 0xed;
592 msg.sig[3] = (unsigned char) 0xfe;
593
594 msg.len[0] = (unsigned char) (nbytes & 0xff);
595 msg.len[1] = (unsigned char) ((nbytes >> 8) & 0xff);
596 msg.len[2] = (unsigned char) ((nbytes >> 16) & 0xff);
597 msg.len[3] = (unsigned char) ((nbytes >> 24) & 0xff);
598
599 if (_Write(&msg, sizeof(msg)) < sizeof(msg))
600 goto exit;
601
602 total = _Write(buffer, nbytes);
603
604 if (total < nbytes)
605 goto exit;
606
607 msg.sig[0] = (unsigned char) 0xed;
608 msg.sig[1] = (unsigned char) 0xfe;
609 msg.sig[2] = (unsigned char) 0xad;
610 msg.sig[3] = (unsigned char) 0xde;
611 msg.len[0] = msg.len[1] = msg.len[2] = msg.len[3] = (char) 0;
612
613 if ((_Write(&msg, sizeof(msg))) < sizeof(msg))
614 goto exit;
615
616 // everything was OK
617 error = false;
618
619 exit:
620 m_error = error;
621 m_lcount = total;
622 m_writing = false;
623
624 return *this;
625 }
626
627 wxSocketBase& wxSocketBase::Unread(const void *buffer, wxUint32 nbytes)
628 {
629 if (nbytes != 0)
630 Pushback(buffer, nbytes);
631
632 m_error = false;
633 m_lcount = nbytes;
634
635 return *this;
636 }
637
638 wxSocketBase& wxSocketBase::Discard()
639 {
640 char *buffer = new char[MAX_DISCARD_SIZE];
641 wxUint32 ret;
642 wxUint32 total = 0;
643
644 // Mask read events
645 m_reading = true;
646
647 SetFlags(wxSOCKET_NOWAIT);
648
649 do
650 {
651 ret = _Read(buffer, MAX_DISCARD_SIZE);
652 total += ret;
653 }
654 while (ret == MAX_DISCARD_SIZE);
655
656 delete[] buffer;
657 m_lcount = total;
658 m_error = false;
659
660 // Allow read events again
661 m_reading = false;
662
663 return *this;
664 }
665
666 // --------------------------------------------------------------------------
667 // Wait functions
668 // --------------------------------------------------------------------------
669
670 // All Wait functions poll the socket using GSocket_Select() to
671 // check for the specified combination of conditions, until one
672 // of these conditions become true, an error occurs, or the
673 // timeout elapses. The polling loop calls PROCESS_EVENTS(), so
674 // this won't block the GUI.
675
676 bool wxSocketBase::_Wait(long seconds,
677 long milliseconds,
678 wxSocketEventFlags flags)
679 {
680 GSocketEventFlags result;
681 long timeout;
682
683 // Set this to true to interrupt ongoing waits
684 m_interrupt = false;
685
686 // Check for valid socket
687 if (!m_socket)
688 return false;
689
690 // Check for valid timeout value.
691 if (seconds != -1)
692 timeout = seconds * 1000 + milliseconds;
693 else
694 timeout = m_timeout * 1000;
695
696 bool has_event_loop = wxTheApp ? (wxTheApp->GetTraits() ? true : false) : false;
697
698 // Wait in an active polling loop.
699 //
700 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
701 // hurt. It has to be here because the (GSocket) event might arrive
702 // a bit delayed, and it has to be in OnRequest as well because we
703 // don't know whether the Wait functions are being used.
704 //
705 // Do this at least once (important if timeout == 0, when
706 // we are just polling). Also, if just polling, do not yield.
707
708 wxDateTime current_time = wxDateTime::UNow();
709 unsigned int time_limit = (current_time.GetTicks() * 1000) + current_time.GetMillisecond() + timeout;
710 bool done = false;
711 bool valid_result = false;
712
713 if (!has_event_loop)
714 {
715 // This is used to avoid a busy loop on wxBase - having a select
716 // timeout of 50 ms per iteration should be enough.
717 if (timeout > 50)
718 m_socket->SetTimeout(50);
719 else
720 m_socket->SetTimeout(timeout);
721 }
722
723 while (!done)
724 {
725 result = m_socket->Select(flags | GSOCK_LOST_FLAG);
726
727 // Incoming connection (server) or connection established (client)
728 if (result & GSOCK_CONNECTION_FLAG)
729 {
730 m_connected = true;
731 m_establishing = false;
732 valid_result = true;
733 break;
734 }
735
736 // Data available or output buffer ready
737 if ((result & GSOCK_INPUT_FLAG) || (result & GSOCK_OUTPUT_FLAG))
738 {
739 valid_result = true;
740 break;
741 }
742
743 // Connection lost
744 if (result & GSOCK_LOST_FLAG)
745 {
746 m_connected = false;
747 m_establishing = false;
748 valid_result = ((flags & GSOCK_LOST_FLAG) != 0);
749 break;
750 }
751
752 // Wait more?
753 current_time = wxDateTime::UNow();
754 int time_left = time_limit - ((current_time.GetTicks() * 1000) + current_time.GetMillisecond());
755 if ((!timeout) || (time_left <= 0) || (m_interrupt))
756 done = true;
757 else
758 {
759 if (has_event_loop)
760 {
761 PROCESS_EVENTS();
762 }
763 else
764 {
765 // If there's less than 50 ms left, just call select with that timeout.
766 if (time_left < 50)
767 m_socket->SetTimeout(time_left);
768 }
769 }
770 }
771
772 // Set timeout back to original value (we overwrote it for polling)
773 if (!has_event_loop)
774 m_socket->SetTimeout(m_timeout*1000);
775
776 return valid_result;
777 }
778
779 bool wxSocketBase::Wait(long seconds, long milliseconds)
780 {
781 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
782 GSOCK_OUTPUT_FLAG |
783 GSOCK_CONNECTION_FLAG |
784 GSOCK_LOST_FLAG);
785 }
786
787 bool wxSocketBase::WaitForRead(long seconds, long milliseconds)
788 {
789 // Check pushback buffer before entering _Wait
790 if (m_unread)
791 return true;
792
793 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
794 // _Wait because of the semantics of WaitForRead: a return
795 // value of true means that a GSocket_Read call will return
796 // immediately, not that there is actually data to read.
797
798 return _Wait(seconds, milliseconds, GSOCK_INPUT_FLAG |
799 GSOCK_LOST_FLAG);
800 }
801
802
803 bool wxSocketBase::WaitForWrite(long seconds, long milliseconds)
804 {
805 return _Wait(seconds, milliseconds, GSOCK_OUTPUT_FLAG);
806 }
807
808 bool wxSocketBase::WaitForLost(long seconds, long milliseconds)
809 {
810 return _Wait(seconds, milliseconds, GSOCK_LOST_FLAG);
811 }
812
813 // --------------------------------------------------------------------------
814 // Miscellaneous
815 // --------------------------------------------------------------------------
816
817 //
818 // Get local or peer address
819 //
820
821 bool wxSocketBase::GetPeer(wxSockAddress& addr_man) const
822 {
823 GAddress *peer;
824
825 if (!m_socket)
826 return false;
827
828 peer = m_socket->GetPeer();
829
830 // copying a null address would just trigger an assert anyway
831
832 if (!peer)
833 return false;
834
835 addr_man.SetAddress(peer);
836 GAddress_destroy(peer);
837
838 return true;
839 }
840
841 bool wxSocketBase::GetLocal(wxSockAddress& addr_man) const
842 {
843 GAddress *local;
844
845 if (!m_socket)
846 return false;
847
848 local = m_socket->GetLocal();
849 addr_man.SetAddress(local);
850 GAddress_destroy(local);
851
852 return true;
853 }
854
855 //
856 // Save and restore socket state
857 //
858
859 void wxSocketBase::SaveState()
860 {
861 wxSocketState *state;
862
863 state = new wxSocketState();
864
865 state->m_flags = m_flags;
866 state->m_notify = m_notify;
867 state->m_eventmask = m_eventmask;
868 state->m_clientData = m_clientData;
869
870 m_states.Append(state);
871 }
872
873 void wxSocketBase::RestoreState()
874 {
875 wxList::compatibility_iterator node;
876 wxSocketState *state;
877
878 node = m_states.GetLast();
879 if (!node)
880 return;
881
882 state = (wxSocketState *)node->GetData();
883
884 m_flags = state->m_flags;
885 m_notify = state->m_notify;
886 m_eventmask = state->m_eventmask;
887 m_clientData = state->m_clientData;
888
889 m_states.Erase(node);
890 delete state;
891 }
892
893 //
894 // Timeout and flags
895 //
896
897 void wxSocketBase::SetTimeout(long seconds)
898 {
899 m_timeout = seconds;
900
901 if (m_socket)
902 m_socket->SetTimeout(m_timeout * 1000);
903 }
904
905 void wxSocketBase::SetFlags(wxSocketFlags flags)
906 {
907 m_flags = flags;
908 }
909
910
911 // --------------------------------------------------------------------------
912 // Event handling
913 // --------------------------------------------------------------------------
914
915 // A note on how events are processed, which is probably the most
916 // difficult thing to get working right while keeping the same API
917 // and functionality for all platforms.
918 //
919 // When GSocket detects an event, it calls wx_socket_callback, which in
920 // turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
921 // object. OnRequest does some housekeeping, and if the event is to be
922 // propagated to the user, it creates a new wxSocketEvent object and
923 // posts it. The event is not processed immediately, but delayed with
924 // AddPendingEvent instead. This is necessary in order to decouple the
925 // event processing from wx_socket_callback; otherwise, subsequent IO
926 // calls made from the user event handler would fail, as gtk callbacks
927 // are not reentrant.
928 //
929 // Note that, unlike events, user callbacks (now deprecated) are _not_
930 // decoupled from wx_socket_callback and thus they suffer from a variety
931 // of problems. Avoid them where possible and use events instead.
932
933 extern "C"
934 void LINKAGEMODE wx_socket_callback(GSocket * WXUNUSED(socket),
935 GSocketEvent notification,
936 char *cdata)
937 {
938 wxSocketBase *sckobj = (wxSocketBase *)cdata;
939
940 sckobj->OnRequest((wxSocketNotify) notification);
941 }
942
943 void wxSocketBase::OnRequest(wxSocketNotify notification)
944 {
945 // NOTE: We duplicate some of the code in _Wait, but this doesn't
946 // hurt. It has to be here because the (GSocket) event might arrive
947 // a bit delayed, and it has to be in _Wait as well because we don't
948 // know whether the Wait functions are being used.
949
950 switch(notification)
951 {
952 case wxSOCKET_CONNECTION:
953 m_establishing = false;
954 m_connected = true;
955 break;
956
957 // If we are in the middle of a R/W operation, do not
958 // propagate events to users. Also, filter 'late' events
959 // which are no longer valid.
960
961 case wxSOCKET_INPUT:
962 if (m_reading || !m_socket->Select(GSOCK_INPUT_FLAG))
963 return;
964 break;
965
966 case wxSOCKET_OUTPUT:
967 if (m_writing || !m_socket->Select(GSOCK_OUTPUT_FLAG))
968 return;
969 break;
970
971 case wxSOCKET_LOST:
972 m_connected = false;
973 m_establishing = false;
974 break;
975
976 default:
977 break;
978 }
979
980 // Schedule the event
981
982 wxSocketEventFlags flag = 0;
983 wxUnusedVar(flag);
984 switch (notification)
985 {
986 case GSOCK_INPUT: flag = GSOCK_INPUT_FLAG; break;
987 case GSOCK_OUTPUT: flag = GSOCK_OUTPUT_FLAG; break;
988 case GSOCK_CONNECTION: flag = GSOCK_CONNECTION_FLAG; break;
989 case GSOCK_LOST: flag = GSOCK_LOST_FLAG; break;
990 default:
991 wxLogWarning(_("wxSocket: unknown event!."));
992 return;
993 }
994
995 if (((m_eventmask & flag) == flag) && m_notify)
996 {
997 if (m_handler)
998 {
999 wxSocketEvent event(m_id);
1000 event.m_event = notification;
1001 event.m_clientData = m_clientData;
1002 event.SetEventObject(this);
1003
1004 m_handler->AddPendingEvent(event);
1005 }
1006 }
1007 }
1008
1009 void wxSocketBase::Notify(bool notify)
1010 {
1011 m_notify = notify;
1012 }
1013
1014 void wxSocketBase::SetNotify(wxSocketEventFlags flags)
1015 {
1016 m_eventmask = flags;
1017 }
1018
1019 void wxSocketBase::SetEventHandler(wxEvtHandler& handler, int id)
1020 {
1021 m_handler = &handler;
1022 m_id = id;
1023 }
1024
1025 // --------------------------------------------------------------------------
1026 // Pushback buffer
1027 // --------------------------------------------------------------------------
1028
1029 void wxSocketBase::Pushback(const void *buffer, wxUint32 size)
1030 {
1031 if (!size) return;
1032
1033 if (m_unread == NULL)
1034 m_unread = malloc(size);
1035 else
1036 {
1037 void *tmp;
1038
1039 tmp = malloc(m_unrd_size + size);
1040 memcpy((char *)tmp + size, m_unread, m_unrd_size);
1041 free(m_unread);
1042
1043 m_unread = tmp;
1044 }
1045
1046 m_unrd_size += size;
1047
1048 memcpy(m_unread, buffer, size);
1049 }
1050
1051 wxUint32 wxSocketBase::GetPushback(void *buffer, wxUint32 size, bool peek)
1052 {
1053 if (!m_unrd_size)
1054 return 0;
1055
1056 if (size > (m_unrd_size-m_unrd_cur))
1057 size = m_unrd_size-m_unrd_cur;
1058
1059 memcpy(buffer, (char *)m_unread + m_unrd_cur, size);
1060
1061 if (!peek)
1062 {
1063 m_unrd_cur += size;
1064 if (m_unrd_size == m_unrd_cur)
1065 {
1066 free(m_unread);
1067 m_unread = NULL;
1068 m_unrd_size = 0;
1069 m_unrd_cur = 0;
1070 }
1071 }
1072
1073 return size;
1074 }
1075
1076
1077 // ==========================================================================
1078 // wxSocketServer
1079 // ==========================================================================
1080
1081 // --------------------------------------------------------------------------
1082 // Ctor
1083 // --------------------------------------------------------------------------
1084
1085 wxSocketServer::wxSocketServer(const wxSockAddress& addr_man,
1086 wxSocketFlags flags)
1087 : wxSocketBase(flags, wxSOCKET_SERVER)
1088 {
1089 wxLogTrace( wxTRACE_Socket, _T("Opening wxSocketServer") );
1090
1091 m_socket = GSocket_new();
1092
1093 if (!m_socket)
1094 {
1095 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_new failed") );
1096 return;
1097 }
1098
1099 // Setup the socket as server
1100
1101 m_socket->SetLocal(addr_man.GetAddress());
1102
1103 if (GetFlags() & wxSOCKET_REUSEADDR) {
1104 m_socket->SetReusable();
1105 }
1106
1107 if (m_socket->SetServer() != GSOCK_NOERROR)
1108 {
1109 delete m_socket;
1110 m_socket = NULL;
1111
1112 wxLogTrace( wxTRACE_Socket, _T("*** GSocket_SetServer failed") );
1113 return;
1114 }
1115
1116 m_socket->SetTimeout(m_timeout * 1000);
1117 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1118 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1119 wx_socket_callback, (char *)this);
1120 }
1121
1122 // --------------------------------------------------------------------------
1123 // Accept
1124 // --------------------------------------------------------------------------
1125
1126 bool wxSocketServer::AcceptWith(wxSocketBase& sock, bool wait)
1127 {
1128 GSocket *child_socket;
1129
1130 if (!m_socket)
1131 return false;
1132
1133 // If wait == false, then the call should be nonblocking.
1134 // When we are finished, we put the socket to blocking mode
1135 // again.
1136
1137 if (!wait)
1138 m_socket->SetNonBlocking(1);
1139
1140 child_socket = m_socket->WaitConnection();
1141
1142 if (!wait)
1143 m_socket->SetNonBlocking(0);
1144
1145 if (!child_socket)
1146 return false;
1147
1148 sock.m_type = wxSOCKET_BASE;
1149 sock.m_socket = child_socket;
1150 sock.m_connected = true;
1151
1152 sock.m_socket->SetTimeout(sock.m_timeout * 1000);
1153 sock.m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1154 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1155 wx_socket_callback, (char *)&sock);
1156
1157 return true;
1158 }
1159
1160 wxSocketBase *wxSocketServer::Accept(bool wait)
1161 {
1162 wxSocketBase* sock = new wxSocketBase();
1163
1164 sock->SetFlags(m_flags);
1165
1166 if (!AcceptWith(*sock, wait))
1167 {
1168 sock->Destroy();
1169 sock = NULL;
1170 }
1171
1172 return sock;
1173 }
1174
1175 bool wxSocketServer::WaitForAccept(long seconds, long milliseconds)
1176 {
1177 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG);
1178 }
1179
1180 bool wxSocketBase::GetOption(int level, int optname, void *optval, int *optlen)
1181 {
1182 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1183
1184 if (m_socket->GetSockOpt(level, optname, optval, optlen)
1185 != GSOCK_NOERROR)
1186 {
1187 return false;
1188 }
1189 return true;
1190 }
1191
1192 bool wxSocketBase::SetOption(int level, int optname, const void *optval,
1193 int optlen)
1194 {
1195 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1196
1197 if (m_socket->SetSockOpt(level, optname, optval, optlen)
1198 != GSOCK_NOERROR)
1199 {
1200 return false;
1201 }
1202 return true;
1203 }
1204
1205 bool wxSocketBase::SetLocal(wxIPV4address& local)
1206 {
1207 GAddress* la = local.GetAddress();
1208
1209 // If the address is valid, save it for use when we call Connect
1210 if (la && la->m_addr)
1211 {
1212 m_localAddress = local;
1213
1214 return true;
1215 }
1216
1217 return false;
1218 }
1219
1220 // ==========================================================================
1221 // wxSocketClient
1222 // ==========================================================================
1223
1224 // --------------------------------------------------------------------------
1225 // Ctor and dtor
1226 // --------------------------------------------------------------------------
1227
1228 wxSocketClient::wxSocketClient(wxSocketFlags flags)
1229 : wxSocketBase(flags, wxSOCKET_CLIENT)
1230 {
1231 }
1232
1233 wxSocketClient::~wxSocketClient()
1234 {
1235 }
1236
1237 // --------------------------------------------------------------------------
1238 // Connect
1239 // --------------------------------------------------------------------------
1240
1241 bool wxSocketClient::DoConnect(wxSockAddress& addr_man, wxSockAddress* local, bool wait)
1242 {
1243 GSocketError err;
1244
1245 if (m_socket)
1246 {
1247 // Shutdown and destroy the socket
1248 Close();
1249 delete m_socket;
1250 }
1251
1252 m_socket = GSocket_new();
1253 m_connected = false;
1254 m_establishing = false;
1255
1256 if (!m_socket)
1257 return false;
1258
1259 m_socket->SetTimeout(m_timeout * 1000);
1260 m_socket->SetCallback(GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1261 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1262 wx_socket_callback, (char *)this);
1263
1264 // If wait == false, then the call should be nonblocking.
1265 // When we are finished, we put the socket to blocking mode
1266 // again.
1267
1268 if (!wait)
1269 m_socket->SetNonBlocking(1);
1270
1271 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1272 if (GetFlags() & wxSOCKET_REUSEADDR)
1273 {
1274 m_socket->SetReusable();
1275 }
1276
1277 // If no local address was passed and one has been set, use the one that was Set
1278 if (!local && m_localAddress.GetAddress())
1279 {
1280 local = &m_localAddress;
1281 }
1282
1283 // Bind to the local IP address and port, when provided
1284 if (local)
1285 {
1286 GAddress* la = local->GetAddress();
1287
1288 if (la && la->m_addr)
1289 m_socket->SetLocal(la);
1290 }
1291
1292 m_socket->SetPeer(addr_man.GetAddress());
1293 err = m_socket->Connect(GSOCK_STREAMED);
1294
1295 if (!wait)
1296 m_socket->SetNonBlocking(0);
1297
1298 if (err != GSOCK_NOERROR)
1299 {
1300 if (err == GSOCK_WOULDBLOCK)
1301 m_establishing = true;
1302
1303 return false;
1304 }
1305
1306 m_connected = true;
1307 return true;
1308 }
1309
1310 bool wxSocketClient::Connect(wxSockAddress& addr_man, bool wait)
1311 {
1312 return (DoConnect(addr_man, NULL, wait));
1313 }
1314
1315 bool wxSocketClient::Connect(wxSockAddress& addr_man, wxSockAddress& local, bool wait)
1316 {
1317 return (DoConnect(addr_man, &local, wait));
1318 }
1319
1320 bool wxSocketClient::WaitOnConnect(long seconds, long milliseconds)
1321 {
1322 if (m_connected) // Already connected
1323 return true;
1324
1325 if (!m_establishing || !m_socket) // No connection in progress
1326 return false;
1327
1328 return _Wait(seconds, milliseconds, GSOCK_CONNECTION_FLAG |
1329 GSOCK_LOST_FLAG);
1330 }
1331
1332 // ==========================================================================
1333 // wxDatagramSocket
1334 // ==========================================================================
1335
1336 /* NOTE: experimental stuff - might change */
1337
1338 wxDatagramSocket::wxDatagramSocket( const wxSockAddress& addr,
1339 wxSocketFlags flags )
1340 : wxSocketBase( flags, wxSOCKET_DATAGRAM )
1341 {
1342 // Create the socket
1343 m_socket = GSocket_new();
1344
1345 if(!m_socket)
1346 {
1347 wxFAIL_MSG( _T("datagram socket not new'd") );
1348 return;
1349 }
1350 // Setup the socket as non connection oriented
1351 m_socket->SetLocal(addr.GetAddress());
1352 if( m_socket->SetNonOriented() != GSOCK_NOERROR )
1353 {
1354 delete m_socket;
1355 m_socket = NULL;
1356 return;
1357 }
1358
1359 // Initialize all stuff
1360 m_connected = false;
1361 m_establishing = false;
1362 m_socket->SetTimeout( m_timeout );
1363 m_socket->SetCallback( GSOCK_INPUT_FLAG | GSOCK_OUTPUT_FLAG |
1364 GSOCK_LOST_FLAG | GSOCK_CONNECTION_FLAG,
1365 wx_socket_callback, (char*)this );
1366 }
1367
1368 wxDatagramSocket& wxDatagramSocket::RecvFrom( wxSockAddress& addr,
1369 void* buf,
1370 wxUint32 nBytes )
1371 {
1372 Read(buf, nBytes);
1373 GetPeer(addr);
1374 return (*this);
1375 }
1376
1377 wxDatagramSocket& wxDatagramSocket::SendTo( const wxSockAddress& addr,
1378 const void* buf,
1379 wxUint32 nBytes )
1380 {
1381 wxASSERT_MSG( m_socket, _T("Socket not initialised") );
1382
1383 m_socket->SetPeer(addr.GetAddress());
1384 Write(buf, nBytes);
1385 return (*this);
1386 }
1387
1388 // ==========================================================================
1389 // wxSocketModule
1390 // ==========================================================================
1391
1392 class wxSocketModule : public wxModule
1393 {
1394 public:
1395 virtual bool OnInit()
1396 {
1397 // wxSocketBase will call GSocket_Init() itself when/if needed
1398 return true;
1399 }
1400
1401 virtual void OnExit()
1402 {
1403 if ( wxSocketBase::IsInitialized() )
1404 wxSocketBase::Shutdown();
1405 }
1406
1407 private:
1408 DECLARE_DYNAMIC_CLASS(wxSocketModule)
1409 };
1410
1411 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule, wxModule)
1412
1413 #endif
1414 // wxUSE_SOCKETS