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) 2000-1999, Guillermo Rodriguez Garcia
9 // License: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ==========================================================================
14 // ==========================================================================
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #include "wx/socket.h"
28 #include "wx/object.h"
29 #include "wx/string.h"
36 #include "wx/module.h"
39 #include "wx/apptrait.h"
40 #include "wx/sckaddr.h"
41 #include "wx/stopwatch.h"
42 #include "wx/thread.h"
43 #include "wx/evtloop.h"
44 #include "wx/private/fd.h"
46 // DLL options compatibility check:
48 WX_CHECK_BUILD_OPTIONS("wxNet")
50 // --------------------------------------------------------------------------
51 // macros and constants
52 // --------------------------------------------------------------------------
55 #define MAX_DISCARD_SIZE (10 * 1024)
57 #define wxTRACE_Socket _T("wxSocket")
59 // --------------------------------------------------------------------------
61 // --------------------------------------------------------------------------
63 IMPLEMENT_CLASS(wxSocketBase
, wxObject
)
64 IMPLEMENT_CLASS(wxSocketServer
, wxSocketBase
)
65 IMPLEMENT_CLASS(wxSocketClient
, wxSocketBase
)
66 IMPLEMENT_CLASS(wxDatagramSocket
, wxSocketBase
)
67 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent
, wxEvent
)
69 // --------------------------------------------------------------------------
71 // --------------------------------------------------------------------------
73 class wxSocketState
: public wxObject
76 wxSocketFlags m_flags
;
77 wxSocketEventFlags m_eventmask
;
82 wxSocketState() : wxObject() {}
84 DECLARE_NO_COPY_CLASS(wxSocketState
)
87 // Conditionally make the socket non-blocking for the lifetime of this object.
88 class wxSocketUnblocker
91 wxSocketUnblocker(GSocket
*socket
, bool unblock
= true)
96 m_socket
->SetNonBlocking(true);
102 m_socket
->SetNonBlocking(false);
106 GSocket
* const m_socket
;
109 DECLARE_NO_COPY_CLASS(wxSocketUnblocker
)
112 // ============================================================================
114 // ============================================================================
116 GSocketManager
*GSocketManager::ms_manager
= NULL
;
119 void GSocketManager::Set(GSocketManager
*manager
)
121 wxASSERT_MSG( !ms_manager
, "too late to set manager now" );
123 ms_manager
= manager
;
127 void GSocketManager::Init()
129 wxASSERT_MSG( !ms_manager
, "shouldn't be initialized twice" );
132 Details: Initialize() creates a hidden window as a sink for socket
133 events, such as 'read completed'. wxMSW has only one message loop
134 for the main thread. If Initialize is called in a secondary thread,
135 the socket window will be created for the secondary thread, but
136 since there is no message loop on this thread, it will never
137 receive events and all socket operations will time out.
138 BTW, the main thread must not be stopped using sleep or block
139 on a semaphore (a bad idea in any case) or socket operations
142 On the Mac side, Initialize() stores a pointer to the CFRunLoop for
143 the main thread. Because secondary threads do not have run loops,
144 adding event notifications to the "Current" loop would have no
145 effect at all, events would never fire.
147 wxASSERT_MSG( wxIsMainThread(),
148 "sockets must be initialized from the main thread" );
150 wxAppConsole
* const app
= wxAppConsole::GetInstance();
151 wxCHECK_RET( app
, "sockets can't be initialized without wxApp" );
153 ms_manager
= app
->GetTraits()->GetSocketManager();
156 // ==========================================================================
158 // ==========================================================================
161 GSocket
*GSocketBase::Create()
163 GSocket
* const newsocket
= new GSocket();
164 if ( !GSocketManager::Get()->Init_Socket(newsocket
) )
173 GSocketBase::GSocketBase()
175 m_fd
= INVALID_SOCKET
;
179 m_error
= GSOCK_NOERROR
;
182 m_non_blocking
= false;
184 m_timeout
.tv_sec
= 10 * 60; /* 10 minutes */
185 m_timeout
.tv_usec
= 0;
187 m_timeout
= 10*60*1000; /* 10 minutes * 60 sec * 1000 millisec */
190 m_establishing
= false;
194 m_initialRecvBufferSize
= -1;
195 m_initialSendBufferSize
= -1;
197 for ( int i
= 0; i
< GSOCK_MAX_EVENT
; i
++ )
201 GSocketBase::~GSocketBase()
203 if (m_fd
!= INVALID_SOCKET
)
207 GAddress_destroy(m_local
);
210 GAddress_destroy(m_peer
);
212 // cast is ok as all GSocketBase objects we have in our code are really
214 GSocketManager::Get()->Destroy_Socket(static_cast<GSocket
*>(this));
218 * Disallow further read/write operations on this socket, close
219 * the fd and disable all callbacks.
221 void GSocketBase::Shutdown()
223 if ( m_fd
!= INVALID_SOCKET
)
225 shutdown(m_fd
, 1 /* SD_SEND */);
229 /* Disable GUI callbacks */
230 for ( int evt
= 0; evt
< GSOCK_MAX_EVENT
; evt
++ )
231 m_cbacks
[evt
] = NULL
;
233 m_detected
= GSOCK_LOST_FLAG
;
236 // ==========================================================================
238 // ==========================================================================
240 // --------------------------------------------------------------------------
241 // Initialization and shutdown
242 // --------------------------------------------------------------------------
244 // FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
245 // to m_countInit with a crit section
246 size_t wxSocketBase::m_countInit
= 0;
248 bool wxSocketBase::IsInitialized()
250 return m_countInit
> 0;
253 bool wxSocketBase::Initialize()
255 if ( !m_countInit
++ )
257 if ( !GSocket_Init() )
268 void wxSocketBase::Shutdown()
270 // we should be initialized
271 wxASSERT_MSG( m_countInit
> 0, _T("extra call to Shutdown()") );
272 if ( --m_countInit
== 0 )
278 // --------------------------------------------------------------------------
280 // --------------------------------------------------------------------------
282 void wxSocketBase::Init()
285 m_type
= wxSOCKET_UNINIT
;
297 m_beingDeleted
= false;
311 if ( !IsInitialized() )
313 // this Initialize() will be undone by wxSocketModule::OnExit(), all
314 // the other calls to it should be matched by a call to Shutdown()
319 wxSocketBase::wxSocketBase()
324 wxSocketBase::wxSocketBase(wxSocketFlags flags
, wxSocketType type
)
333 wxSocketBase::~wxSocketBase()
335 // Just in case the app called Destroy() *and* then deleted the socket
336 // immediately: don't leave dangling pointers.
337 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
339 traits
->RemoveFromPendingDelete(this);
341 // Shutdown and close the socket
345 // Destroy the GSocket object
349 // Free the pushback buffer
354 bool wxSocketBase::Destroy()
356 // Delayed destruction: the socket will be deleted during the next idle
357 // loop iteration. This ensures that all pending events have been
359 m_beingDeleted
= true;
361 // Shutdown and close the socket
364 // Supress events from now on
367 // schedule this object for deletion
368 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
371 // let the traits object decide what to do with us
372 traits
->ScheduleForDestroy(this);
374 else // no app or no traits
376 // in wxBase we might have no app object at all, don't leak memory
383 // --------------------------------------------------------------------------
385 // --------------------------------------------------------------------------
387 // The following IO operations update m_error and m_lcount:
388 // {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
390 // TODO: Should Connect, Accept and AcceptWith update m_error?
392 bool wxSocketBase::Close()
394 // Interrupt pending waits
400 m_socket
->UnsetCallback(
404 GSOCK_CONNECTION_FLAG
407 // Shutdown the connection
408 m_socket
->Shutdown();
412 m_establishing
= false;
416 wxSocketBase
& wxSocketBase::Read(void* buffer
, wxUint32 nbytes
)
421 m_lcount
= DoRead(buffer
, nbytes
);
423 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
424 if (m_flags
& wxSOCKET_WAITALL
)
425 m_error
= (m_lcount
!= nbytes
);
427 m_error
= (m_lcount
== 0);
429 // Allow read events from now on
435 wxUint32
wxSocketBase::DoRead(void* buffer_
, wxUint32 nbytes
)
437 // We use pointer arithmetic here which doesn't work with void pointers.
438 char *buffer
= static_cast<char *>(buffer_
);
440 // Try the push back buffer first, even before checking whether the socket
441 // is valid to allow reading previously pushed back data from an already
443 wxUint32 total
= GetPushback(buffer
, nbytes
, false);
447 // If it's indeed closed or if read everything, there is nothing more to do.
448 if ( !m_socket
|| !nbytes
)
451 wxCHECK_MSG( buffer
, 0, "NULL buffer" );
454 // wxSOCKET_NOWAIT overrides all the other flags and means that we are
455 // polling the socket and don't block at all.
456 if ( m_flags
& wxSOCKET_NOWAIT
)
458 wxSocketUnblocker
unblock(m_socket
);
459 int ret
= m_socket
->Read(buffer
, nbytes
);
465 else // blocking socket
469 // Wait until socket becomes ready for reading dispatching the GUI
470 // events in the meanwhile unless wxSOCKET_BLOCK was explicitly
471 // specified to disable this.
472 if ( !(m_flags
& wxSOCKET_BLOCK
) && !WaitForRead() )
475 const int ret
= m_socket
->Read(buffer
, nbytes
);
478 // for connection-oriented (e.g. TCP) sockets we can only read
479 // 0 bytes if the other end has been closed, and for
480 // connectionless ones (UDP) this flag doesn't make sense
481 // anyhow so we can set it to true too without doing any harm
488 // this will be always interpreted as error by Read()
494 // If wxSOCKET_WAITALL is not set, we can leave now as we did read
495 // something and we don't need to wait for all nbytes bytes to be
497 if ( !(m_flags
& wxSOCKET_WAITALL
) )
500 // Otherwise continue reading until we do read everything.
512 wxSocketBase
& wxSocketBase::ReadMsg(void* buffer
, wxUint32 nbytes
)
514 wxUint32 len
, len2
, sig
, total
;
519 unsigned char sig
[4];
520 unsigned char len
[4];
529 SetFlags((m_flags
& wxSOCKET_BLOCK
) | wxSOCKET_WAITALL
);
531 if (DoRead(&msg
, sizeof(msg
)) != sizeof(msg
))
534 sig
= (wxUint32
)msg
.sig
[0];
535 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
536 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
537 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
539 if (sig
!= 0xfeeddead)
541 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
545 len
= (wxUint32
)msg
.len
[0];
546 len
|= (wxUint32
)(msg
.len
[1] << 8);
547 len
|= (wxUint32
)(msg
.len
[2] << 16);
548 len
|= (wxUint32
)(msg
.len
[3] << 24);
558 // Don't attempt to read if the msg was zero bytes long.
561 total
= DoRead(buffer
, len
);
569 char *discard_buffer
= new char[MAX_DISCARD_SIZE
];
572 // NOTE: discarded bytes don't add to m_lcount.
575 discard_len
= ((len2
> MAX_DISCARD_SIZE
)? MAX_DISCARD_SIZE
: len2
);
576 discard_len
= DoRead(discard_buffer
, (wxUint32
)discard_len
);
577 len2
-= (wxUint32
)discard_len
;
579 while ((discard_len
> 0) && len2
);
581 delete [] discard_buffer
;
586 if (DoRead(&msg
, sizeof(msg
)) != sizeof(msg
))
589 sig
= (wxUint32
)msg
.sig
[0];
590 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
591 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
592 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
594 if (sig
!= 0xdeadfeed)
596 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
612 wxSocketBase
& wxSocketBase::Peek(void* buffer
, wxUint32 nbytes
)
617 m_lcount
= DoRead(buffer
, nbytes
);
618 Pushback(buffer
, m_lcount
);
620 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
621 if (m_flags
& wxSOCKET_WAITALL
)
622 m_error
= (m_lcount
!= nbytes
);
624 m_error
= (m_lcount
== 0);
626 // Allow read events again
632 wxSocketBase
& wxSocketBase::Write(const void *buffer
, wxUint32 nbytes
)
637 m_lcount
= DoWrite(buffer
, nbytes
);
639 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
640 if (m_flags
& wxSOCKET_WAITALL
)
641 m_error
= (m_lcount
!= nbytes
);
643 m_error
= (m_lcount
== 0);
645 // Allow write events again
651 // This function is a mirror image of DoRead() except that it doesn't use the
652 // push back buffer, please see comments there
653 wxUint32
wxSocketBase::DoWrite(const void *buffer_
, wxUint32 nbytes
)
655 const char *buffer
= static_cast<const char *>(buffer_
);
657 // Return if there is nothing to read or the socket is (already?) closed.
658 if ( !m_socket
|| !nbytes
)
661 wxCHECK_MSG( buffer
, 0, "NULL buffer" );
664 if ( m_flags
& wxSOCKET_NOWAIT
)
666 wxSocketUnblocker
unblock(m_socket
);
667 const int ret
= m_socket
->Write(buffer
, nbytes
);
671 else // blocking socket
675 if ( !(m_flags
& wxSOCKET_BLOCK
) && !WaitForWrite() )
678 const int ret
= m_socket
->Write(buffer
, nbytes
);
689 if ( !(m_flags
& wxSOCKET_WAITALL
) )
703 wxSocketBase
& wxSocketBase::WriteMsg(const void *buffer
, wxUint32 nbytes
)
709 unsigned char sig
[4];
710 unsigned char len
[4];
718 SetFlags((m_flags
& wxSOCKET_BLOCK
) | wxSOCKET_WAITALL
);
720 msg
.sig
[0] = (unsigned char) 0xad;
721 msg
.sig
[1] = (unsigned char) 0xde;
722 msg
.sig
[2] = (unsigned char) 0xed;
723 msg
.sig
[3] = (unsigned char) 0xfe;
725 msg
.len
[0] = (unsigned char) (nbytes
& 0xff);
726 msg
.len
[1] = (unsigned char) ((nbytes
>> 8) & 0xff);
727 msg
.len
[2] = (unsigned char) ((nbytes
>> 16) & 0xff);
728 msg
.len
[3] = (unsigned char) ((nbytes
>> 24) & 0xff);
730 if (DoWrite(&msg
, sizeof(msg
)) < sizeof(msg
))
733 total
= DoWrite(buffer
, nbytes
);
738 msg
.sig
[0] = (unsigned char) 0xed;
739 msg
.sig
[1] = (unsigned char) 0xfe;
740 msg
.sig
[2] = (unsigned char) 0xad;
741 msg
.sig
[3] = (unsigned char) 0xde;
745 msg
.len
[3] = (char) 0;
747 if ((DoWrite(&msg
, sizeof(msg
))) < sizeof(msg
))
761 wxSocketBase
& wxSocketBase::Unread(const void *buffer
, wxUint32 nbytes
)
764 Pushback(buffer
, nbytes
);
772 wxSocketBase
& wxSocketBase::Discard()
774 char *buffer
= new char[MAX_DISCARD_SIZE
];
781 SetFlags(wxSOCKET_NOWAIT
);
785 ret
= DoRead(buffer
, MAX_DISCARD_SIZE
);
788 while (ret
== MAX_DISCARD_SIZE
);
794 // Allow read events again
800 // --------------------------------------------------------------------------
802 // --------------------------------------------------------------------------
805 * Polls the socket to determine its status. This function will
806 * check for the events specified in the 'flags' parameter, and
807 * it will return a mask indicating which operations can be
808 * performed. This function won't block, regardless of the
809 * mode (blocking | nonblocking) of the socket.
811 GSocketEventFlags
GSocketBase::Select(GSocketEventFlags flags
)
815 GSocketEventFlags result
= 0;
822 return (GSOCK_LOST_FLAG
& flags
);
824 /* Do not use a static struct, Linux can garble it */
829 wxFD_ZERO(&writefds
);
830 wxFD_ZERO(&exceptfds
);
831 wxFD_SET(m_fd
, &readfds
);
832 if (flags
& GSOCK_OUTPUT_FLAG
|| flags
& GSOCK_CONNECTION_FLAG
)
833 wxFD_SET(m_fd
, &writefds
);
834 wxFD_SET(m_fd
, &exceptfds
);
836 /* Check 'sticky' CONNECTION flag first */
837 result
|= GSOCK_CONNECTION_FLAG
& m_detected
;
839 /* If we have already detected a LOST event, then don't try
840 * to do any further processing.
842 if ((m_detected
& GSOCK_LOST_FLAG
) != 0)
844 m_establishing
= false;
845 return (GSOCK_LOST_FLAG
& flags
);
849 if (select(m_fd
+ 1, &readfds
, &writefds
, &exceptfds
, &tv
) < 0)
851 /* What to do here? */
852 return (result
& flags
);
855 /* Check for exceptions and errors */
856 if (wxFD_ISSET(m_fd
, &exceptfds
))
858 m_establishing
= false;
859 m_detected
= GSOCK_LOST_FLAG
;
861 /* LOST event: Abort any further processing */
862 return (GSOCK_LOST_FLAG
& flags
);
865 /* Check for readability */
866 if (wxFD_ISSET(m_fd
, &readfds
))
868 result
|= GSOCK_INPUT_FLAG
;
870 if (m_server
&& m_stream
)
872 /* This is a TCP server socket that detected a connection.
873 While the INPUT_FLAG is also set, it doesn't matter on
874 this kind of sockets, as we can only Accept() from them. */
875 m_detected
|= GSOCK_CONNECTION_FLAG
;
879 /* Check for writability */
880 if (wxFD_ISSET(m_fd
, &writefds
))
882 if (m_establishing
&& !m_server
)
885 SOCKOPTLEN_T len
= sizeof(error
);
886 m_establishing
= false;
887 getsockopt(m_fd
, SOL_SOCKET
, SO_ERROR
, (char*)&error
, &len
);
891 m_detected
= GSOCK_LOST_FLAG
;
893 /* LOST event: Abort any further processing */
894 return (GSOCK_LOST_FLAG
& flags
);
898 m_detected
|= GSOCK_CONNECTION_FLAG
;
903 result
|= GSOCK_OUTPUT_FLAG
;
907 return (result
| m_detected
) & flags
;
910 // All Wait functions poll the socket using GSocket_Select() to
911 // check for the specified combination of conditions, until one
912 // of these conditions become true, an error occurs, or the
913 // timeout elapses. The polling loop runs the event loop so that
914 // this won't block the GUI.
917 wxSocketBase::DoWait(long seconds
, long milliseconds
, wxSocketEventFlags flags
)
919 wxCHECK_MSG( m_socket
, false, "can't wait on invalid socket" );
921 // This can be set to true from Interrupt() to exit this function a.s.a.p.
925 // Use either the provided timeout or the default timeout value associated
928 // TODO: allow waiting forever, see #9443
929 const long timeout
= seconds
== -1 ? m_timeout
* 1000
930 : seconds
* 1000 + milliseconds
;
931 const wxMilliClock_t timeEnd
= wxGetLocalTimeMillis() + timeout
;
933 // Get the active event loop which we'll use for the message dispatching
934 // when running in the main thread
935 wxEventLoopBase
*eventLoop
;
936 if ( wxIsMainThread() )
938 eventLoop
= wxEventLoop::GetActive();
940 else // in worker thread
942 // We never dispatch messages from threads other than the main one.
946 // Wait in an active polling loop: notice that the loop is executed at
947 // least once, even if timeout is 0 (i.e. polling).
948 bool gotEvent
= false;
951 // We always stop waiting when the connection is lost as it doesn't
952 // make sense to continue further, even if GSOCK_LOST_FLAG is not
953 // specified in flags to wait for.
954 const GSocketEventFlags
955 result
= m_socket
->Select(flags
| GSOCK_LOST_FLAG
);
957 // Incoming connection (server) or connection established (client)?
958 if ( result
& GSOCK_CONNECTION_FLAG
)
961 m_establishing
= false;
966 // Data available or output buffer ready?
967 if ( (result
& GSOCK_INPUT_FLAG
) || (result
& GSOCK_OUTPUT_FLAG
) )
974 if ( result
& GSOCK_LOST_FLAG
)
977 m_establishing
= false;
978 if ( flags
& GSOCK_LOST_FLAG
)
987 const wxMilliClock_t timeNow
= wxGetLocalTimeMillis();
988 if ( timeNow
>= timeEnd
)
993 // This function is only called if wxSOCKET_BLOCK flag was not used
994 // and so we should dispatch the events if there is an event loop
995 // capable of doing it.
996 if ( eventLoop
->Pending() )
997 eventLoop
->Dispatch();
1000 else // no event loop or waiting in another thread
1002 // We're busy waiting but at least give up the rest of our current
1006 #endif // wxUSE_THREADS
1012 bool wxSocketBase::Wait(long seconds
, long milliseconds
)
1014 return DoWait(seconds
, milliseconds
,
1017 GSOCK_CONNECTION_FLAG
|
1022 bool wxSocketBase::WaitForRead(long seconds
, long milliseconds
)
1024 // Check pushback buffer before entering DoWait
1028 // Note that GSOCK_INPUT_LOST has to be explicitly passed to DoWait
1029 // because of the semantics of WaitForRead: a return value of true means
1030 // that a GSocket_Read call will return immediately, not that there is
1031 // actually data to read.
1032 return DoWait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
| GSOCK_LOST_FLAG
);
1036 bool wxSocketBase::WaitForWrite(long seconds
, long milliseconds
)
1038 return DoWait(seconds
, milliseconds
, GSOCK_OUTPUT_FLAG
| GSOCK_LOST_FLAG
);
1041 bool wxSocketBase::WaitForLost(long seconds
, long milliseconds
)
1043 return DoWait(seconds
, milliseconds
, GSOCK_LOST_FLAG
);
1046 // --------------------------------------------------------------------------
1048 // --------------------------------------------------------------------------
1051 // Get local or peer address
1054 bool wxSocketBase::GetPeer(wxSockAddress
& addr_man
) const
1061 peer
= m_socket
->GetPeer();
1063 // copying a null address would just trigger an assert anyway
1068 addr_man
.SetAddress(peer
);
1069 GAddress_destroy(peer
);
1074 bool wxSocketBase::GetLocal(wxSockAddress
& addr_man
) const
1081 local
= m_socket
->GetLocal();
1082 addr_man
.SetAddress(local
);
1083 GAddress_destroy(local
);
1089 // Save and restore socket state
1092 void wxSocketBase::SaveState()
1094 wxSocketState
*state
;
1096 state
= new wxSocketState();
1098 state
->m_flags
= m_flags
;
1099 state
->m_notify
= m_notify
;
1100 state
->m_eventmask
= m_eventmask
;
1101 state
->m_clientData
= m_clientData
;
1103 m_states
.Append(state
);
1106 void wxSocketBase::RestoreState()
1108 wxList::compatibility_iterator node
;
1109 wxSocketState
*state
;
1111 node
= m_states
.GetLast();
1115 state
= (wxSocketState
*)node
->GetData();
1117 m_flags
= state
->m_flags
;
1118 m_notify
= state
->m_notify
;
1119 m_eventmask
= state
->m_eventmask
;
1120 m_clientData
= state
->m_clientData
;
1122 m_states
.Erase(node
);
1127 // Timeout and flags
1130 void wxSocketBase::SetTimeout(long seconds
)
1132 m_timeout
= seconds
;
1135 m_socket
->SetTimeout(m_timeout
* 1000);
1138 void wxSocketBase::SetFlags(wxSocketFlags flags
)
1140 // Do some sanity checking on the flags used: not all values can be used
1142 wxASSERT_MSG( !(flags
& wxSOCKET_NOWAIT
) ||
1143 !(flags
& (wxSOCKET_WAITALL
| wxSOCKET_BLOCK
)),
1144 "Using wxSOCKET_WAITALL or wxSOCKET_BLOCK with "
1145 "wxSOCKET_NOWAIT doesn't make sense" );
1151 // --------------------------------------------------------------------------
1153 // --------------------------------------------------------------------------
1155 // A note on how events are processed, which is probably the most
1156 // difficult thing to get working right while keeping the same API
1157 // and functionality for all platforms.
1159 // When GSocket detects an event, it calls wx_socket_callback, which in
1160 // turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
1161 // object. OnRequest does some housekeeping, and if the event is to be
1162 // propagated to the user, it creates a new wxSocketEvent object and
1163 // posts it. The event is not processed immediately, but delayed with
1164 // AddPendingEvent instead. This is necessary in order to decouple the
1165 // event processing from wx_socket_callback; otherwise, subsequent IO
1166 // calls made from the user event handler would fail, as gtk callbacks
1167 // are not reentrant.
1169 // Note that, unlike events, user callbacks (now deprecated) are _not_
1170 // decoupled from wx_socket_callback and thus they suffer from a variety
1171 // of problems. Avoid them where possible and use events instead.
1174 void LINKAGEMODE
wx_socket_callback(GSocket
* WXUNUSED(socket
),
1175 GSocketEvent notification
,
1178 wxSocketBase
*sckobj
= (wxSocketBase
*)cdata
;
1180 sckobj
->OnRequest((wxSocketNotify
) notification
);
1183 void wxSocketBase::OnRequest(wxSocketNotify notification
)
1185 switch(notification
)
1187 case wxSOCKET_CONNECTION
:
1188 m_establishing
= false;
1192 // If we are in the middle of a R/W operation, do not
1193 // propagate events to users. Also, filter 'late' events
1194 // which are no longer valid.
1196 case wxSOCKET_INPUT
:
1197 if (m_reading
|| !m_socket
->Select(GSOCK_INPUT_FLAG
))
1201 case wxSOCKET_OUTPUT
:
1202 if (m_writing
|| !m_socket
->Select(GSOCK_OUTPUT_FLAG
))
1207 m_connected
= false;
1208 m_establishing
= false;
1212 // Schedule the event
1214 wxSocketEventFlags flag
= 0;
1216 switch (notification
)
1218 case GSOCK_INPUT
: flag
= GSOCK_INPUT_FLAG
; break;
1219 case GSOCK_OUTPUT
: flag
= GSOCK_OUTPUT_FLAG
; break;
1220 case GSOCK_CONNECTION
: flag
= GSOCK_CONNECTION_FLAG
; break;
1221 case GSOCK_LOST
: flag
= GSOCK_LOST_FLAG
; break;
1223 wxLogWarning(_("wxSocket: unknown event!."));
1227 if (((m_eventmask
& flag
) == flag
) && m_notify
)
1231 wxSocketEvent
event(m_id
);
1232 event
.m_event
= notification
;
1233 event
.m_clientData
= m_clientData
;
1234 event
.SetEventObject(this);
1236 m_handler
->AddPendingEvent(event
);
1241 void wxSocketBase::Notify(bool notify
)
1245 m_socket
->Notify(notify
);
1248 void wxSocketBase::SetNotify(wxSocketEventFlags flags
)
1250 m_eventmask
= flags
;
1253 void wxSocketBase::SetEventHandler(wxEvtHandler
& handler
, int id
)
1255 m_handler
= &handler
;
1259 // --------------------------------------------------------------------------
1261 // --------------------------------------------------------------------------
1263 void wxSocketBase::Pushback(const void *buffer
, wxUint32 size
)
1267 if (m_unread
== NULL
)
1268 m_unread
= malloc(size
);
1273 tmp
= malloc(m_unrd_size
+ size
);
1274 memcpy((char *)tmp
+ size
, m_unread
, m_unrd_size
);
1280 m_unrd_size
+= size
;
1282 memcpy(m_unread
, buffer
, size
);
1285 wxUint32
wxSocketBase::GetPushback(void *buffer
, wxUint32 size
, bool peek
)
1287 wxCHECK_MSG( buffer
, 0, "NULL buffer" );
1292 if (size
> (m_unrd_size
-m_unrd_cur
))
1293 size
= m_unrd_size
-m_unrd_cur
;
1295 memcpy(buffer
, (char *)m_unread
+ m_unrd_cur
, size
);
1300 if (m_unrd_size
== m_unrd_cur
)
1313 // ==========================================================================
1315 // ==========================================================================
1317 // --------------------------------------------------------------------------
1319 // --------------------------------------------------------------------------
1321 wxSocketServer::wxSocketServer(const wxSockAddress
& addr_man
,
1322 wxSocketFlags flags
)
1323 : wxSocketBase(flags
, wxSOCKET_SERVER
)
1325 wxLogTrace( wxTRACE_Socket
, _T("Opening wxSocketServer") );
1327 m_socket
= GSocket::Create();
1331 wxLogTrace( wxTRACE_Socket
, _T("*** GSocket_new failed") );
1335 // Setup the socket as server
1336 m_socket
->Notify(m_notify
);
1337 m_socket
->SetLocal(addr_man
.GetAddress());
1339 if (GetFlags() & wxSOCKET_REUSEADDR
) {
1340 m_socket
->SetReusable();
1342 if (GetFlags() & wxSOCKET_BROADCAST
) {
1343 m_socket
->SetBroadcast();
1345 if (GetFlags() & wxSOCKET_NOBIND
) {
1346 m_socket
->DontDoBind();
1349 if (m_socket
->SetServer() != GSOCK_NOERROR
)
1354 wxLogTrace( wxTRACE_Socket
, _T("*** GSocket_SetServer failed") );
1358 m_socket
->SetTimeout(m_timeout
* 1000);
1359 m_socket
->SetCallback(GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1360 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1361 wx_socket_callback
, (char *)this);
1363 wxLogTrace( wxTRACE_Socket
, _T("wxSocketServer on fd %d"), m_socket
->m_fd
);
1366 // --------------------------------------------------------------------------
1368 // --------------------------------------------------------------------------
1370 bool wxSocketServer::AcceptWith(wxSocketBase
& sock
, bool wait
)
1375 // If wait == false, then the call should be nonblocking.
1376 // When we are finished, we put the socket to blocking mode
1378 wxSocketUnblocker
unblock(m_socket
, !wait
);
1379 GSocket
* const child_socket
= m_socket
->WaitConnection();
1384 sock
.m_type
= wxSOCKET_BASE
;
1385 sock
.m_socket
= child_socket
;
1386 sock
.m_connected
= true;
1388 sock
.m_socket
->SetTimeout(sock
.m_timeout
* 1000);
1389 sock
.m_socket
->SetCallback(GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1390 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1391 wx_socket_callback
, (char *)&sock
);
1396 wxSocketBase
*wxSocketServer::Accept(bool wait
)
1398 wxSocketBase
* sock
= new wxSocketBase();
1400 sock
->SetFlags(m_flags
);
1402 if (!AcceptWith(*sock
, wait
))
1411 bool wxSocketServer::WaitForAccept(long seconds
, long milliseconds
)
1413 return DoWait(seconds
, milliseconds
, GSOCK_CONNECTION_FLAG
);
1416 bool wxSocketBase::GetOption(int level
, int optname
, void *optval
, int *optlen
)
1418 wxASSERT_MSG( m_socket
, _T("Socket not initialised") );
1420 if (m_socket
->GetSockOpt(level
, optname
, optval
, optlen
)
1428 bool wxSocketBase::SetOption(int level
, int optname
, const void *optval
,
1431 wxASSERT_MSG( m_socket
, _T("Socket not initialised") );
1433 if (m_socket
->SetSockOpt(level
, optname
, optval
, optlen
)
1441 bool wxSocketBase::SetLocal(const wxIPV4address
& local
)
1443 GAddress
* la
= local
.GetAddress();
1445 // If the address is valid, save it for use when we call Connect
1446 if (la
&& la
->m_addr
)
1448 m_localAddress
= local
;
1456 // ==========================================================================
1458 // ==========================================================================
1460 // --------------------------------------------------------------------------
1462 // --------------------------------------------------------------------------
1464 wxSocketClient::wxSocketClient(wxSocketFlags flags
)
1465 : wxSocketBase(flags
, wxSOCKET_CLIENT
)
1467 m_initialRecvBufferSize
=
1468 m_initialSendBufferSize
= -1;
1471 wxSocketClient::~wxSocketClient()
1475 // --------------------------------------------------------------------------
1477 // --------------------------------------------------------------------------
1479 bool wxSocketClient::DoConnect(const wxSockAddress
& addr_man
,
1480 const wxSockAddress
* local
,
1485 // Shutdown and destroy the socket
1490 m_socket
= GSocket::Create();
1491 m_connected
= false;
1492 m_establishing
= false;
1497 m_socket
->SetTimeout(m_timeout
* 1000);
1498 m_socket
->SetCallback(
1502 GSOCK_CONNECTION_FLAG
,
1507 // If wait == false, then the call should be nonblocking. When we are
1508 // finished, we put the socket to blocking mode again.
1509 wxSocketUnblocker
unblock(m_socket
, !wait
);
1511 // Reuse makes sense for clients too, if we are trying to rebind to the same port
1512 if (GetFlags() & wxSOCKET_REUSEADDR
)
1514 m_socket
->SetReusable();
1516 if (GetFlags() & wxSOCKET_BROADCAST
)
1518 m_socket
->SetBroadcast();
1520 if (GetFlags() & wxSOCKET_NOBIND
)
1522 m_socket
->DontDoBind();
1525 // If no local address was passed and one has been set, use the one that was Set
1526 if (!local
&& m_localAddress
.GetAddress())
1528 local
= &m_localAddress
;
1531 // Bind to the local IP address and port, when provided
1534 GAddress
* la
= local
->GetAddress();
1536 if (la
&& la
->m_addr
)
1537 m_socket
->SetLocal(la
);
1540 #if defined(__WXMSW__) || defined(__WXGTK__)
1541 m_socket
->SetInitialSocketBuffers(m_initialRecvBufferSize
, m_initialSendBufferSize
);
1544 m_socket
->SetPeer(addr_man
.GetAddress());
1545 const GSocketError err
= m_socket
->Connect(GSOCK_STREAMED
);
1547 //this will register for callbacks - must be called after m_socket->m_fd was initialized
1548 m_socket
->Notify(m_notify
);
1550 if (err
!= GSOCK_NOERROR
)
1552 if (err
== GSOCK_WOULDBLOCK
)
1553 m_establishing
= true;
1562 bool wxSocketClient::Connect(const wxSockAddress
& addr_man
, bool wait
)
1564 return DoConnect(addr_man
, NULL
, wait
);
1567 bool wxSocketClient::Connect(const wxSockAddress
& addr_man
,
1568 const wxSockAddress
& local
,
1571 return DoConnect(addr_man
, &local
, wait
);
1574 bool wxSocketClient::WaitOnConnect(long seconds
, long milliseconds
)
1578 // this happens if the initial attempt to connect succeeded without
1583 wxCHECK_MSG( m_establishing
&& m_socket
, false,
1584 "No connection establishment attempt in progress" );
1586 // we must specify GSOCK_LOST_FLAG here explicitly because we must return
1587 // true if the connection establishment process is finished, whether it is
1588 // over because we successfully connected or because we were not able to
1590 return DoWait(seconds
, milliseconds
,
1591 GSOCK_CONNECTION_FLAG
| GSOCK_LOST_FLAG
);
1594 // ==========================================================================
1596 // ==========================================================================
1598 /* NOTE: experimental stuff - might change */
1600 wxDatagramSocket::wxDatagramSocket( const wxSockAddress
& addr
,
1601 wxSocketFlags flags
)
1602 : wxSocketBase( flags
, wxSOCKET_DATAGRAM
)
1604 // Create the socket
1605 m_socket
= GSocket::Create();
1609 wxFAIL_MSG( _T("datagram socket not new'd") );
1612 m_socket
->Notify(m_notify
);
1613 // Setup the socket as non connection oriented
1614 m_socket
->SetLocal(addr
.GetAddress());
1615 if (flags
& wxSOCKET_REUSEADDR
)
1617 m_socket
->SetReusable();
1619 if (GetFlags() & wxSOCKET_BROADCAST
)
1621 m_socket
->SetBroadcast();
1623 if (GetFlags() & wxSOCKET_NOBIND
)
1625 m_socket
->DontDoBind();
1627 if ( m_socket
->SetNonOriented() != GSOCK_NOERROR
)
1634 // Initialize all stuff
1635 m_connected
= false;
1636 m_establishing
= false;
1637 m_socket
->SetTimeout( m_timeout
* 1000 );
1638 m_socket
->SetCallback( GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1639 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1640 wx_socket_callback
, (char*)this );
1643 wxDatagramSocket
& wxDatagramSocket::RecvFrom( wxSockAddress
& addr
,
1652 wxDatagramSocket
& wxDatagramSocket::SendTo( const wxSockAddress
& addr
,
1656 wxASSERT_MSG( m_socket
, _T("Socket not initialised") );
1658 m_socket
->SetPeer(addr
.GetAddress());
1663 // ==========================================================================
1665 // ==========================================================================
1667 class wxSocketModule
: public wxModule
1670 virtual bool OnInit()
1672 // wxSocketBase will call GSocket_Init() itself when/if needed
1676 virtual void OnExit()
1678 if ( wxSocketBase::IsInitialized() )
1679 wxSocketBase::Shutdown();
1683 DECLARE_DYNAMIC_CLASS(wxSocketModule
)
1686 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule
, wxModule
)
1688 #endif // wxUSE_SOCKETS