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