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