1 /////////////////////////////////////////////////////////////////////////////
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: see wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ==========================================================================
14 // ==========================================================================
17 #pragma implementation "socket.h"
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
30 #include "wx/apptrait.h"
32 #include "wx/object.h"
33 #include "wx/string.h"
36 #include "wx/module.h"
41 #include "wx/sckaddr.h"
42 #include "wx/socket.h"
44 // --------------------------------------------------------------------------
45 // macros and constants
46 // --------------------------------------------------------------------------
49 #define MAX_DISCARD_SIZE (10 * 1024)
51 // what to do within waits: we have 2 cases: from the main thread itself we
52 // have to call wxYield() to let the events (including the GUI events and the
53 // low-level (not wxWindows) events from GSocket) be processed. From another
54 // thread it is enough to just call wxThread::Yield() which will give away the
55 // rest of our time slice: the explanation is that the events will be processed
56 // by the main thread anyhow, without calling wxYield(), but we don't want to
57 // eat the CPU time uselessly while sitting in the loop waiting for the data
59 #define PROCESS_EVENTS() \
61 if ( wxThread::IsMain() ) \
66 #else // !wxUSE_THREADS
67 #define PROCESS_EVENTS() wxYield()
68 #endif // wxUSE_THREADS/!wxUSE_THREADS
70 #define wxTRACE_Socket _T("wxSocket")
72 // --------------------------------------------------------------------------
74 // --------------------------------------------------------------------------
76 IMPLEMENT_CLASS(wxSocketBase
, wxObject
)
77 IMPLEMENT_CLASS(wxSocketServer
, wxSocketBase
)
78 IMPLEMENT_CLASS(wxSocketClient
, wxSocketBase
)
79 IMPLEMENT_CLASS(wxDatagramSocket
, wxSocketBase
)
80 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent
, wxEvent
)
82 // --------------------------------------------------------------------------
84 // --------------------------------------------------------------------------
86 class wxSocketState
: public wxObject
89 wxSocketFlags m_flags
;
90 wxSocketEventFlags m_eventmask
;
93 #if WXWIN_COMPATIBILITY
94 wxSocketBase::wxSockCbk m_cbk
;
96 #endif // WXWIN_COMPATIBILITY
99 wxSocketState() : wxObject() {}
101 DECLARE_NO_COPY_CLASS(wxSocketState
)
104 // ==========================================================================
106 // ==========================================================================
108 // --------------------------------------------------------------------------
109 // Initialization and shutdown
110 // --------------------------------------------------------------------------
112 // FIXME-MT: all this is MT-unsafe, of course, we should protect all accesses
113 // to m_countInit with a crit section
114 size_t wxSocketBase::m_countInit
= 0;
116 bool wxSocketBase::IsInitialized()
118 return m_countInit
> 0;
121 bool wxSocketBase::Initialize()
123 if ( !m_countInit
++ )
125 if ( !GSocket_Init() )
136 void wxSocketBase::Shutdown()
138 // we should be initialized
139 wxASSERT_MSG( m_countInit
, _T("extra call to Shutdown()") );
140 if ( !--m_countInit
)
146 // --------------------------------------------------------------------------
148 // --------------------------------------------------------------------------
150 void wxSocketBase::Init()
153 m_type
= wxSOCKET_UNINIT
;
164 m_beingDeleted
= FALSE
;
177 #if WXWIN_COMPATIBILITY
180 #endif // WXWIN_COMPATIBILITY
182 if ( !IsInitialized() )
184 // this Initialize() will be undone by wxSocketModule::OnExit(), all the
185 // other calls to it should be matched by a call to Shutdown()
190 wxSocketBase::wxSocketBase()
195 wxSocketBase::wxSocketBase(wxSocketFlags flags
, wxSocketType type
)
203 wxSocketBase::~wxSocketBase()
205 // Just in case the app called Destroy() *and* then deleted
206 // the socket immediately: don't leave dangling pointers.
207 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
209 traits
->RemoveFromPendingDelete(this);
211 // Shutdown and close the socket
215 // Destroy the GSocket object
217 GSocket_destroy(m_socket
);
219 // Free the pushback buffer
224 bool wxSocketBase::Destroy()
226 // Delayed destruction: the socket will be deleted during the next
227 // idle loop iteration. This ensures that all pending events have
229 m_beingDeleted
= TRUE
;
231 // Shutdown and close the socket
234 // Supress events from now on
237 // schedule this object for deletion
238 wxAppTraits
*traits
= wxTheApp
? wxTheApp
->GetTraits() : NULL
;
241 // let the traits object decide what to do with us
242 traits
->ScheduleForDestroy(this);
244 else // no app or no traits
246 // in wxBase we might have no app object at all, don't leak memory
253 // --------------------------------------------------------------------------
255 // --------------------------------------------------------------------------
257 // The following IO operations update m_error and m_lcount:
258 // {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
260 // TODO: Should Connect, Accept and AcceptWith update m_error?
262 bool wxSocketBase::Close()
264 // Interrupt pending waits
270 GSocket_UnsetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
271 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
);
273 // Shutdown the connection
274 GSocket_Shutdown(m_socket
);
278 m_establishing
= FALSE
;
282 wxSocketBase
& wxSocketBase::Read(void* buffer
, wxUint32 nbytes
)
287 m_lcount
= _Read(buffer
, nbytes
);
289 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
290 if (m_flags
& wxSOCKET_WAITALL
)
291 m_error
= (m_lcount
!= nbytes
);
293 m_error
= (m_lcount
== 0);
295 // Allow read events from now on
301 wxUint32
wxSocketBase::_Read(void* buffer
, wxUint32 nbytes
)
306 // Try the pushback buffer first
307 total
= GetPushback(buffer
, nbytes
, FALSE
);
309 buffer
= (char *)buffer
+ total
;
311 // Return now in one of the following cases:
312 // - the socket is invalid,
313 // - we got all the data,
314 // - we got *some* data and we are not using wxSOCKET_WAITALL.
317 ((total
!= 0) && !(m_flags
& wxSOCKET_WAITALL
)) )
320 // Possible combinations (they are checked in this order)
322 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
326 if (m_flags
& wxSOCKET_NOWAIT
)
328 GSocket_SetNonBlocking(m_socket
, 1);
329 ret
= GSocket_Read(m_socket
, (char *)buffer
, nbytes
);
330 GSocket_SetNonBlocking(m_socket
, 0);
341 if ( !(m_flags
& wxSOCKET_BLOCK
) && !WaitForRead() )
344 ret
= GSocket_Read(m_socket
, (char *)buffer
, nbytes
);
350 buffer
= (char *)buffer
+ ret
;
353 // If we got here and wxSOCKET_WAITALL is not set, we can leave
354 // now. Otherwise, wait until we recv all the data or until there
357 more
= (ret
> 0 && nbytes
> 0 && (m_flags
& wxSOCKET_WAITALL
));
364 wxSocketBase
& wxSocketBase::ReadMsg(void* buffer
, wxUint32 nbytes
)
366 wxUint32 len
, len2
, sig
, total
;
371 unsigned char sig
[4];
372 unsigned char len
[4];
381 SetFlags((m_flags
& wxSOCKET_BLOCK
) | wxSOCKET_WAITALL
);
383 if (_Read(&msg
, sizeof(msg
)) != sizeof(msg
))
386 sig
= (wxUint32
)msg
.sig
[0];
387 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
388 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
389 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
391 if (sig
!= 0xfeeddead)
393 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
397 len
= (wxUint32
)msg
.len
[0];
398 len
|= (wxUint32
)(msg
.len
[1] << 8);
399 len
|= (wxUint32
)(msg
.len
[2] << 16);
400 len
|= (wxUint32
)(msg
.len
[3] << 24);
410 // Don't attemp to read if the msg was zero bytes long.
413 total
= _Read(buffer
, len
);
420 char *discard_buffer
= new char[MAX_DISCARD_SIZE
];
423 // NOTE: discarded bytes don't add to m_lcount.
426 discard_len
= ((len2
> MAX_DISCARD_SIZE
)? MAX_DISCARD_SIZE
: len2
);
427 discard_len
= _Read(discard_buffer
, (wxUint32
)discard_len
);
428 len2
-= (wxUint32
)discard_len
;
430 while ((discard_len
> 0) && len2
);
432 delete [] discard_buffer
;
437 if (_Read(&msg
, sizeof(msg
)) != sizeof(msg
))
440 sig
= (wxUint32
)msg
.sig
[0];
441 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
442 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
443 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
445 if (sig
!= 0xdeadfeed)
447 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
463 wxSocketBase
& wxSocketBase::Peek(void* buffer
, wxUint32 nbytes
)
468 m_lcount
= _Read(buffer
, nbytes
);
469 Pushback(buffer
, m_lcount
);
471 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
472 if (m_flags
& wxSOCKET_WAITALL
)
473 m_error
= (m_lcount
!= nbytes
);
475 m_error
= (m_lcount
== 0);
477 // Allow read events again
483 wxSocketBase
& wxSocketBase::Write(const void *buffer
, wxUint32 nbytes
)
488 m_lcount
= _Write(buffer
, nbytes
);
490 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
491 if (m_flags
& wxSOCKET_WAITALL
)
492 m_error
= (m_lcount
!= nbytes
);
494 m_error
= (m_lcount
== 0);
496 // Allow write events again
502 wxUint32
wxSocketBase::_Write(const void *buffer
, wxUint32 nbytes
)
507 // If the socket is invalid or parameters are ill, return immediately
508 if (!m_socket
|| !buffer
|| !nbytes
)
511 // Possible combinations (they are checked in this order)
513 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
517 if (m_flags
& wxSOCKET_NOWAIT
)
519 GSocket_SetNonBlocking(m_socket
, 1);
520 ret
= GSocket_Write(m_socket
, (const char *)buffer
, nbytes
);
521 GSocket_SetNonBlocking(m_socket
, 0);
532 if ( !(m_flags
& wxSOCKET_BLOCK
) && !WaitForWrite() )
535 ret
= GSocket_Write(m_socket
, (const char *)buffer
, nbytes
);
541 buffer
= (const char *)buffer
+ ret
;
544 // If we got here and wxSOCKET_WAITALL is not set, we can leave
545 // now. Otherwise, wait until we send all the data or until there
548 more
= (ret
> 0 && nbytes
> 0 && (m_flags
& wxSOCKET_WAITALL
));
555 wxSocketBase
& wxSocketBase::WriteMsg(const void *buffer
, wxUint32 nbytes
)
562 unsigned char sig
[4];
563 unsigned char len
[4];
572 SetFlags((m_flags
& wxSOCKET_BLOCK
) | wxSOCKET_WAITALL
);
574 msg
.sig
[0] = (unsigned char) 0xad;
575 msg
.sig
[1] = (unsigned char) 0xde;
576 msg
.sig
[2] = (unsigned char) 0xed;
577 msg
.sig
[3] = (unsigned char) 0xfe;
579 msg
.len
[0] = (unsigned char) (nbytes
& 0xff);
580 msg
.len
[1] = (unsigned char) ((nbytes
>> 8) & 0xff);
581 msg
.len
[2] = (unsigned char) ((nbytes
>> 16) & 0xff);
582 msg
.len
[3] = (unsigned char) ((nbytes
>> 24) & 0xff);
584 if (_Write(&msg
, sizeof(msg
)) < sizeof(msg
))
587 total
= _Write(buffer
, nbytes
);
592 msg
.sig
[0] = (unsigned char) 0xed;
593 msg
.sig
[1] = (unsigned char) 0xfe;
594 msg
.sig
[2] = (unsigned char) 0xad;
595 msg
.sig
[3] = (unsigned char) 0xde;
596 msg
.len
[0] = msg
.len
[1] = msg
.len
[2] = msg
.len
[3] = (char) 0;
598 if ((_Write(&msg
, sizeof(msg
))) < sizeof(msg
))
612 wxSocketBase
& wxSocketBase::Unread(const void *buffer
, wxUint32 nbytes
)
615 Pushback(buffer
, nbytes
);
623 wxSocketBase
& wxSocketBase::Discard()
626 char *buffer
= new char[MAX_DISCARD_SIZE
];
634 SetFlags(wxSOCKET_NOWAIT
);
638 ret
= _Read(buffer
, MAX_DISCARD_SIZE
);
641 while (ret
== MAX_DISCARD_SIZE
);
647 // Allow read events again
653 // --------------------------------------------------------------------------
655 // --------------------------------------------------------------------------
657 // All Wait functions poll the socket using GSocket_Select() to
658 // check for the specified combination of conditions, until one
659 // of these conditions become true, an error occurs, or the
660 // timeout elapses. The polling loop calls PROCESS_EVENTS(), so
661 // this won't block the GUI.
663 bool wxSocketBase::_Wait(long seconds
,
665 wxSocketEventFlags flags
)
667 GSocketEventFlags result
;
670 // Set this to TRUE to interrupt ongoing waits
673 // Check for valid socket
677 // Check for valid timeout value.
679 timeout
= seconds
* 1000 + milliseconds
;
681 timeout
= m_timeout
* 1000;
683 // Wait in an active polling loop.
685 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
686 // hurt. It has to be here because the (GSocket) event might arrive
687 // a bit delayed, and it has to be in OnRequest as well because we
688 // don't know whether the Wait functions are being used.
690 // Do this at least once (important if timeout == 0, when
691 // we are just polling). Also, if just polling, do not yield.
698 result
= GSocket_Select(m_socket
, flags
| GSOCK_LOST_FLAG
);
700 // Incoming connection (server) or connection established (client)
701 if (result
& GSOCK_CONNECTION_FLAG
)
704 m_establishing
= FALSE
;
708 // Data available or output buffer ready
709 if ((result
& GSOCK_INPUT_FLAG
) || (result
& GSOCK_OUTPUT_FLAG
))
715 if (result
& GSOCK_LOST_FLAG
)
718 m_establishing
= FALSE
;
719 return (flags
& GSOCK_LOST_FLAG
) != 0;
723 if ((!timeout
) || (chrono
.Time() > timeout
) || (m_interrupt
))
732 bool wxSocketBase::Wait(long seconds
, long milliseconds
)
734 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
|
736 GSOCK_CONNECTION_FLAG
|
740 bool wxSocketBase::WaitForRead(long seconds
, long milliseconds
)
742 // Check pushback buffer before entering _Wait
746 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
747 // _Wait becuase of the semantics of WaitForRead: a return
748 // value of TRUE means that a GSocket_Read call will return
749 // immediately, not that there is actually data to read.
751 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
|
755 bool wxSocketBase::WaitForWrite(long seconds
, long milliseconds
)
757 return _Wait(seconds
, milliseconds
, GSOCK_OUTPUT_FLAG
);
760 bool wxSocketBase::WaitForLost(long seconds
, long milliseconds
)
762 return _Wait(seconds
, milliseconds
, GSOCK_LOST_FLAG
);
765 // --------------------------------------------------------------------------
767 // --------------------------------------------------------------------------
770 // Get local or peer address
773 bool wxSocketBase::GetPeer(wxSockAddress
& addr_man
) const
780 peer
= GSocket_GetPeer(m_socket
);
782 // copying a null address would just trigger an assert anyway
787 addr_man
.SetAddress(peer
);
788 GAddress_destroy(peer
);
793 bool wxSocketBase::GetLocal(wxSockAddress
& addr_man
) const
800 local
= GSocket_GetLocal(m_socket
);
801 addr_man
.SetAddress(local
);
802 GAddress_destroy(local
);
808 // Save and restore socket state
811 void wxSocketBase::SaveState()
813 wxSocketState
*state
;
815 state
= new wxSocketState();
817 state
->m_flags
= m_flags
;
818 state
->m_notify
= m_notify
;
819 state
->m_eventmask
= m_eventmask
;
820 state
->m_clientData
= m_clientData
;
821 #if WXWIN_COMPATIBILITY
822 state
->m_cbk
= m_cbk
;
823 state
->m_cdata
= m_cdata
;
824 #endif // WXWIN_COMPATIBILITY
826 m_states
.Append(state
);
829 void wxSocketBase::RestoreState()
831 wxList::compatibility_iterator node
;
832 wxSocketState
*state
;
834 node
= m_states
.GetLast();
838 state
= (wxSocketState
*)node
->GetData();
840 m_flags
= state
->m_flags
;
841 m_notify
= state
->m_notify
;
842 m_eventmask
= state
->m_eventmask
;
843 m_clientData
= state
->m_clientData
;
844 #if WXWIN_COMPATIBILITY
845 m_cbk
= state
->m_cbk
;
846 m_cdata
= state
->m_cdata
;
847 #endif // WXWIN_COMPATIBILITY
849 m_states
.Erase(node
);
857 void wxSocketBase::SetTimeout(long seconds
)
862 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
865 void wxSocketBase::SetFlags(wxSocketFlags flags
)
871 // --------------------------------------------------------------------------
872 // Callbacks (now obsolete - use events instead)
873 // --------------------------------------------------------------------------
875 #if WXWIN_COMPATIBILITY
877 wxSocketBase::wxSockCbk
wxSocketBase::Callback(wxSockCbk cbk_
)
879 wxSockCbk old_cbk
= cbk_
;
885 char *wxSocketBase::CallbackData(char *data
)
887 char *old_data
= m_cdata
;
893 #endif // WXWIN_COMPATIBILITY
895 // --------------------------------------------------------------------------
897 // --------------------------------------------------------------------------
899 // A note on how events are processed, which is probably the most
900 // difficult thing to get working right while keeping the same API
901 // and functionality for all platforms.
903 // When GSocket detects an event, it calls wx_socket_callback, which in
904 // turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
905 // object. OnRequest does some housekeeping, and if the event is to be
906 // propagated to the user, it creates a new wxSocketEvent object and
907 // posts it. The event is not processed immediately, but delayed with
908 // AddPendingEvent instead. This is necessary in order to decouple the
909 // event processing from wx_socket_callback; otherwise, subsequent IO
910 // calls made from the user event handler would fail, as gtk callbacks
911 // are not reentrant.
913 // Note that, unlike events, user callbacks (now deprecated) are _not_
914 // decoupled from wx_socket_callback and thus they suffer from a variety
915 // of problems. Avoid them where possible and use events instead.
918 void LINKAGEMODE
wx_socket_callback(GSocket
* WXUNUSED(socket
),
919 GSocketEvent notification
,
922 wxSocketBase
*sckobj
= (wxSocketBase
*)cdata
;
924 sckobj
->OnRequest((wxSocketNotify
) notification
);
927 void wxSocketBase::OnRequest(wxSocketNotify notification
)
929 // NOTE: We duplicate some of the code in _Wait, but this doesn't
930 // hurt. It has to be here because the (GSocket) event might arrive
931 // a bit delayed, and it has to be in _Wait as well because we don't
932 // know whether the Wait functions are being used.
936 case wxSOCKET_CONNECTION
:
937 m_establishing
= FALSE
;
941 // If we are in the middle of a R/W operation, do not
942 // propagate events to users. Also, filter 'late' events
943 // which are no longer valid.
946 if (m_reading
|| !GSocket_Select(m_socket
, GSOCK_INPUT_FLAG
))
950 case wxSOCKET_OUTPUT
:
951 if (m_writing
|| !GSocket_Select(m_socket
, GSOCK_OUTPUT_FLAG
))
957 m_establishing
= FALSE
;
964 // Schedule the event
966 wxSocketEventFlags flag
= 0;
967 switch (notification
)
969 case GSOCK_INPUT
: flag
= GSOCK_INPUT_FLAG
; break;
970 case GSOCK_OUTPUT
: flag
= GSOCK_OUTPUT_FLAG
; break;
971 case GSOCK_CONNECTION
: flag
= GSOCK_CONNECTION_FLAG
; break;
972 case GSOCK_LOST
: flag
= GSOCK_LOST_FLAG
; break;
974 wxLogWarning(_("wxSocket: unknown event!."));
978 if (((m_eventmask
& flag
) == flag
) && m_notify
)
982 wxSocketEvent
event(m_id
);
983 event
.m_event
= notification
;
984 event
.m_clientData
= m_clientData
;
985 event
.SetEventObject(this);
987 m_handler
->AddPendingEvent(event
);
990 #if WXWIN_COMPATIBILITY
992 m_cbk(*this, notification
, m_cdata
);
993 #endif // WXWIN_COMPATIBILITY
997 void wxSocketBase::Notify(bool notify
)
1002 void wxSocketBase::SetNotify(wxSocketEventFlags flags
)
1004 m_eventmask
= flags
;
1007 void wxSocketBase::SetEventHandler(wxEvtHandler
& handler
, int id
)
1009 m_handler
= &handler
;
1013 // --------------------------------------------------------------------------
1015 // --------------------------------------------------------------------------
1017 void wxSocketBase::Pushback(const void *buffer
, wxUint32 size
)
1021 if (m_unread
== NULL
)
1022 m_unread
= malloc(size
);
1027 tmp
= malloc(m_unrd_size
+ size
);
1028 memcpy((char *)tmp
+ size
, m_unread
, m_unrd_size
);
1034 m_unrd_size
+= size
;
1036 memcpy(m_unread
, buffer
, size
);
1039 wxUint32
wxSocketBase::GetPushback(void *buffer
, wxUint32 size
, bool peek
)
1044 if (size
> (m_unrd_size
-m_unrd_cur
))
1045 size
= m_unrd_size
-m_unrd_cur
;
1047 memcpy(buffer
, (char *)m_unread
+ m_unrd_cur
, size
);
1052 if (m_unrd_size
== m_unrd_cur
)
1065 // ==========================================================================
1067 // ==========================================================================
1069 // --------------------------------------------------------------------------
1071 // --------------------------------------------------------------------------
1073 wxSocketServer::wxSocketServer(wxSockAddress
& addr_man
,
1074 wxSocketFlags flags
)
1075 : wxSocketBase(flags
, wxSOCKET_SERVER
)
1077 wxLogTrace( wxTRACE_Socket
, _T("Opening wxSocketServer") );
1079 m_socket
= GSocket_new();
1083 wxLogTrace( wxTRACE_Socket
, _T("*** GSocket_new failed") );
1087 // Setup the socket as server
1089 GSocket_SetLocal(m_socket
, addr_man
.GetAddress());
1090 if (GSocket_SetServer(m_socket
) != GSOCK_NOERROR
)
1092 GSocket_destroy(m_socket
);
1095 wxLogTrace( wxTRACE_Socket
, _T("*** GSocket_SetServer failed") );
1099 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
1100 GSocket_SetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1101 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1102 wx_socket_callback
, (char *)this);
1105 // --------------------------------------------------------------------------
1107 // --------------------------------------------------------------------------
1109 bool wxSocketServer::AcceptWith(wxSocketBase
& sock
, bool wait
)
1111 GSocket
*child_socket
;
1116 // If wait == FALSE, then the call should be nonblocking.
1117 // When we are finished, we put the socket to blocking mode
1121 GSocket_SetNonBlocking(m_socket
, 1);
1123 child_socket
= GSocket_WaitConnection(m_socket
);
1126 GSocket_SetNonBlocking(m_socket
, 0);
1131 sock
.m_type
= wxSOCKET_BASE
;
1132 sock
.m_socket
= child_socket
;
1133 sock
.m_connected
= TRUE
;
1135 GSocket_SetTimeout(sock
.m_socket
, sock
.m_timeout
* 1000);
1136 GSocket_SetCallback(sock
.m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1137 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1138 wx_socket_callback
, (char *)&sock
);
1143 wxSocketBase
*wxSocketServer::Accept(bool wait
)
1145 wxSocketBase
* sock
= new wxSocketBase();
1147 sock
->SetFlags(m_flags
);
1149 if (!AcceptWith(*sock
, wait
))
1158 bool wxSocketServer::WaitForAccept(long seconds
, long milliseconds
)
1160 return _Wait(seconds
, milliseconds
, GSOCK_CONNECTION_FLAG
);
1163 // ==========================================================================
1165 // ==========================================================================
1167 // --------------------------------------------------------------------------
1169 // --------------------------------------------------------------------------
1171 wxSocketClient::wxSocketClient(wxSocketFlags flags
)
1172 : wxSocketBase(flags
, wxSOCKET_CLIENT
)
1176 wxSocketClient::~wxSocketClient()
1180 // --------------------------------------------------------------------------
1182 // --------------------------------------------------------------------------
1184 bool wxSocketClient::Connect(wxSockAddress
& addr_man
, bool wait
)
1190 // Shutdown and destroy the socket
1192 GSocket_destroy(m_socket
);
1195 m_socket
= GSocket_new();
1196 m_connected
= FALSE
;
1197 m_establishing
= FALSE
;
1202 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
1203 GSocket_SetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1204 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1205 wx_socket_callback
, (char *)this);
1207 // If wait == FALSE, then the call should be nonblocking.
1208 // When we are finished, we put the socket to blocking mode
1212 GSocket_SetNonBlocking(m_socket
, 1);
1214 GSocket_SetPeer(m_socket
, addr_man
.GetAddress());
1215 err
= GSocket_Connect(m_socket
, GSOCK_STREAMED
);
1218 GSocket_SetNonBlocking(m_socket
, 0);
1220 if (err
!= GSOCK_NOERROR
)
1222 if (err
== GSOCK_WOULDBLOCK
)
1223 m_establishing
= TRUE
;
1232 bool wxSocketClient::WaitOnConnect(long seconds
, long milliseconds
)
1234 if (m_connected
) // Already connected
1237 if (!m_establishing
|| !m_socket
) // No connection in progress
1240 return _Wait(seconds
, milliseconds
, GSOCK_CONNECTION_FLAG
|
1244 // ==========================================================================
1246 // ==========================================================================
1248 /* NOTE: experimental stuff - might change */
1250 wxDatagramSocket::wxDatagramSocket( wxSockAddress
& addr
,
1251 wxSocketFlags flags
)
1252 : wxSocketBase( flags
, wxSOCKET_DATAGRAM
)
1254 // Create the socket
1255 m_socket
= GSocket_new();
1260 // Setup the socket as non connection oriented
1261 GSocket_SetLocal(m_socket
, addr
.GetAddress());
1262 if( GSocket_SetNonOriented(m_socket
) != GSOCK_NOERROR
)
1264 GSocket_destroy(m_socket
);
1269 // Initialize all stuff
1270 m_connected
= FALSE
;
1271 m_establishing
= FALSE
;
1272 GSocket_SetTimeout( m_socket
, m_timeout
);
1273 GSocket_SetCallback( m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1274 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1275 wx_socket_callback
, (char*)this );
1279 wxDatagramSocket
& wxDatagramSocket::RecvFrom( wxSockAddress
& addr
,
1288 wxDatagramSocket
& wxDatagramSocket::SendTo( wxSockAddress
& addr
,
1292 GSocket_SetPeer(m_socket
, addr
.GetAddress());
1297 // ==========================================================================
1299 // ==========================================================================
1301 class wxSocketModule
: public wxModule
1304 virtual bool OnInit()
1306 // wxSocketBase will call GSocket_Init() itself when/if needed
1310 virtual void OnExit()
1312 if ( wxSocketBase::IsInitialized() )
1313 wxSocketBase::Shutdown();
1317 DECLARE_DYNAMIC_CLASS(wxSocketModule
)
1320 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule
, wxModule
)