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