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 license
10 /////////////////////////////////////////////////////////////////////////////
12 // ==========================================================================
14 // ==========================================================================
17 #pragma implementation "socket.h"
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
31 #include "wx/object.h"
32 #include "wx/string.h"
35 #include "wx/module.h"
41 #include "wx/gdicmn.h" // for wxPendingDelete
44 #include "wx/sckaddr.h"
45 #include "wx/socket.h"
47 // --------------------------------------------------------------------------
48 // macros and constants
49 // --------------------------------------------------------------------------
52 #define MAX_DISCARD_SIZE (10 * 1024)
54 // what to do within waits: in wxBase we don't do anything as we don't have
55 // the event loop anyhow (for now). In GUI apps we have 2 cases: from the main
56 // thread itself we have to call wxYield() to let the events (including the
57 // GUI events and the low-level (not wxWindows) events from GSocket) be
58 // processed. From another thread it is enough to just call wxThread::Yield()
59 // which will give away the rest of our time slice: the explanation is that
60 // the events will be processed by the main thread anyhow, without calling
61 // wxYield(), but we don't want to eat the CPU time uselessly while sitting
62 // in the loop waiting for the data
65 #define PROCESS_EVENTS() \
67 if ( wxThread::IsMain() ) \
72 #else // !wxUSE_THREADS
73 #define PROCESS_EVENTS() wxYield()
74 #endif // wxUSE_THREADS/!wxUSE_THREADS
76 #define PROCESS_EVENTS()
77 #endif // wxUSE_GUI/!wxUSE_GUI
79 // --------------------------------------------------------------------------
81 // --------------------------------------------------------------------------
83 IMPLEMENT_CLASS(wxSocketBase
, wxObject
)
84 IMPLEMENT_CLASS(wxSocketServer
, wxSocketBase
)
85 IMPLEMENT_CLASS(wxSocketClient
, wxSocketBase
)
86 IMPLEMENT_CLASS(wxDatagramSocket
, wxSocketBase
)
87 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent
, wxEvent
)
89 // --------------------------------------------------------------------------
91 // --------------------------------------------------------------------------
93 class wxSocketState
: public wxObject
96 wxSocketFlags m_flags
;
97 wxSocketEventFlags m_eventmask
;
100 #if WXWIN_COMPATIBILITY
101 wxSocketBase::wxSockCbk m_cbk
;
103 #endif // WXWIN_COMPATIBILITY
106 wxSocketState() : wxObject() {}
109 // ==========================================================================
111 // ==========================================================================
113 // --------------------------------------------------------------------------
115 // --------------------------------------------------------------------------
117 void wxSocketBase::Init()
120 m_type
= wxSOCKET_UNINIT
;
131 m_beingDeleted
= FALSE
;
144 #if WXWIN_COMPATIBILITY
147 #endif // WXWIN_COMPATIBILITY
150 wxSocketBase::wxSocketBase()
155 wxSocketBase::wxSocketBase(wxSocketFlags flags
, wxSocketType type
)
163 wxSocketBase::~wxSocketBase()
165 // Just in case the app called Destroy() *and* then deleted
166 // the socket immediately: don't leave dangling pointers.
168 wxPendingDelete
.DeleteObject(this);
171 // Shutdown and close the socket
175 // Destroy the GSocket object
177 GSocket_destroy(m_socket
);
179 // Free the pushback buffer
184 bool wxSocketBase::Destroy()
186 // Delayed destruction: the socket will be deleted during the next
187 // idle loop iteration. This ensures that all pending events have
189 m_beingDeleted
= TRUE
;
191 // Shutdown and close the socket
194 // Supress events from now on
198 if ( !wxPendingDelete
.Member(this) )
199 wxPendingDelete
.Append(this);
207 // --------------------------------------------------------------------------
209 // --------------------------------------------------------------------------
211 // The following IO operations update m_error and m_lcount:
212 // {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
214 // TODO: Should Connect, Accept and AcceptWith update m_error?
216 bool wxSocketBase::Close()
218 // Interrupt pending waits
224 GSocket_UnsetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
225 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
);
227 // Shutdown the connection
228 GSocket_Shutdown(m_socket
);
232 m_establishing
= FALSE
;
236 wxSocketBase
& wxSocketBase::Read(void* buffer
, wxUint32 nbytes
)
241 m_lcount
= _Read(buffer
, nbytes
);
243 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
244 if (m_flags
& wxSOCKET_WAITALL
)
245 m_error
= (m_lcount
!= nbytes
);
247 m_error
= (m_lcount
== 0);
249 // Allow read events from now on
255 wxUint32
wxSocketBase::_Read(void* buffer
, wxUint32 nbytes
)
260 // Try the pushback buffer first
261 total
= GetPushback(buffer
, nbytes
, FALSE
);
263 buffer
= (char *)buffer
+ total
;
265 // Return now in one of the following cases:
266 // - the socket is invalid,
267 // - we got all the data,
268 // - we got *some* data and we are not using wxSOCKET_WAITALL.
271 ((total
!= 0) && !(m_flags
& wxSOCKET_WAITALL
)) )
274 // Possible combinations (they are checked in this order)
276 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
280 if (m_flags
& wxSOCKET_NOWAIT
)
282 GSocket_SetNonBlocking(m_socket
, 1);
283 ret
= GSocket_Read(m_socket
, (char *)buffer
, nbytes
);
284 GSocket_SetNonBlocking(m_socket
, 0);
295 if ( !(m_flags
& wxSOCKET_BLOCK
) && !WaitForRead() )
298 ret
= GSocket_Read(m_socket
, (char *)buffer
, nbytes
);
304 buffer
= (char *)buffer
+ ret
;
307 // If we got here and wxSOCKET_WAITALL is not set, we can leave
308 // now. Otherwise, wait until we recv all the data or until there
311 more
= (ret
> 0 && nbytes
> 0 && (m_flags
& wxSOCKET_WAITALL
));
318 wxSocketBase
& wxSocketBase::ReadMsg(void* buffer
, wxUint32 nbytes
)
320 wxUint32 len
, len2
, sig
, total
;
325 unsigned char sig
[4];
326 unsigned char len
[4];
335 SetFlags((m_flags
& wxSOCKET_BLOCK
) | wxSOCKET_WAITALL
);
337 if (_Read(&msg
, sizeof(msg
)) != sizeof(msg
))
340 sig
= (wxUint32
)msg
.sig
[0];
341 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
342 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
343 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
345 if (sig
!= 0xfeeddead)
347 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
351 len
= (wxUint32
)msg
.len
[0];
352 len
|= (wxUint32
)(msg
.len
[1] << 8);
353 len
|= (wxUint32
)(msg
.len
[2] << 16);
354 len
|= (wxUint32
)(msg
.len
[3] << 24);
364 // Don't attemp to read if the msg was zero bytes long.
367 total
= _Read(buffer
, len
);
374 char *discard_buffer
= new char[MAX_DISCARD_SIZE
];
377 // NOTE: discarded bytes don't add to m_lcount.
380 discard_len
= ((len2
> MAX_DISCARD_SIZE
)? MAX_DISCARD_SIZE
: len2
);
381 discard_len
= _Read(discard_buffer
, (wxUint32
)discard_len
);
382 len2
-= (wxUint32
)discard_len
;
384 while ((discard_len
> 0) && len2
);
386 delete [] discard_buffer
;
391 if (_Read(&msg
, sizeof(msg
)) != sizeof(msg
))
394 sig
= (wxUint32
)msg
.sig
[0];
395 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
396 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
397 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
399 if (sig
!= 0xdeadfeed)
401 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
417 wxSocketBase
& wxSocketBase::Peek(void* buffer
, wxUint32 nbytes
)
422 m_lcount
= _Read(buffer
, nbytes
);
423 Pushback(buffer
, m_lcount
);
425 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
426 if (m_flags
& wxSOCKET_WAITALL
)
427 m_error
= (m_lcount
!= nbytes
);
429 m_error
= (m_lcount
== 0);
431 // Allow read events again
437 wxSocketBase
& wxSocketBase::Write(const void *buffer
, wxUint32 nbytes
)
442 m_lcount
= _Write(buffer
, nbytes
);
444 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
445 if (m_flags
& wxSOCKET_WAITALL
)
446 m_error
= (m_lcount
!= nbytes
);
448 m_error
= (m_lcount
== 0);
450 // Allow write events again
456 wxUint32
wxSocketBase::_Write(const void *buffer
, wxUint32 nbytes
)
461 // If the socket is invalid or parameters are ill, return immediately
462 if (!m_socket
|| !buffer
|| !nbytes
)
465 // Possible combinations (they are checked in this order)
467 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
471 if (m_flags
& wxSOCKET_NOWAIT
)
473 GSocket_SetNonBlocking(m_socket
, 1);
474 ret
= GSocket_Write(m_socket
, (const char *)buffer
, nbytes
);
475 GSocket_SetNonBlocking(m_socket
, 0);
486 if ( !(m_flags
& wxSOCKET_BLOCK
) && !WaitForWrite() )
489 ret
= GSocket_Write(m_socket
, (const char *)buffer
, nbytes
);
495 buffer
= (const char *)buffer
+ ret
;
498 // If we got here and wxSOCKET_WAITALL is not set, we can leave
499 // now. Otherwise, wait until we send all the data or until there
502 more
= (ret
> 0 && nbytes
> 0 && (m_flags
& wxSOCKET_WAITALL
));
509 wxSocketBase
& wxSocketBase::WriteMsg(const void *buffer
, wxUint32 nbytes
)
516 unsigned char sig
[4];
517 unsigned char len
[4];
526 SetFlags((m_flags
& wxSOCKET_BLOCK
) | wxSOCKET_WAITALL
);
528 msg
.sig
[0] = (unsigned char) 0xad;
529 msg
.sig
[1] = (unsigned char) 0xde;
530 msg
.sig
[2] = (unsigned char) 0xed;
531 msg
.sig
[3] = (unsigned char) 0xfe;
533 msg
.len
[0] = (unsigned char) (nbytes
& 0xff);
534 msg
.len
[1] = (unsigned char) ((nbytes
>> 8) & 0xff);
535 msg
.len
[2] = (unsigned char) ((nbytes
>> 16) & 0xff);
536 msg
.len
[3] = (unsigned char) ((nbytes
>> 24) & 0xff);
538 if (_Write(&msg
, sizeof(msg
)) < sizeof(msg
))
541 total
= _Write(buffer
, nbytes
);
546 msg
.sig
[0] = (unsigned char) 0xed;
547 msg
.sig
[1] = (unsigned char) 0xfe;
548 msg
.sig
[2] = (unsigned char) 0xad;
549 msg
.sig
[3] = (unsigned char) 0xde;
550 msg
.len
[0] = msg
.len
[1] = msg
.len
[2] = msg
.len
[3] = (char) 0;
552 if ((_Write(&msg
, sizeof(msg
))) < sizeof(msg
))
566 wxSocketBase
& wxSocketBase::Unread(const void *buffer
, wxUint32 nbytes
)
569 Pushback(buffer
, nbytes
);
577 wxSocketBase
& wxSocketBase::Discard()
580 char *buffer
= new char[MAX_DISCARD_SIZE
];
588 SetFlags(wxSOCKET_NOWAIT
);
592 ret
= _Read(buffer
, MAX_DISCARD_SIZE
);
595 while (ret
== MAX_DISCARD_SIZE
);
601 // Allow read events again
607 // --------------------------------------------------------------------------
609 // --------------------------------------------------------------------------
611 // All Wait functions poll the socket using GSocket_Select() to
612 // check for the specified combination of conditions, until one
613 // of these conditions become true, an error occurs, or the
614 // timeout elapses. The polling loop calls PROCESS_EVENTS(), so
615 // this won't block the GUI.
617 bool wxSocketBase::_Wait(long seconds
,
619 wxSocketEventFlags flags
)
621 GSocketEventFlags result
;
624 // Set this to TRUE to interrupt ongoing waits
627 // Check for valid socket
631 // Check for valid timeout value.
633 timeout
= seconds
* 1000 + milliseconds
;
635 timeout
= m_timeout
* 1000;
637 // Wait in an active polling loop.
639 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
640 // hurt. It has to be here because the (GSocket) event might arrive
641 // a bit delayed, and it has to be in OnRequest as well because we
642 // don't know whether the Wait functions are being used.
644 // Do this at least once (important if timeout == 0, when
645 // we are just polling). Also, if just polling, do not yield.
652 result
= GSocket_Select(m_socket
, flags
| GSOCK_LOST_FLAG
);
654 // Incoming connection (server) or connection established (client)
655 if (result
& GSOCK_CONNECTION_FLAG
)
658 m_establishing
= FALSE
;
662 // Data available or output buffer ready
663 if ((result
& GSOCK_INPUT_FLAG
) || (result
& GSOCK_OUTPUT_FLAG
))
669 if (result
& GSOCK_LOST_FLAG
)
672 m_establishing
= FALSE
;
673 return (flags
& GSOCK_LOST_FLAG
) != 0;
677 if ((!timeout
) || (chrono
.Time() > timeout
) || (m_interrupt
))
686 bool wxSocketBase::Wait(long seconds
, long milliseconds
)
688 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
|
690 GSOCK_CONNECTION_FLAG
|
694 bool wxSocketBase::WaitForRead(long seconds
, long milliseconds
)
696 // Check pushback buffer before entering _Wait
700 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
701 // _Wait becuase of the semantics of WaitForRead: a return
702 // value of TRUE means that a GSocket_Read call will return
703 // immediately, not that there is actually data to read.
705 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
|
709 bool wxSocketBase::WaitForWrite(long seconds
, long milliseconds
)
711 return _Wait(seconds
, milliseconds
, GSOCK_OUTPUT_FLAG
);
714 bool wxSocketBase::WaitForLost(long seconds
, long milliseconds
)
716 return _Wait(seconds
, milliseconds
, GSOCK_LOST_FLAG
);
719 // --------------------------------------------------------------------------
721 // --------------------------------------------------------------------------
724 // Get local or peer address
727 bool wxSocketBase::GetPeer(wxSockAddress
& addr_man
) const
734 peer
= GSocket_GetPeer(m_socket
);
735 addr_man
.SetAddress(peer
);
736 GAddress_destroy(peer
);
741 bool wxSocketBase::GetLocal(wxSockAddress
& addr_man
) const
748 local
= GSocket_GetLocal(m_socket
);
749 addr_man
.SetAddress(local
);
750 GAddress_destroy(local
);
756 // Save and restore socket state
759 void wxSocketBase::SaveState()
761 wxSocketState
*state
;
763 state
= new wxSocketState();
765 state
->m_flags
= m_flags
;
766 state
->m_notify
= m_notify
;
767 state
->m_eventmask
= m_eventmask
;
768 state
->m_clientData
= m_clientData
;
769 #if WXWIN_COMPATIBILITY
770 state
->m_cbk
= m_cbk
;
771 state
->m_cdata
= m_cdata
;
772 #endif // WXWIN_COMPATIBILITY
774 m_states
.Append(state
);
777 void wxSocketBase::RestoreState()
780 wxSocketState
*state
;
782 node
= m_states
.Last();
786 state
= (wxSocketState
*)node
->Data();
788 m_flags
= state
->m_flags
;
789 m_notify
= state
->m_notify
;
790 m_eventmask
= state
->m_eventmask
;
791 m_clientData
= state
->m_clientData
;
792 #if WXWIN_COMPATIBILITY
793 m_cbk
= state
->m_cbk
;
794 m_cdata
= state
->m_cdata
;
795 #endif // WXWIN_COMPATIBILITY
805 void wxSocketBase::SetTimeout(long seconds
)
810 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
813 void wxSocketBase::SetFlags(wxSocketFlags flags
)
819 // --------------------------------------------------------------------------
820 // Callbacks (now obsolete - use events instead)
821 // --------------------------------------------------------------------------
823 #if WXWIN_COMPATIBILITY
825 wxSocketBase::wxSockCbk
wxSocketBase::Callback(wxSockCbk cbk_
)
827 wxSockCbk old_cbk
= cbk_
;
833 char *wxSocketBase::CallbackData(char *data
)
835 char *old_data
= m_cdata
;
841 #endif // WXWIN_COMPATIBILITY
843 // --------------------------------------------------------------------------
845 // --------------------------------------------------------------------------
847 // A note on how events are processed, which is probably the most
848 // difficult thing to get working right while keeping the same API
849 // and functionality for all platforms.
851 // When GSocket detects an event, it calls wx_socket_callback, which in
852 // turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
853 // object. OnRequest does some housekeeping, and if the event is to be
854 // propagated to the user, it creates a new wxSocketEvent object and
855 // posts it. The event is not processed immediately, but delayed with
856 // AddPendingEvent instead. This is necessary in order to decouple the
857 // event processing from wx_socket_callback; otherwise, subsequent IO
858 // calls made from the user event handler would fail, as gtk callbacks
859 // are not reentrant.
861 // Note that, unlike events, user callbacks (now deprecated) are _not_
862 // decoupled from wx_socket_callback and thus they suffer from a variety
863 // of problems. Avoid them where possible and use events instead.
865 static void LINKAGEMODE
wx_socket_callback(GSocket
* WXUNUSED(socket
),
866 GSocketEvent notification
,
869 wxSocketBase
*sckobj
= (wxSocketBase
*)cdata
;
871 sckobj
->OnRequest((wxSocketNotify
) notification
);
874 void wxSocketBase::OnRequest(wxSocketNotify notification
)
876 // NOTE: We duplicate some of the code in _Wait, but this doesn't
877 // hurt. It has to be here because the (GSocket) event might arrive
878 // a bit delayed, and it has to be in _Wait as well because we don't
879 // know whether the Wait functions are being used.
883 case wxSOCKET_CONNECTION
:
884 m_establishing
= FALSE
;
888 // If we are in the middle of a R/W operation, do not
889 // propagate events to users. Also, filter 'late' events
890 // which are no longer valid.
893 if (m_reading
|| !GSocket_Select(m_socket
, GSOCK_INPUT_FLAG
))
897 case wxSOCKET_OUTPUT
:
898 if (m_writing
|| !GSocket_Select(m_socket
, GSOCK_OUTPUT_FLAG
))
904 m_establishing
= FALSE
;
911 // Schedule the event
913 wxSocketEventFlags flag
= 0;
914 switch (notification
)
916 case GSOCK_INPUT
: flag
= GSOCK_INPUT_FLAG
; break;
917 case GSOCK_OUTPUT
: flag
= GSOCK_OUTPUT_FLAG
; break;
918 case GSOCK_CONNECTION
: flag
= GSOCK_CONNECTION_FLAG
; break;
919 case GSOCK_LOST
: flag
= GSOCK_LOST_FLAG
; break;
921 wxLogWarning(_("wxSocket: unknown event!."));
925 if (((m_eventmask
& flag
) == flag
) && m_notify
)
929 wxSocketEvent
event(m_id
);
930 event
.m_event
= notification
;
931 event
.m_clientData
= m_clientData
;
932 event
.SetEventObject(this);
934 m_handler
->AddPendingEvent(event
);
937 #if WXWIN_COMPATIBILITY
939 m_cbk(*this, notification
, m_cdata
);
940 #endif // WXWIN_COMPATIBILITY
944 void wxSocketBase::Notify(bool notify
)
949 void wxSocketBase::SetNotify(wxSocketEventFlags flags
)
954 void wxSocketBase::SetEventHandler(wxEvtHandler
& handler
, int id
)
956 m_handler
= &handler
;
960 // --------------------------------------------------------------------------
962 // --------------------------------------------------------------------------
964 void wxSocketBase::Pushback(const void *buffer
, wxUint32 size
)
968 if (m_unread
== NULL
)
969 m_unread
= malloc(size
);
974 tmp
= malloc(m_unrd_size
+ size
);
975 memcpy((char *)tmp
+ size
, m_unread
, m_unrd_size
);
983 memcpy(m_unread
, buffer
, size
);
986 wxUint32
wxSocketBase::GetPushback(void *buffer
, wxUint32 size
, bool peek
)
991 if (size
> (m_unrd_size
-m_unrd_cur
))
992 size
= m_unrd_size
-m_unrd_cur
;
994 memcpy(buffer
, (char *)m_unread
+ m_unrd_cur
, size
);
999 if (m_unrd_size
== m_unrd_cur
)
1012 // ==========================================================================
1014 // ==========================================================================
1016 // --------------------------------------------------------------------------
1018 // --------------------------------------------------------------------------
1020 wxSocketServer::wxSocketServer(wxSockAddress
& addr_man
,
1021 wxSocketFlags flags
)
1022 : wxSocketBase(flags
, wxSOCKET_SERVER
)
1024 // Create the socket
1025 m_socket
= GSocket_new();
1030 // Setup the socket as server
1031 GSocket_SetLocal(m_socket
, addr_man
.GetAddress());
1032 if (GSocket_SetServer(m_socket
) != GSOCK_NOERROR
)
1034 GSocket_destroy(m_socket
);
1039 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
1040 GSocket_SetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1041 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1042 wx_socket_callback
, (char *)this);
1046 // --------------------------------------------------------------------------
1048 // --------------------------------------------------------------------------
1050 bool wxSocketServer::AcceptWith(wxSocketBase
& sock
, bool wait
)
1052 GSocket
*child_socket
;
1057 // If wait == FALSE, then the call should be nonblocking.
1058 // When we are finished, we put the socket to blocking mode
1062 GSocket_SetNonBlocking(m_socket
, 1);
1064 child_socket
= GSocket_WaitConnection(m_socket
);
1067 GSocket_SetNonBlocking(m_socket
, 0);
1072 sock
.m_type
= wxSOCKET_BASE
;
1073 sock
.m_socket
= child_socket
;
1074 sock
.m_connected
= TRUE
;
1076 GSocket_SetTimeout(sock
.m_socket
, sock
.m_timeout
* 1000);
1077 GSocket_SetCallback(sock
.m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1078 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1079 wx_socket_callback
, (char *)&sock
);
1084 wxSocketBase
*wxSocketServer::Accept(bool wait
)
1086 wxSocketBase
* sock
= new wxSocketBase();
1088 sock
->SetFlags(m_flags
);
1090 if (!AcceptWith(*sock
, wait
))
1099 bool wxSocketServer::WaitForAccept(long seconds
, long milliseconds
)
1101 return _Wait(seconds
, milliseconds
, GSOCK_CONNECTION_FLAG
);
1104 // ==========================================================================
1106 // ==========================================================================
1108 // --------------------------------------------------------------------------
1110 // --------------------------------------------------------------------------
1112 wxSocketClient::wxSocketClient(wxSocketFlags flags
)
1113 : wxSocketBase(flags
, wxSOCKET_CLIENT
)
1117 wxSocketClient::~wxSocketClient()
1121 // --------------------------------------------------------------------------
1123 // --------------------------------------------------------------------------
1125 bool wxSocketClient::Connect(wxSockAddress
& addr_man
, bool wait
)
1131 // Shutdown and destroy the socket
1133 GSocket_destroy(m_socket
);
1136 m_socket
= GSocket_new();
1137 m_connected
= FALSE
;
1138 m_establishing
= FALSE
;
1143 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
1144 GSocket_SetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1145 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1146 wx_socket_callback
, (char *)this);
1148 // If wait == FALSE, then the call should be nonblocking.
1149 // When we are finished, we put the socket to blocking mode
1153 GSocket_SetNonBlocking(m_socket
, 1);
1155 GSocket_SetPeer(m_socket
, addr_man
.GetAddress());
1156 err
= GSocket_Connect(m_socket
, GSOCK_STREAMED
);
1159 GSocket_SetNonBlocking(m_socket
, 0);
1161 if (err
!= GSOCK_NOERROR
)
1163 if (err
== GSOCK_WOULDBLOCK
)
1164 m_establishing
= TRUE
;
1173 bool wxSocketClient::WaitOnConnect(long seconds
, long milliseconds
)
1175 if (m_connected
) // Already connected
1178 if (!m_establishing
|| !m_socket
) // No connection in progress
1181 return _Wait(seconds
, milliseconds
, GSOCK_CONNECTION_FLAG
|
1185 // ==========================================================================
1187 // ==========================================================================
1189 /* NOTE: experimental stuff - might change */
1191 wxDatagramSocket::wxDatagramSocket( wxSockAddress
& addr
,
1192 wxSocketFlags flags
)
1193 : wxSocketBase( flags
, wxSOCKET_DATAGRAM
)
1195 // Create the socket
1196 m_socket
= GSocket_new();
1201 // Setup the socket as non connection oriented
1202 GSocket_SetLocal(m_socket
, addr
.GetAddress());
1203 if( GSocket_SetNonOriented(m_socket
) != GSOCK_NOERROR
)
1205 GSocket_destroy(m_socket
);
1210 // Initialize all stuff
1211 m_connected
= FALSE
;
1212 m_establishing
= FALSE
;
1213 GSocket_SetTimeout( m_socket
, m_timeout
);
1214 GSocket_SetCallback( m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1215 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1216 wx_socket_callback
, (char*)this );
1220 wxDatagramSocket
& wxDatagramSocket::RecvFrom( wxSockAddress
& addr
,
1229 wxDatagramSocket
& wxDatagramSocket::SendTo( wxSockAddress
& addr
,
1233 GSocket_SetPeer(m_socket
, addr
.GetAddress());
1238 // ==========================================================================
1240 // ==========================================================================
1242 wxSocketEvent::wxSocketEvent(int id
) : wxEvent(id
)
1244 SetEventType( (wxEventType
)wxEVT_SOCKET
);
1247 void wxSocketEvent::CopyObject(wxObject
& object_dest
) const
1249 wxSocketEvent
*event
= (wxSocketEvent
*)&object_dest
;
1251 wxEvent::CopyObject(object_dest
);
1253 event
->m_event
= m_event
;
1254 event
->m_clientData
= m_clientData
;
1257 // ==========================================================================
1259 // ==========================================================================
1261 class WXDLLEXPORT wxSocketModule
: public wxModule
1263 DECLARE_DYNAMIC_CLASS(wxSocketModule
)
1266 bool OnInit() { return GSocket_Init() != 0; }
1267 void OnExit() { GSocket_Cleanup(); }
1270 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule
, wxModule
)