1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/socket.cpp
3 // Purpose: Socket handler classes
4 // Authors: Guilhem Lavaux, Guillermo Rodriguez Garcia
6 // Copyright: (C) 1999-1997, Guilhem Lavaux
7 // (C) 1999-2000, Guillermo Rodriguez Garcia
8 // (C) 2008 Vadim Zeitlin
10 // License: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // ==========================================================================
15 // ==========================================================================
17 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/wxprec.h"
26 #include "wx/socket.h"
29 #include "wx/object.h"
30 #include "wx/string.h"
37 #include "wx/module.h"
40 #include "wx/apptrait.h"
41 #include "wx/sckaddr.h"
42 #include "wx/stopwatch.h"
43 #include "wx/thread.h"
44 #include "wx/evtloop.h"
47 #include "wx/private/fd.h"
48 #include "wx/private/socket.h"
54 // we use MSG_NOSIGNAL to avoid getting SIGPIPE when sending data to a remote
55 // host which closed the connection if it is available, otherwise we rely on
56 // SO_NOSIGPIPE existency
58 // this should cover all the current Unix systems (Windows never sends any
59 // signals anyhow) but if we find one that has neither we should explicitly
60 // ignore SIGPIPE for it
61 // OpenVMS has neither MSG_NOSIGNAL nor SO_NOSIGPIPE. However the socket sample
62 // seems to work. Not sure if problems will show up on OpenVMS using sockets.
64 #define wxSOCKET_MSG_NOSIGNAL MSG_NOSIGNAL
65 #else // MSG_NOSIGNAL not available (BSD including OS X)
66 #if defined(__UNIX__) && !defined(SO_NOSIGPIPE) && !defined( __VMS )
67 #error "Writing to socket could generate unhandled SIGPIPE."
68 #error "Please post information about your system to wx-dev."
71 #define wxSOCKET_MSG_NOSIGNAL 0
74 // DLL options compatibility check:
76 WX_CHECK_BUILD_OPTIONS("wxNet")
78 // --------------------------------------------------------------------------
79 // macros and constants
80 // --------------------------------------------------------------------------
83 wxDEFINE_EVENT(wxEVT_SOCKET
, wxSocketEvent
);
86 #define MAX_DISCARD_SIZE (10 * 1024)
88 #define wxTRACE_Socket _T("wxSocket")
90 // --------------------------------------------------------------------------
92 // --------------------------------------------------------------------------
94 IMPLEMENT_CLASS(wxSocketBase
, wxObject
)
95 IMPLEMENT_CLASS(wxSocketServer
, wxSocketBase
)
96 IMPLEMENT_CLASS(wxSocketClient
, wxSocketBase
)
97 IMPLEMENT_CLASS(wxDatagramSocket
, wxSocketBase
)
98 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent
, wxEvent
)
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
107 void SetTimeValFromMS(timeval
& tv
, unsigned long ms
)
109 tv
.tv_sec
= (ms
/ 1000);
110 tv
.tv_usec
= (ms
% 1000) * 1000;
113 } // anonymous namespace
115 // --------------------------------------------------------------------------
117 // --------------------------------------------------------------------------
119 class wxSocketState
: public wxObject
122 wxSocketFlags m_flags
;
123 wxSocketEventFlags m_eventmask
;
128 wxSocketState() : wxObject() {}
130 DECLARE_NO_COPY_CLASS(wxSocketState
)
133 // wxSocketWaitModeChanger: temporarily change the socket flags affecting its
135 class wxSocketWaitModeChanger
138 // temporarily set the flags to include the flag value which may be either
139 // wxSOCKET_NOWAIT or wxSOCKET_WAITALL
140 wxSocketWaitModeChanger(wxSocketBase
*socket
, int flag
)
142 m_oldflags(socket
->GetFlags())
145 wxASSERT_MSG( flag
== wxSOCKET_WAITALL
|| flag
== wxSOCKET_NOWAIT
,
148 // preserve wxSOCKET_BLOCK value when switching to wxSOCKET_WAITALL
149 // mode but not when switching to wxSOCKET_NOWAIT as the latter is
150 // incompatible with wxSOCKET_BLOCK
151 if ( flag
!= wxSOCKET_NOWAIT
)
152 flag
|= m_oldflags
& wxSOCKET_BLOCK
;
154 socket
->SetFlags(flag
);
157 ~wxSocketWaitModeChanger()
159 m_socket
->SetFlags(m_oldflags
);
163 wxSocketBase
* const m_socket
;
164 const int m_oldflags
;
166 DECLARE_NO_COPY_CLASS(wxSocketWaitModeChanger
)
169 // wxSocketRead/WriteGuard are instantiated before starting reading
170 // from/writing to the socket
171 class wxSocketReadGuard
174 wxSocketReadGuard(wxSocketBase
*socket
)
177 wxASSERT_MSG( !m_socket
->m_reading
, "read reentrancy?" );
179 m_socket
->m_reading
= true;
184 m_socket
->m_reading
= false;
186 m_socket
->m_impl
->ReenableEvents(wxSOCKET_INPUT_FLAG
);
190 wxSocketBase
* const m_socket
;
192 DECLARE_NO_COPY_CLASS(wxSocketReadGuard
)
195 class wxSocketWriteGuard
198 wxSocketWriteGuard(wxSocketBase
*socket
)
201 wxASSERT_MSG( !m_socket
->m_writing
, "write reentrancy?" );
203 m_socket
->m_writing
= true;
205 m_socket
->m_impl
->ReenableEvents(wxSOCKET_OUTPUT_FLAG
);
208 ~wxSocketWriteGuard()
210 m_socket
->m_writing
= false;
214 wxSocketBase
* const m_socket
;
216 DECLARE_NO_COPY_CLASS(wxSocketWriteGuard
)
219 // ============================================================================
221 // ============================================================================
223 wxSocketManager
*wxSocketManager::ms_manager
= NULL
;
226 void wxSocketManager::Set(wxSocketManager
*manager
)
228 wxASSERT_MSG( !ms_manager
, "too late to set manager now" );
230 ms_manager
= manager
;
234 void wxSocketManager::Init()
236 wxASSERT_MSG( !ms_manager
, "shouldn't be initialized twice" );
239 Details: Initialize() creates a hidden window as a sink for socket
240 events, such as 'read completed'. wxMSW has only one message loop
241 for the main thread. If Initialize is called in a secondary thread,
242 the socket window will be created for the secondary thread, but
243 since there is no message loop on this thread, it will never
244 receive events and all socket operations will time out.
245 BTW, the main thread must not be stopped using sleep or block
246 on a semaphore (a bad idea in any case) or socket operations
249 On the Mac side, Initialize() stores a pointer to the CFRunLoop for
250 the main thread. Because secondary threads do not have run loops,
251 adding event notifications to the "Current" loop would have no
252 effect at all, events would never fire.
254 wxASSERT_MSG( wxIsMainThread(),
255 "sockets must be initialized from the main thread" );
257 wxAppConsole
* const app
= wxAppConsole::GetInstance();
258 wxCHECK_RET( app
, "sockets can't be initialized without wxApp" );
260 ms_manager
= app
->GetTraits()->GetSocketManager();
263 // ==========================================================================
265 // ==========================================================================
267 wxSocketImpl::wxSocketImpl(wxSocketBase
& wxsocket
)
268 : m_wxsocket(&wxsocket
)
270 m_fd
= INVALID_SOCKET
;
271 m_error
= wxSOCKET_NOERROR
;
275 SetTimeout(wxsocket
.GetTimeout() * 1000);
277 m_establishing
= false;
281 m_initialRecvBufferSize
= -1;
282 m_initialSendBufferSize
= -1;
285 wxSocketImpl::~wxSocketImpl()
287 if ( m_fd
!= INVALID_SOCKET
)
291 bool wxSocketImpl::PreCreateCheck(const wxSockAddressImpl
& addr
)
293 if ( m_fd
!= INVALID_SOCKET
)
295 m_error
= wxSOCKET_INVSOCK
;
301 m_error
= wxSOCKET_INVADDR
;
308 void wxSocketImpl::PostCreation()
310 // FreeBSD variants can't use MSG_NOSIGNAL, and instead use a socket option
312 EnableSocketOption(SO_NOSIGPIPE
);
316 EnableSocketOption(SO_REUSEADDR
);
320 wxASSERT_MSG( !m_stream
, "broadcasting is for datagram sockets only" );
322 EnableSocketOption(SO_BROADCAST
);
325 if ( m_initialRecvBufferSize
>= 0 )
326 SetSocketOption(SO_RCVBUF
, m_initialRecvBufferSize
);
327 if ( m_initialSendBufferSize
>= 0 )
328 SetSocketOption(SO_SNDBUF
, m_initialSendBufferSize
);
330 // we always put our sockets in unblocked mode and handle blocking
331 // ourselves in DoRead/Write() if wxSOCKET_WAITALL is specified
332 UnblockAndRegisterWithEventLoop();
335 wxSocketError
wxSocketImpl::UpdateLocalAddress()
337 WX_SOCKLEN_T lenAddr
= m_local
.GetLen();
338 if ( getsockname(m_fd
, m_local
.GetWritableAddr(), &lenAddr
) != 0 )
341 m_error
= wxSOCKET_IOERR
;
345 return wxSOCKET_NOERROR
;
348 wxSocketError
wxSocketImpl::CreateServer()
350 if ( !PreCreateCheck(m_local
) )
356 // do create the socket
357 m_fd
= socket(m_local
.GetFamily(), SOCK_STREAM
, 0);
359 if ( m_fd
== INVALID_SOCKET
)
361 m_error
= wxSOCKET_IOERR
;
362 return wxSOCKET_IOERR
;
367 // and then bind to and listen on it
369 // FIXME: should we test for m_dobind here?
370 if ( bind(m_fd
, m_local
.GetAddr(), m_local
.GetLen()) != 0 )
371 m_error
= wxSOCKET_IOERR
;
375 if ( listen(m_fd
, 5) != 0 )
376 m_error
= wxSOCKET_IOERR
;
385 // finally retrieve the address we effectively bound to
386 return UpdateLocalAddress();
389 wxSocketError
wxSocketImpl::CreateClient(bool wait
)
391 if ( !PreCreateCheck(m_peer
) )
394 m_fd
= socket(m_peer
.GetFamily(), SOCK_STREAM
, 0);
396 if ( m_fd
== INVALID_SOCKET
)
398 m_error
= wxSOCKET_IOERR
;
399 return wxSOCKET_IOERR
;
404 // If a local address has been set, then bind to it before calling connect
405 if ( m_local
.IsOk() )
407 if ( bind(m_fd
, m_local
.GetAddr(), m_local
.GetLen()) != 0 )
410 m_error
= wxSOCKET_IOERR
;
416 int rc
= connect(m_fd
, m_peer
.GetAddr(), m_peer
.GetLen());
417 if ( rc
== SOCKET_ERROR
)
419 wxSocketError err
= GetLastError();
420 if ( err
== wxSOCKET_WOULDBLOCK
)
422 m_establishing
= true;
424 // block waiting for connection if we should (otherwise just return
425 // wxSOCKET_WOULDBLOCK to the caller)
428 err
= SelectWithTimeout(wxSOCKET_CONNECTION_FLAG
)
431 m_establishing
= false;
439 m_error
= wxSOCKET_NOERROR
;
446 wxSocketError
wxSocketImpl::CreateUDP()
448 if ( !PreCreateCheck(m_local
) )
454 m_fd
= socket(m_local
.GetFamily(), SOCK_DGRAM
, 0);
456 if ( m_fd
== INVALID_SOCKET
)
458 m_error
= wxSOCKET_IOERR
;
459 return wxSOCKET_IOERR
;
466 if ( bind(m_fd
, m_local
.GetAddr(), m_local
.GetLen()) != 0 )
469 m_error
= wxSOCKET_IOERR
;
473 return UpdateLocalAddress();
476 return wxSOCKET_NOERROR
;
479 wxSocketImpl
*wxSocketImpl::Accept(wxSocketBase
& wxsocket
)
481 wxSockAddressStorage from
;
482 WX_SOCKLEN_T fromlen
= sizeof(from
);
483 const SOCKET fd
= accept(m_fd
, &from
.addr
, &fromlen
);
485 // accepting is similar to reading in the sense that it resets "ready for
486 // read" flag on the socket
487 ReenableEvents(wxSOCKET_INPUT_FLAG
);
489 if ( fd
== INVALID_SOCKET
)
492 wxSocketImpl
* const sock
= Create(wxsocket
);
494 sock
->m_peer
= wxSockAddressImpl(from
.addr
, fromlen
);
496 sock
->UnblockAndRegisterWithEventLoop();
502 void wxSocketImpl::Close()
504 if ( m_fd
!= INVALID_SOCKET
)
507 m_fd
= INVALID_SOCKET
;
511 void wxSocketImpl::Shutdown()
513 if ( m_fd
!= INVALID_SOCKET
)
515 shutdown(m_fd
, 1 /* SD_SEND */);
521 * Sets the timeout for blocking calls. Time is expressed in
524 void wxSocketImpl::SetTimeout(unsigned long millis
)
526 SetTimeValFromMS(m_timeout
, millis
);
529 void wxSocketImpl::NotifyOnStateChange(wxSocketNotify event
)
531 m_wxsocket
->OnRequest(event
);
534 /* Address handling */
535 wxSocketError
wxSocketImpl::SetLocal(const wxSockAddressImpl
& local
)
537 /* the socket must be initialized, or it must be a server */
538 if (m_fd
!= INVALID_SOCKET
&& !m_server
)
540 m_error
= wxSOCKET_INVSOCK
;
541 return wxSOCKET_INVSOCK
;
546 m_error
= wxSOCKET_INVADDR
;
547 return wxSOCKET_INVADDR
;
552 return wxSOCKET_NOERROR
;
555 wxSocketError
wxSocketImpl::SetPeer(const wxSockAddressImpl
& peer
)
559 m_error
= wxSOCKET_INVADDR
;
560 return wxSOCKET_INVADDR
;
565 return wxSOCKET_NOERROR
;
568 const wxSockAddressImpl
& wxSocketImpl::GetLocal()
570 if ( !m_local
.IsOk() )
571 UpdateLocalAddress();
576 // ----------------------------------------------------------------------------
578 // ----------------------------------------------------------------------------
580 // this macro wraps the given expression (normally a syscall) in a loop which
581 // ignores any interruptions, i.e. reevaluates it again if it failed and errno
584 #define DO_WHILE_EINTR( rc, syscall ) \
588 while ( rc == -1 && errno == EINTR )
590 #define DO_WHILE_EINTR( rc, syscall ) rc = (syscall)
593 int wxSocketImpl::RecvStream(void *buffer
, int size
)
596 DO_WHILE_EINTR( ret
, recv(m_fd
, static_cast<char *>(buffer
), size
, 0) );
600 // receiving 0 bytes for a TCP socket indicates that the connection was
601 // closed by peer so shut down our end as well (for UDP sockets empty
602 // datagrams are also possible)
603 m_establishing
= false;
604 NotifyOnStateChange(wxSOCKET_LOST
);
608 // do not return an error in this case however
614 int wxSocketImpl::SendStream(const void *buffer
, int size
)
617 DO_WHILE_EINTR( ret
, send(m_fd
, static_cast<const char *>(buffer
), size
,
618 wxSOCKET_MSG_NOSIGNAL
) );
623 int wxSocketImpl::RecvDgram(void *buffer
, int size
)
625 wxSockAddressStorage from
;
626 WX_SOCKLEN_T fromlen
= sizeof(from
);
629 DO_WHILE_EINTR( ret
, recvfrom(m_fd
, static_cast<char *>(buffer
), size
,
630 0, &from
.addr
, &fromlen
) );
632 if ( ret
== SOCKET_ERROR
)
635 m_peer
= wxSockAddressImpl(from
.addr
, fromlen
);
636 if ( !m_peer
.IsOk() )
642 int wxSocketImpl::SendDgram(const void *buffer
, int size
)
644 if ( !m_peer
.IsOk() )
646 m_error
= wxSOCKET_INVADDR
;
651 DO_WHILE_EINTR( ret
, sendto(m_fd
, static_cast<const char *>(buffer
), size
,
652 0, m_peer
.GetAddr(), m_peer
.GetLen()) );
657 int wxSocketImpl::Read(void *buffer
, int size
)
659 // server sockets can't be used for IO, only to accept new connections
660 if ( m_fd
== INVALID_SOCKET
|| m_server
)
662 m_error
= wxSOCKET_INVSOCK
;
666 int ret
= m_stream
? RecvStream(buffer
, size
)
667 : RecvDgram(buffer
, size
);
669 m_error
= ret
== SOCKET_ERROR
? GetLastError() : wxSOCKET_NOERROR
;
674 int wxSocketImpl::Write(const void *buffer
, int size
)
676 if ( m_fd
== INVALID_SOCKET
|| m_server
)
678 m_error
= wxSOCKET_INVSOCK
;
682 int ret
= m_stream
? SendStream(buffer
, size
)
683 : SendDgram(buffer
, size
);
685 m_error
= ret
== SOCKET_ERROR
? GetLastError() : wxSOCKET_NOERROR
;
690 // ==========================================================================
692 // ==========================================================================
694 // --------------------------------------------------------------------------
695 // Initialization and shutdown
696 // --------------------------------------------------------------------------
698 // FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
699 // to m_countInit with a crit section
700 size_t wxSocketBase::m_countInit
= 0;
702 bool wxSocketBase::IsInitialized()
704 return m_countInit
> 0;
707 bool wxSocketBase::Initialize()
709 if ( !m_countInit
++ )
711 wxSocketManager
* const manager
= wxSocketManager::Get();
712 if ( !manager
|| !manager
->OnInit() )
723 void wxSocketBase::Shutdown()
725 // we should be initialized
726 wxASSERT_MSG( m_countInit
> 0, _T("extra call to Shutdown()") );
727 if ( --m_countInit
== 0 )
729 wxSocketManager
* const manager
= wxSocketManager::Get();
730 wxCHECK_RET( manager
, "should have a socket manager" );
736 // --------------------------------------------------------------------------
738 // --------------------------------------------------------------------------
740 void wxSocketBase::Init()
743 m_type
= wxSOCKET_UNINIT
;
754 m_beingDeleted
= false;
769 if ( !IsInitialized() )
771 // this Initialize() will be undone by wxSocketModule::OnExit(), all
772 // the other calls to it should be matched by a call to Shutdown()
774 wxLogError("Cannot initialize wxSocketBase");
778 wxSocketBase::wxSocketBase()
783 wxSocketBase::wxSocketBase(wxSocketFlags flags
, wxSocketType type
)
792 wxSocketBase::~wxSocketBase()
794 // Just in case the app called Destroy() *and* then deleted the socket
795 // immediately: don't leave dangling pointers.
796 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
798 traits
->RemoveFromPendingDelete(this);
800 // Shutdown and close the socket
804 // Destroy the implementation object
807 // Free the pushback buffer
812 bool wxSocketBase::Destroy()
814 // Delayed destruction: the socket will be deleted during the next idle
815 // loop iteration. This ensures that all pending events have been
817 m_beingDeleted
= true;
819 // Shutdown and close the socket
822 // Suppress events from now on
825 // schedule this object for deletion
826 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
829 // let the traits object decide what to do with us
830 traits
->ScheduleForDestroy(this);
832 else // no app or no traits
834 // in wxBase we might have no app object at all, don't leak memory
841 // ----------------------------------------------------------------------------
843 // ----------------------------------------------------------------------------
845 void wxSocketBase::SetError(wxSocketError error
)
847 m_impl
->m_error
= error
;
850 wxSocketError
wxSocketBase::LastError() const
852 return m_impl
->GetError();
855 // --------------------------------------------------------------------------
857 // --------------------------------------------------------------------------
859 // The following IO operations update m_lcount:
860 // {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
861 bool wxSocketBase::Close()
863 // Interrupt pending waits
869 m_establishing
= false;
873 void wxSocketBase::ShutdownOutput()
879 wxSocketBase
& wxSocketBase::Read(void* buffer
, wxUint32 nbytes
)
881 wxSocketReadGuard
read(this);
883 m_lcount
= DoRead(buffer
, nbytes
);
888 wxUint32
wxSocketBase::DoRead(void* buffer_
, wxUint32 nbytes
)
890 wxCHECK_MSG( m_impl
, 0, "socket must be valid" );
892 // We use pointer arithmetic here which doesn't work with void pointers.
893 char *buffer
= static_cast<char *>(buffer_
);
894 wxCHECK_MSG( buffer
, 0, "NULL buffer" );
896 // Try the push back buffer first, even before checking whether the socket
897 // is valid to allow reading previously pushed back data from an already
899 wxUint32 total
= GetPushback(buffer
, nbytes
, false);
905 // our socket is non-blocking so Read() will return immediately if
906 // there is nothing to read yet and it's more efficient to try it first
907 // before entering DoWait() which is going to start dispatching GUI
908 // events and, even more importantly, we must do this under Windows
909 // where we're not going to get notifications about socket being ready
910 // for reading before we read all the existing data from it
911 const int ret
= m_connected
? m_impl
->Read(buffer
, nbytes
) : 0;
914 if ( m_impl
->GetLastError() == wxSOCKET_WOULDBLOCK
)
916 // if we don't want to wait, just return immediately
917 if ( m_flags
& wxSOCKET_NOWAIT
)
920 // otherwise wait until the socket becomes ready for reading or
921 // an error occurs on it
922 if ( !DoWaitWithTimeout(wxSOCKET_INPUT_FLAG
) )
924 // and exit if the timeout elapsed before it did
925 SetError(wxSOCKET_TIMEDOUT
);
934 SetError(wxSOCKET_IOERR
);
940 // for connection-oriented (e.g. TCP) sockets we can only read
941 // 0 bytes if the other end has been closed, and for connectionless
942 // ones (UDP) this flag doesn't make sense anyhow so we can set it
943 // to true too without doing any harm
946 // we're not going to read anything else and so if we haven't read
947 // anything (or not everything in wxSOCKET_WAITALL case) already,
949 if ( (m_flags
& wxSOCKET_WAITALL
) || !total
)
950 SetError(wxSOCKET_IOERR
);
956 // if we are happy to read something and not the entire nbytes bytes,
958 if ( !(m_flags
& wxSOCKET_WAITALL
) )
968 wxSocketBase
& wxSocketBase::ReadMsg(void* buffer
, wxUint32 nbytes
)
972 unsigned char sig
[4];
973 unsigned char len
[4];
976 wxSocketReadGuard
read(this);
978 wxSocketWaitModeChanger
changeFlags(this, wxSOCKET_WAITALL
);
981 if ( DoRead(&msg
, sizeof(msg
)) == sizeof(msg
) )
983 wxUint32 sig
= (wxUint32
)msg
.sig
[0];
984 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
985 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
986 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
988 if ( sig
== 0xfeeddead )
990 wxUint32 len
= (wxUint32
)msg
.len
[0];
991 len
|= (wxUint32
)(msg
.len
[1] << 8);
992 len
|= (wxUint32
)(msg
.len
[2] << 16);
993 len
|= (wxUint32
)(msg
.len
[3] << 24);
1004 // Don't attempt to read if the msg was zero bytes long.
1005 m_lcount
= len
? DoRead(buffer
, len
) : 0;
1009 char discard_buffer
[MAX_DISCARD_SIZE
];
1012 // NOTE: discarded bytes don't add to m_lcount.
1015 discard_len
= len2
> MAX_DISCARD_SIZE
1018 discard_len
= DoRead(discard_buffer
, (wxUint32
)discard_len
);
1019 len2
-= (wxUint32
)discard_len
;
1021 while ((discard_len
> 0) && len2
);
1024 if ( !len2
&& DoRead(&msg
, sizeof(msg
)) == sizeof(msg
) )
1026 sig
= (wxUint32
)msg
.sig
[0];
1027 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
1028 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
1029 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
1031 if ( sig
== 0xdeadfeed )
1038 SetError(wxSOCKET_IOERR
);
1043 wxSocketBase
& wxSocketBase::Peek(void* buffer
, wxUint32 nbytes
)
1045 wxSocketReadGuard
read(this);
1047 m_lcount
= DoRead(buffer
, nbytes
);
1049 Pushback(buffer
, m_lcount
);
1054 wxSocketBase
& wxSocketBase::Write(const void *buffer
, wxUint32 nbytes
)
1056 wxSocketWriteGuard
write(this);
1058 m_lcount
= DoWrite(buffer
, nbytes
);
1063 // This function is a mirror image of DoRead() except that it doesn't use the
1064 // push back buffer and doesn't treat 0 return value specially (normally this
1065 // shouldn't happen at all here), so please see comments there for explanations
1066 wxUint32
wxSocketBase::DoWrite(const void *buffer_
, wxUint32 nbytes
)
1068 wxCHECK_MSG( m_impl
, 0, "socket must be valid" );
1070 const char *buffer
= static_cast<const char *>(buffer_
);
1071 wxCHECK_MSG( buffer
, 0, "NULL buffer" );
1078 if ( (m_flags
& wxSOCKET_WAITALL
) || !total
)
1079 SetError(wxSOCKET_IOERR
);
1083 const int ret
= m_impl
->Write(buffer
, nbytes
);
1086 if ( m_impl
->GetLastError() == wxSOCKET_WOULDBLOCK
)
1088 if ( m_flags
& wxSOCKET_NOWAIT
)
1091 if ( !DoWaitWithTimeout(wxSOCKET_OUTPUT_FLAG
) )
1093 SetError(wxSOCKET_TIMEDOUT
);
1099 else // "real" error
1101 SetError(wxSOCKET_IOERR
);
1108 if ( !(m_flags
& wxSOCKET_WAITALL
) )
1118 wxSocketBase
& wxSocketBase::WriteMsg(const void *buffer
, wxUint32 nbytes
)
1122 unsigned char sig
[4];
1123 unsigned char len
[4];
1126 wxSocketWriteGuard
write(this);
1128 wxSocketWaitModeChanger
changeFlags(this, wxSOCKET_WAITALL
);
1130 msg
.sig
[0] = (unsigned char) 0xad;
1131 msg
.sig
[1] = (unsigned char) 0xde;
1132 msg
.sig
[2] = (unsigned char) 0xed;
1133 msg
.sig
[3] = (unsigned char) 0xfe;
1135 msg
.len
[0] = (unsigned char) (nbytes
& 0xff);
1136 msg
.len
[1] = (unsigned char) ((nbytes
>> 8) & 0xff);
1137 msg
.len
[2] = (unsigned char) ((nbytes
>> 16) & 0xff);
1138 msg
.len
[3] = (unsigned char) ((nbytes
>> 24) & 0xff);
1141 if ( DoWrite(&msg
, sizeof(msg
)) == sizeof(msg
) )
1143 m_lcount
= DoWrite(buffer
, nbytes
);
1144 if ( m_lcount
== nbytes
)
1146 msg
.sig
[0] = (unsigned char) 0xed;
1147 msg
.sig
[1] = (unsigned char) 0xfe;
1148 msg
.sig
[2] = (unsigned char) 0xad;
1149 msg
.sig
[3] = (unsigned char) 0xde;
1153 msg
.len
[3] = (char) 0;
1155 if ( DoWrite(&msg
, sizeof(msg
)) == sizeof(msg
))
1161 SetError(wxSOCKET_IOERR
);
1166 wxSocketBase
& wxSocketBase::Unread(const void *buffer
, wxUint32 nbytes
)
1169 Pushback(buffer
, nbytes
);
1171 SetError(wxSOCKET_NOERROR
);
1177 wxSocketBase
& wxSocketBase::Discard()
1179 char *buffer
= new char[MAX_DISCARD_SIZE
];
1183 wxSocketReadGuard
read(this);
1185 wxSocketWaitModeChanger
changeFlags(this, wxSOCKET_NOWAIT
);
1189 ret
= DoRead(buffer
, MAX_DISCARD_SIZE
);
1192 while (ret
== MAX_DISCARD_SIZE
);
1196 SetError(wxSOCKET_NOERROR
);
1201 // --------------------------------------------------------------------------
1203 // --------------------------------------------------------------------------
1206 This function will check for the events specified in the flags parameter,
1207 and it will return a mask indicating which operations can be performed.
1209 wxSocketEventFlags
wxSocketImpl::Select(wxSocketEventFlags flags
,
1210 const timeval
*timeout
)
1212 if ( m_fd
== INVALID_SOCKET
)
1213 return (wxSOCKET_LOST_FLAG
& flags
);
1219 tv
.tv_sec
= tv
.tv_usec
= 0;
1221 // prepare the FD sets, passing NULL for the one(s) we don't use
1223 readfds
, *preadfds
= NULL
,
1224 writefds
, *pwritefds
= NULL
,
1225 exceptfds
; // always want to know about errors
1227 if ( flags
& wxSOCKET_INPUT_FLAG
)
1229 preadfds
= &readfds
;
1230 wxFD_ZERO(preadfds
);
1231 wxFD_SET(m_fd
, preadfds
);
1234 // when using non-blocking connect() the socket becomes connected
1235 // (successfully or not) when it becomes writable
1236 if ( flags
& (wxSOCKET_OUTPUT_FLAG
| wxSOCKET_CONNECTION_FLAG
) )
1238 pwritefds
= &writefds
;
1239 wxFD_ZERO(pwritefds
);
1240 wxFD_SET(m_fd
, pwritefds
);
1243 wxFD_ZERO(&exceptfds
);
1244 wxFD_SET(m_fd
, &exceptfds
);
1246 const int rc
= select(m_fd
+ 1, preadfds
, pwritefds
, &exceptfds
, &tv
);
1248 // check for errors first
1249 if ( rc
== -1 || wxFD_ISSET(m_fd
, &exceptfds
) )
1251 m_establishing
= false;
1253 return wxSOCKET_LOST_FLAG
& flags
;
1259 wxASSERT_MSG( rc
== 1, "unexpected select() return value" );
1261 wxSocketEventFlags detected
= 0;
1262 if ( preadfds
&& wxFD_ISSET(m_fd
, preadfds
) )
1263 detected
|= wxSOCKET_INPUT_FLAG
;
1265 if ( pwritefds
&& wxFD_ISSET(m_fd
, pwritefds
) )
1267 // check for the case of non-blocking connect()
1268 if ( m_establishing
&& !m_server
)
1271 SOCKOPTLEN_T len
= sizeof(error
);
1272 m_establishing
= false;
1273 getsockopt(m_fd
, SOL_SOCKET
, SO_ERROR
, (char*)&error
, &len
);
1276 detected
= wxSOCKET_LOST_FLAG
;
1278 detected
|= wxSOCKET_CONNECTION_FLAG
;
1280 else // not called to get non-blocking connect() status
1282 detected
|= wxSOCKET_OUTPUT_FLAG
;
1286 return detected
& flags
;
1290 wxSocketBase::DoWait(long seconds
, long milliseconds
, wxSocketEventFlags flags
)
1292 // Use either the provided timeout or the default timeout value associated
1293 // with this socket.
1295 // TODO: allow waiting forever, see #9443
1296 const long timeout
= seconds
== -1 ? m_timeout
* 1000
1297 : seconds
* 1000 + milliseconds
;
1299 return DoWait(timeout
, flags
);
1303 wxSocketBase::DoWait(long timeout
, wxSocketEventFlags flags
)
1305 wxCHECK_MSG( m_impl
, -1, "can't wait on invalid socket" );
1307 // we're never going to become ready if we're not connected (any more)
1308 if ( !m_connected
&& !m_establishing
)
1311 // This can be set to true from Interrupt() to exit this function a.s.a.p.
1312 m_interrupt
= false;
1315 const wxMilliClock_t timeEnd
= wxGetLocalTimeMillis() + timeout
;
1317 // Get the active event loop which we'll use for the message dispatching
1318 // when running in the main thread unless this was explicitly disabled by
1319 // setting wxSOCKET_BLOCK flag
1320 wxEventLoopBase
*eventLoop
;
1321 if ( !(m_flags
& wxSOCKET_BLOCK
) && wxIsMainThread() )
1323 eventLoop
= wxEventLoop::GetActive();
1325 else // in worker thread
1327 // We never dispatch messages from threads other than the main one.
1331 // Make sure the events we're interested in are enabled before waiting for
1332 // them: this is really necessary here as otherwise this could happen:
1333 // 1. DoRead(wxSOCKET_WAITALL) is called
1334 // 2. There is nothing to read so DoWait(wxSOCKET_INPUT_FLAG) is called
1335 // 3. Some, but not all data appears, wxSocketImplUnix::OnReadWaiting()
1336 // is called and wxSOCKET_INPUT_FLAG events are disabled in it
1337 // 4. Because of wxSOCKET_WAITALL we call DoWait() again but the events
1338 // are still disabled and we block forever
1340 // More elegant solution would be nice but for now simply re-enabling the
1341 // events here will do
1342 m_impl
->ReenableEvents(flags
& (wxSOCKET_INPUT_FLAG
| wxSOCKET_OUTPUT_FLAG
));
1345 // Wait until we receive the event we're waiting for or the timeout expires
1346 // (but note that we always execute the loop at least once, even if timeout
1347 // is 0 as this is used for polling)
1349 for ( bool firstTime
= true; !m_interrupt
; firstTime
= false )
1351 long timeLeft
= wxMilliClockToLong(timeEnd
- wxGetLocalTimeMillis());
1360 wxSocketEventFlags events
;
1363 // reset them before starting to wait
1366 eventLoop
->DispatchTimeout(timeLeft
);
1368 events
= m_eventsgot
;
1370 else // no event loop or waiting in another thread
1372 // as explained below, we should always check for wxSOCKET_LOST_FLAG
1374 SetTimeValFromMS(tv
, timeLeft
);
1375 events
= m_impl
->Select(flags
| wxSOCKET_LOST_FLAG
, &tv
);
1378 // always check for wxSOCKET_LOST_FLAG, even if flags doesn't include
1379 // it, as continuing to wait for anything else after getting it is
1381 if ( events
& wxSOCKET_LOST_FLAG
)
1383 m_connected
= false;
1384 m_establishing
= false;
1389 // otherwise mask out the bits we're not interested in
1392 // Incoming connection (server) or connection established (client)?
1393 if ( events
& wxSOCKET_CONNECTION_FLAG
)
1396 m_establishing
= false;
1401 // Data available or output buffer ready?
1402 if ( (events
& wxSOCKET_INPUT_FLAG
) || (events
& wxSOCKET_OUTPUT_FLAG
) )
1412 bool wxSocketBase::Wait(long seconds
, long milliseconds
)
1414 return DoWait(seconds
, milliseconds
,
1415 wxSOCKET_INPUT_FLAG
|
1416 wxSOCKET_OUTPUT_FLAG
|
1417 wxSOCKET_CONNECTION_FLAG
) != 0;
1420 bool wxSocketBase::WaitForRead(long seconds
, long milliseconds
)
1422 // Check pushback buffer before entering DoWait
1426 // Check if the socket is not already ready for input, if it is, there is
1427 // no need to start waiting for it (worse, we'll actually never get a
1428 // notification about the socket becoming ready if it is already under
1430 if ( m_impl
->Select(wxSOCKET_INPUT_FLAG
) )
1433 return DoWait(seconds
, milliseconds
, wxSOCKET_INPUT_FLAG
) != 0;
1437 bool wxSocketBase::WaitForWrite(long seconds
, long milliseconds
)
1439 if ( m_impl
->Select(wxSOCKET_OUTPUT_FLAG
) )
1442 return DoWait(seconds
, milliseconds
, wxSOCKET_OUTPUT_FLAG
) != 0;
1445 bool wxSocketBase::WaitForLost(long seconds
, long milliseconds
)
1447 return DoWait(seconds
, milliseconds
, wxSOCKET_LOST_FLAG
) == -1;
1450 // --------------------------------------------------------------------------
1452 // --------------------------------------------------------------------------
1455 // Get local or peer address
1458 bool wxSocketBase::GetPeer(wxSockAddress
& addr
) const
1460 wxCHECK_MSG( m_impl
, false, "invalid socket" );
1462 const wxSockAddressImpl
& peer
= m_impl
->GetPeer();
1466 addr
.SetAddress(peer
);
1471 bool wxSocketBase::GetLocal(wxSockAddress
& addr
) const
1473 wxCHECK_MSG( m_impl
, false, "invalid socket" );
1475 const wxSockAddressImpl
& local
= m_impl
->GetLocal();
1476 if ( !local
.IsOk() )
1479 addr
.SetAddress(local
);
1485 // Save and restore socket state
1488 void wxSocketBase::SaveState()
1490 wxSocketState
*state
;
1492 state
= new wxSocketState();
1494 state
->m_flags
= m_flags
;
1495 state
->m_notify
= m_notify
;
1496 state
->m_eventmask
= m_eventmask
;
1497 state
->m_clientData
= m_clientData
;
1499 m_states
.Append(state
);
1502 void wxSocketBase::RestoreState()
1504 wxList::compatibility_iterator node
;
1505 wxSocketState
*state
;
1507 node
= m_states
.GetLast();
1511 state
= (wxSocketState
*)node
->GetData();
1513 m_flags
= state
->m_flags
;
1514 m_notify
= state
->m_notify
;
1515 m_eventmask
= state
->m_eventmask
;
1516 m_clientData
= state
->m_clientData
;
1518 m_states
.Erase(node
);
1523 // Timeout and flags
1526 void wxSocketBase::SetTimeout(long seconds
)
1528 m_timeout
= seconds
;
1531 m_impl
->SetTimeout(m_timeout
* 1000);
1534 void wxSocketBase::SetFlags(wxSocketFlags flags
)
1536 // Do some sanity checking on the flags used: not all values can be used
1538 wxASSERT_MSG( !(flags
& wxSOCKET_NOWAIT
) ||
1539 !(flags
& (wxSOCKET_WAITALL
| wxSOCKET_BLOCK
)),
1540 "Using wxSOCKET_WAITALL or wxSOCKET_BLOCK with "
1541 "wxSOCKET_NOWAIT doesn't make sense" );
1547 // --------------------------------------------------------------------------
1549 // --------------------------------------------------------------------------
1551 void wxSocketBase::OnRequest(wxSocketNotify notification
)
1553 wxSocketEventFlags flag
= 0;
1554 switch ( notification
)
1556 case wxSOCKET_INPUT
:
1557 flag
= wxSOCKET_INPUT_FLAG
;
1560 case wxSOCKET_OUTPUT
:
1561 flag
= wxSOCKET_OUTPUT_FLAG
;
1564 case wxSOCKET_CONNECTION
:
1565 flag
= wxSOCKET_CONNECTION_FLAG
;
1569 flag
= wxSOCKET_LOST_FLAG
;
1573 wxFAIL_MSG( "unknown wxSocket notification" );
1576 // if we lost the connection the socket is now closed
1577 if ( notification
== wxSOCKET_LOST
)
1580 // remember the events which were generated for this socket, we're going to
1581 // use this in DoWait()
1582 m_eventsgot
|= flag
;
1584 // send the wx event if enabled and we're interested in it
1585 if ( m_notify
&& (m_eventmask
& flag
) && m_handler
)
1587 // don't generate the events when we're inside DoWait() called from our
1588 // own code as we are going to consume the data that has just become
1589 // available ourselves and the user code won't see it at all
1590 if ( (notification
== wxSOCKET_INPUT
&& m_reading
) ||
1591 (notification
== wxSOCKET_OUTPUT
&& m_writing
) )
1596 wxSocketEvent
event(m_id
);
1597 event
.m_event
= notification
;
1598 event
.m_clientData
= m_clientData
;
1599 event
.SetEventObject(this);
1601 m_handler
->AddPendingEvent(event
);
1605 void wxSocketBase::Notify(bool notify
)
1610 void wxSocketBase::SetNotify(wxSocketEventFlags flags
)
1612 m_eventmask
= flags
;
1615 void wxSocketBase::SetEventHandler(wxEvtHandler
& handler
, int id
)
1617 m_handler
= &handler
;
1621 // --------------------------------------------------------------------------
1623 // --------------------------------------------------------------------------
1625 void wxSocketBase::Pushback(const void *buffer
, wxUint32 size
)
1629 if (m_unread
== NULL
)
1630 m_unread
= malloc(size
);
1635 tmp
= malloc(m_unrd_size
+ size
);
1636 memcpy((char *)tmp
+ size
, m_unread
, m_unrd_size
);
1642 m_unrd_size
+= size
;
1644 memcpy(m_unread
, buffer
, size
);
1647 wxUint32
wxSocketBase::GetPushback(void *buffer
, wxUint32 size
, bool peek
)
1649 wxCHECK_MSG( buffer
, 0, "NULL buffer" );
1654 if (size
> (m_unrd_size
-m_unrd_cur
))
1655 size
= m_unrd_size
-m_unrd_cur
;
1657 memcpy(buffer
, (char *)m_unread
+ m_unrd_cur
, size
);
1662 if (m_unrd_size
== m_unrd_cur
)
1675 // ==========================================================================
1677 // ==========================================================================
1679 // --------------------------------------------------------------------------
1681 // --------------------------------------------------------------------------
1683 wxSocketServer::wxSocketServer(const wxSockAddress
& addr
,
1684 wxSocketFlags flags
)
1685 : wxSocketBase(flags
, wxSOCKET_SERVER
)
1687 wxLogTrace( wxTRACE_Socket
, _T("Opening wxSocketServer") );
1689 m_impl
= wxSocketImpl::Create(*this);
1693 wxLogTrace( wxTRACE_Socket
, _T("*** Failed to create m_impl") );
1697 // Setup the socket as server
1698 m_impl
->SetLocal(addr
.GetAddress());
1700 if (GetFlags() & wxSOCKET_REUSEADDR
) {
1701 m_impl
->SetReusable();
1703 if (GetFlags() & wxSOCKET_BROADCAST
) {
1704 m_impl
->SetBroadcast();
1706 if (GetFlags() & wxSOCKET_NOBIND
) {
1707 m_impl
->DontDoBind();
1710 if (m_impl
->CreateServer() != wxSOCKET_NOERROR
)
1715 wxLogTrace( wxTRACE_Socket
, _T("*** CreateServer() failed") );
1719 wxLogTrace( wxTRACE_Socket
, _T("wxSocketServer on fd %d"), m_impl
->m_fd
);
1722 // --------------------------------------------------------------------------
1724 // --------------------------------------------------------------------------
1726 bool wxSocketServer::AcceptWith(wxSocketBase
& sock
, bool wait
)
1728 if ( !m_impl
|| (m_impl
->m_fd
== INVALID_SOCKET
) || !m_impl
->IsServer() )
1730 wxFAIL_MSG( "can only be called for a valid server socket" );
1732 SetError(wxSOCKET_INVSOCK
);
1739 // wait until we get a connection
1740 if ( !m_impl
->SelectWithTimeout(wxSOCKET_INPUT_FLAG
) )
1742 SetError(wxSOCKET_TIMEDOUT
);
1748 sock
.m_impl
= m_impl
->Accept(sock
);
1752 SetError(m_impl
->GetLastError());
1757 sock
.m_type
= wxSOCKET_BASE
;
1758 sock
.m_connected
= true;
1763 wxSocketBase
*wxSocketServer::Accept(bool wait
)
1765 wxSocketBase
* sock
= new wxSocketBase();
1767 sock
->SetFlags(m_flags
);
1769 if (!AcceptWith(*sock
, wait
))
1778 bool wxSocketServer::WaitForAccept(long seconds
, long milliseconds
)
1780 return DoWait(seconds
, milliseconds
, wxSOCKET_CONNECTION_FLAG
) == 1;
1783 bool wxSocketBase::GetOption(int level
, int optname
, void *optval
, int *optlen
)
1785 wxASSERT_MSG( m_impl
, _T("Socket not initialised") );
1787 SOCKOPTLEN_T lenreal
= *optlen
;
1788 if ( getsockopt(m_impl
->m_fd
, level
, optname
,
1789 static_cast<char *>(optval
), &lenreal
) != 0 )
1798 wxSocketBase::SetOption(int level
, int optname
, const void *optval
, int optlen
)
1800 wxASSERT_MSG( m_impl
, _T("Socket not initialised") );
1802 return setsockopt(m_impl
->m_fd
, level
, optname
,
1803 static_cast<const char *>(optval
), optlen
) == 0;
1806 bool wxSocketBase::SetLocal(const wxIPV4address
& local
)
1808 m_localAddress
= local
;
1813 // ==========================================================================
1815 // ==========================================================================
1817 // --------------------------------------------------------------------------
1819 // --------------------------------------------------------------------------
1821 wxSocketClient::wxSocketClient(wxSocketFlags flags
)
1822 : wxSocketBase(flags
, wxSOCKET_CLIENT
)
1824 m_initialRecvBufferSize
=
1825 m_initialSendBufferSize
= -1;
1828 // --------------------------------------------------------------------------
1830 // --------------------------------------------------------------------------
1832 bool wxSocketClient::DoConnect(const wxSockAddress
& remote
,
1833 const wxSockAddress
* local
,
1838 // Shutdown and destroy the old socket
1843 m_connected
= false;
1844 m_establishing
= false;
1846 // Create and set up the new one
1847 m_impl
= wxSocketImpl::Create(*this);
1851 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1852 if (GetFlags() & wxSOCKET_REUSEADDR
)
1853 m_impl
->SetReusable();
1854 if (GetFlags() & wxSOCKET_BROADCAST
)
1855 m_impl
->SetBroadcast();
1856 if (GetFlags() & wxSOCKET_NOBIND
)
1857 m_impl
->DontDoBind();
1859 // Bind to the local IP address and port, when provided or if one had been
1861 if ( !local
&& m_localAddress
.GetAddress().IsOk() )
1862 local
= &m_localAddress
;
1865 m_impl
->SetLocal(local
->GetAddress());
1867 m_impl
->SetInitialSocketBuffers(m_initialRecvBufferSize
, m_initialSendBufferSize
);
1869 m_impl
->SetPeer(remote
.GetAddress());
1871 // Finally do create the socket and connect to the peer
1872 const wxSocketError err
= m_impl
->CreateClient(wait
);
1874 if ( err
!= wxSOCKET_NOERROR
)
1876 if ( err
== wxSOCKET_WOULDBLOCK
)
1878 wxASSERT_MSG( !wait
, "shouldn't get this for blocking connect" );
1880 m_establishing
= true;
1890 bool wxSocketClient::Connect(const wxSockAddress
& remote
, bool wait
)
1892 return DoConnect(remote
, NULL
, wait
);
1895 bool wxSocketClient::Connect(const wxSockAddress
& remote
,
1896 const wxSockAddress
& local
,
1899 return DoConnect(remote
, &local
, wait
);
1902 bool wxSocketClient::WaitOnConnect(long seconds
, long milliseconds
)
1906 // this happens if the initial attempt to connect succeeded without
1911 wxCHECK_MSG( m_establishing
&& m_impl
, false,
1912 "No connection establishment attempt in progress" );
1914 // notice that we return true even if DoWait() returned -1, i.e. if an
1915 // error occurred and connection was lost: this is intentional as we should
1916 // return false only if timeout expired without anything happening
1917 return DoWait(seconds
, milliseconds
, wxSOCKET_CONNECTION_FLAG
) != 0;
1920 // ==========================================================================
1922 // ==========================================================================
1924 wxDatagramSocket::wxDatagramSocket( const wxSockAddress
& addr
,
1925 wxSocketFlags flags
)
1926 : wxSocketBase( flags
, wxSOCKET_DATAGRAM
)
1928 // Create the socket
1929 m_impl
= wxSocketImpl::Create(*this);
1934 // Setup the socket as non connection oriented
1935 m_impl
->SetLocal(addr
.GetAddress());
1936 if (flags
& wxSOCKET_REUSEADDR
)
1938 m_impl
->SetReusable();
1940 if (GetFlags() & wxSOCKET_BROADCAST
)
1942 m_impl
->SetBroadcast();
1944 if (GetFlags() & wxSOCKET_NOBIND
)
1946 m_impl
->DontDoBind();
1949 if ( m_impl
->CreateUDP() != wxSOCKET_NOERROR
)
1956 // Initialize all stuff
1957 m_connected
= false;
1958 m_establishing
= false;
1961 wxDatagramSocket
& wxDatagramSocket::RecvFrom( wxSockAddress
& addr
,
1970 wxDatagramSocket
& wxDatagramSocket::SendTo( const wxSockAddress
& addr
,
1974 wxASSERT_MSG( m_impl
, _T("Socket not initialised") );
1976 m_impl
->SetPeer(addr
.GetAddress());
1981 // ==========================================================================
1983 // ==========================================================================
1985 class wxSocketModule
: public wxModule
1988 virtual bool OnInit()
1990 // wxSocketBase will call Initialize() itself only if sockets are
1991 // really used, don't do it from here
1995 virtual void OnExit()
1997 if ( wxSocketBase::IsInitialized() )
1998 wxSocketBase::Shutdown();
2002 DECLARE_DYNAMIC_CLASS(wxSocketModule
)
2005 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule
, wxModule
)
2007 #if defined(wxUSE_SELECT_DISPATCHER) && wxUSE_SELECT_DISPATCHER
2008 // NOTE: we need to force linking against socketiohandler.cpp otherwise in
2009 // static builds of wxWidgets the ManagerSetter::ManagerSetter ctor
2010 // contained there wouldn't be ever called
2011 wxFORCE_LINK_MODULE( socketiohandler
)
2014 #endif // wxUSE_SOCKETS