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
56 #define PROCESS_EVENTS() wxYield()
58 #define PROCESS_EVENTS()
61 // --------------------------------------------------------------------------
63 // --------------------------------------------------------------------------
65 IMPLEMENT_CLASS(wxSocketBase
, wxObject
)
66 IMPLEMENT_CLASS(wxSocketServer
, wxSocketBase
)
67 IMPLEMENT_CLASS(wxSocketClient
, wxSocketBase
)
68 IMPLEMENT_CLASS(wxDatagramSocket
, wxSocketBase
)
69 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent
, wxEvent
)
71 // --------------------------------------------------------------------------
73 // --------------------------------------------------------------------------
75 class wxSocketState
: public wxObject
78 wxSocketFlags m_flags
;
79 wxSocketEventFlags m_eventmask
;
82 #if WXWIN_COMPATIBILITY
83 wxSocketBase::wxSockCbk m_cbk
;
85 #endif // WXWIN_COMPATIBILITY
88 wxSocketState() : wxObject() {}
91 // ==========================================================================
93 // ==========================================================================
95 // --------------------------------------------------------------------------
97 // --------------------------------------------------------------------------
99 void wxSocketBase::Init()
102 m_type
= wxSOCKET_UNINIT
;
113 m_beingDeleted
= FALSE
;
126 #if WXWIN_COMPATIBILITY
129 #endif // WXWIN_COMPATIBILITY
132 wxSocketBase::wxSocketBase()
137 wxSocketBase::wxSocketBase(wxSocketFlags flags
, wxSocketType type
)
145 wxSocketBase::~wxSocketBase()
147 // Just in case the app called Destroy() *and* then deleted
148 // the socket immediately: don't leave dangling pointers.
150 wxPendingDelete
.DeleteObject(this);
153 // Shutdown and close the socket
157 // Destroy the GSocket object
159 GSocket_destroy(m_socket
);
161 // Free the pushback buffer
166 bool wxSocketBase::Destroy()
168 // Delayed destruction: the socket will be deleted during the next
169 // idle loop iteration. This ensures that all pending events have
171 m_beingDeleted
= TRUE
;
173 // Shutdown and close the socket
176 // Supress events from now on
180 if ( !wxPendingDelete
.Member(this) )
181 wxPendingDelete
.Append(this);
189 // --------------------------------------------------------------------------
191 // --------------------------------------------------------------------------
193 // The following IO operations update m_error and m_lcount:
194 // {Read, Write, ReadMsg, WriteMsg, Peek, Unread, Discard}
196 // TODO: Should Connect, Accept and AcceptWith update m_error?
198 bool wxSocketBase::Close()
200 // Interrupt pending waits
206 GSocket_UnsetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
207 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
);
209 // Shutdown the connection
210 GSocket_Shutdown(m_socket
);
214 m_establishing
= FALSE
;
218 wxSocketBase
& wxSocketBase::Read(void* buffer
, wxUint32 nbytes
)
223 m_lcount
= _Read(buffer
, nbytes
);
225 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
226 if (m_flags
& wxSOCKET_WAITALL
)
227 m_error
= (m_lcount
!= nbytes
);
229 m_error
= (m_lcount
== 0);
231 // Allow read events from now on
237 wxUint32
wxSocketBase::_Read(void* buffer
, wxUint32 nbytes
)
242 // Try the pushback buffer first
243 total
= GetPushback(buffer
, nbytes
, FALSE
);
245 buffer
= (char *)buffer
+ total
;
247 // Return now in one of the following cases:
248 // - the socket is invalid,
249 // - we got all the data,
250 // - we got *some* data and we are not using wxSOCKET_WAITALL.
253 ((total
!= 0) && !(m_flags
& wxSOCKET_WAITALL
)) )
256 // Possible combinations (they are checked in this order)
258 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
262 if (m_flags
& wxSOCKET_NOWAIT
)
264 GSocket_SetNonBlocking(m_socket
, 1);
265 ret
= GSocket_Read(m_socket
, (char *)buffer
, nbytes
);
266 GSocket_SetNonBlocking(m_socket
, 0);
277 if ( !(m_flags
& wxSOCKET_BLOCK
) && !WaitForRead() )
280 ret
= GSocket_Read(m_socket
, (char *)buffer
, nbytes
);
286 buffer
= (char *)buffer
+ ret
;
289 // If we got here and wxSOCKET_WAITALL is not set, we can leave
290 // now. Otherwise, wait until we recv all the data or until there
293 more
= (ret
> 0 && nbytes
> 0 && (m_flags
& wxSOCKET_WAITALL
));
300 wxSocketBase
& wxSocketBase::ReadMsg(void* buffer
, wxUint32 nbytes
)
302 wxUint32 len
, len2
, sig
, total
;
307 unsigned char sig
[4];
308 unsigned char len
[4];
317 SetFlags((m_flags
& wxSOCKET_BLOCK
) | wxSOCKET_WAITALL
);
319 if (_Read(&msg
, sizeof(msg
)) != sizeof(msg
))
322 sig
= (wxUint32
)msg
.sig
[0];
323 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
324 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
325 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
327 if (sig
!= 0xfeeddead)
329 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
333 len
= (wxUint32
)msg
.len
[0];
334 len
|= (wxUint32
)(msg
.len
[1] << 8);
335 len
|= (wxUint32
)(msg
.len
[2] << 16);
336 len
|= (wxUint32
)(msg
.len
[3] << 24);
346 // Don't attemp to read if the msg was zero bytes long.
349 total
= _Read(buffer
, len
);
356 char *discard_buffer
= new char[MAX_DISCARD_SIZE
];
359 // NOTE: discarded bytes don't add to m_lcount.
362 discard_len
= ((len2
> MAX_DISCARD_SIZE
)? MAX_DISCARD_SIZE
: len2
);
363 discard_len
= _Read(discard_buffer
, (wxUint32
)discard_len
);
364 len2
-= (wxUint32
)discard_len
;
366 while ((discard_len
> 0) && len2
);
368 delete [] discard_buffer
;
373 if (_Read(&msg
, sizeof(msg
)) != sizeof(msg
))
376 sig
= (wxUint32
)msg
.sig
[0];
377 sig
|= (wxUint32
)(msg
.sig
[1] << 8);
378 sig
|= (wxUint32
)(msg
.sig
[2] << 16);
379 sig
|= (wxUint32
)(msg
.sig
[3] << 24);
381 if (sig
!= 0xdeadfeed)
383 wxLogWarning(_("wxSocket: invalid signature in ReadMsg."));
399 wxSocketBase
& wxSocketBase::Peek(void* buffer
, wxUint32 nbytes
)
404 m_lcount
= _Read(buffer
, nbytes
);
405 Pushback(buffer
, m_lcount
);
407 // If in wxSOCKET_WAITALL mode, all bytes should have been read.
408 if (m_flags
& wxSOCKET_WAITALL
)
409 m_error
= (m_lcount
!= nbytes
);
411 m_error
= (m_lcount
== 0);
413 // Allow read events again
419 wxSocketBase
& wxSocketBase::Write(const void *buffer
, wxUint32 nbytes
)
424 m_lcount
= _Write(buffer
, nbytes
);
426 // If in wxSOCKET_WAITALL mode, all bytes should have been written.
427 if (m_flags
& wxSOCKET_WAITALL
)
428 m_error
= (m_lcount
!= nbytes
);
430 m_error
= (m_lcount
== 0);
432 // Allow write events again
438 wxUint32
wxSocketBase::_Write(const void *buffer
, wxUint32 nbytes
)
443 // If the socket is invalid or parameters are ill, return immediately
444 if (!m_socket
|| !buffer
|| !nbytes
)
447 // Possible combinations (they are checked in this order)
449 // wxSOCKET_WAITALL (with or without wxSOCKET_BLOCK)
453 if (m_flags
& wxSOCKET_NOWAIT
)
455 GSocket_SetNonBlocking(m_socket
, 1);
456 ret
= GSocket_Write(m_socket
, (const char *)buffer
, nbytes
);
457 GSocket_SetNonBlocking(m_socket
, 0);
468 if ( !(m_flags
& wxSOCKET_BLOCK
) && !WaitForWrite() )
471 ret
= GSocket_Write(m_socket
, (const char *)buffer
, nbytes
);
477 buffer
= (const char *)buffer
+ ret
;
480 // Yes, this can happen even when the socket selects as writable!
481 // (probably due to a buggy kernel; Linux 2.0.36 seems to do this).
482 // Fake it so that we stay in the loop, but do it only for ret < 0,
483 // as ret == 0 means that the socket is closed. I'm not applying
484 // this hack for read calls as it seems unnecessary there.
486 if ((ret
< 0) && (GSocket_GetError(m_socket
) == GSOCK_WOULDBLOCK
))
488 wxLogDebug(_("wxSocket: working around select() bug in Write."));
492 // If we got here and wxSOCKET_WAITALL is not set, we can leave
493 // now. Otherwise, wait until we send all the data or until there
496 more
= (ret
> 0 && nbytes
> 0 && (m_flags
& wxSOCKET_WAITALL
));
503 wxSocketBase
& wxSocketBase::WriteMsg(const void *buffer
, wxUint32 nbytes
)
510 unsigned char sig
[4];
511 unsigned char len
[4];
520 SetFlags((m_flags
& wxSOCKET_BLOCK
) | wxSOCKET_WAITALL
);
522 msg
.sig
[0] = (unsigned char) 0xad;
523 msg
.sig
[1] = (unsigned char) 0xde;
524 msg
.sig
[2] = (unsigned char) 0xed;
525 msg
.sig
[3] = (unsigned char) 0xfe;
527 msg
.len
[0] = (unsigned char) (nbytes
& 0xff);
528 msg
.len
[1] = (unsigned char) ((nbytes
>> 8) & 0xff);
529 msg
.len
[2] = (unsigned char) ((nbytes
>> 16) & 0xff);
530 msg
.len
[3] = (unsigned char) ((nbytes
>> 24) & 0xff);
532 if (_Write(&msg
, sizeof(msg
)) < sizeof(msg
))
535 total
= _Write(buffer
, nbytes
);
540 msg
.sig
[0] = (unsigned char) 0xed;
541 msg
.sig
[1] = (unsigned char) 0xfe;
542 msg
.sig
[2] = (unsigned char) 0xad;
543 msg
.sig
[3] = (unsigned char) 0xde;
544 msg
.len
[0] = msg
.len
[1] = msg
.len
[2] = msg
.len
[3] = (char) 0;
546 if ((_Write(&msg
, sizeof(msg
))) < sizeof(msg
))
560 wxSocketBase
& wxSocketBase::Unread(const void *buffer
, wxUint32 nbytes
)
563 Pushback(buffer
, nbytes
);
571 wxSocketBase
& wxSocketBase::Discard()
574 char *buffer
= new char[MAX_DISCARD_SIZE
];
582 SetFlags(wxSOCKET_NOWAIT
);
586 ret
= _Read(buffer
, MAX_DISCARD_SIZE
);
589 while (ret
== MAX_DISCARD_SIZE
);
595 // Allow read events again
601 // --------------------------------------------------------------------------
603 // --------------------------------------------------------------------------
605 // All Wait functions poll the socket using GSocket_Select() to
606 // check for the specified combination of conditions, until one
607 // of these conditions become true, an error occurs, or the
608 // timeout elapses. The polling loop calls PROCESS_EVENTS(), so
609 // this won't block the GUI.
611 bool wxSocketBase::_Wait(long seconds
,
613 wxSocketEventFlags flags
)
615 GSocketEventFlags result
;
618 // Set this to TRUE to interrupt ongoing waits
621 // Check for valid socket
625 // Check for valid timeout value.
627 timeout
= seconds
* 1000 + milliseconds
;
629 timeout
= m_timeout
* 1000;
631 // Wait in an active polling loop.
633 // NOTE: We duplicate some of the code in OnRequest, but this doesn't
634 // hurt. It has to be here because the (GSocket) event might arrive
635 // a bit delayed, and it has to be in OnRequest as well because we
636 // don't know whether the Wait functions are being used.
638 // Do this at least once (important if timeout == 0, when
639 // we are just polling). Also, if just polling, do not yield.
646 result
= GSocket_Select(m_socket
, flags
| GSOCK_LOST_FLAG
);
648 // Incoming connection (server) or connection established (client)
649 if (result
& GSOCK_CONNECTION_FLAG
)
652 m_establishing
= FALSE
;
656 // Data available or output buffer ready
657 if ((result
& GSOCK_INPUT_FLAG
) || (result
& GSOCK_OUTPUT_FLAG
))
663 if (result
& GSOCK_LOST_FLAG
)
666 m_establishing
= FALSE
;
667 return (flags
& GSOCK_LOST_FLAG
) != 0;
671 if ((!timeout
) || (chrono
.Time() > timeout
) || (m_interrupt
))
680 bool wxSocketBase::Wait(long seconds
, long milliseconds
)
682 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
|
684 GSOCK_CONNECTION_FLAG
|
688 bool wxSocketBase::WaitForRead(long seconds
, long milliseconds
)
690 // Check pushback buffer before entering _Wait
694 // Note that GSOCK_INPUT_LOST has to be explicitly passed to
695 // _Wait becuase of the semantics of WaitForRead: a return
696 // value of TRUE means that a GSocket_Read call will return
697 // immediately, not that there is actually data to read.
699 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
|
703 bool wxSocketBase::WaitForWrite(long seconds
, long milliseconds
)
705 return _Wait(seconds
, milliseconds
, GSOCK_OUTPUT_FLAG
);
708 bool wxSocketBase::WaitForLost(long seconds
, long milliseconds
)
710 return _Wait(seconds
, milliseconds
, GSOCK_LOST_FLAG
);
713 // --------------------------------------------------------------------------
715 // --------------------------------------------------------------------------
718 // Get local or peer address
721 bool wxSocketBase::GetPeer(wxSockAddress
& addr_man
) const
728 peer
= GSocket_GetPeer(m_socket
);
729 addr_man
.SetAddress(peer
);
730 GAddress_destroy(peer
);
735 bool wxSocketBase::GetLocal(wxSockAddress
& addr_man
) const
742 local
= GSocket_GetLocal(m_socket
);
743 addr_man
.SetAddress(local
);
744 GAddress_destroy(local
);
750 // Save and restore socket state
753 void wxSocketBase::SaveState()
755 wxSocketState
*state
;
757 state
= new wxSocketState();
759 state
->m_flags
= m_flags
;
760 state
->m_notify
= m_notify
;
761 state
->m_eventmask
= m_eventmask
;
762 state
->m_clientData
= m_clientData
;
763 #if WXWIN_COMPATIBILITY
764 state
->m_cbk
= m_cbk
;
765 state
->m_cdata
= m_cdata
;
766 #endif // WXWIN_COMPATIBILITY
768 m_states
.Append(state
);
771 void wxSocketBase::RestoreState()
774 wxSocketState
*state
;
776 node
= m_states
.Last();
780 state
= (wxSocketState
*)node
->Data();
782 m_flags
= state
->m_flags
;
783 m_notify
= state
->m_notify
;
784 m_eventmask
= state
->m_eventmask
;
785 m_clientData
= state
->m_clientData
;
786 #if WXWIN_COMPATIBILITY
787 m_cbk
= state
->m_cbk
;
788 m_cdata
= state
->m_cdata
;
789 #endif // WXWIN_COMPATIBILITY
799 void wxSocketBase::SetTimeout(long seconds
)
804 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
807 void wxSocketBase::SetFlags(wxSocketFlags flags
)
813 // --------------------------------------------------------------------------
814 // Callbacks (now obsolete - use events instead)
815 // --------------------------------------------------------------------------
817 #if WXWIN_COMPATIBILITY
819 wxSocketBase::wxSockCbk
wxSocketBase::Callback(wxSockCbk cbk_
)
821 wxSockCbk old_cbk
= cbk_
;
827 char *wxSocketBase::CallbackData(char *data
)
829 char *old_data
= m_cdata
;
835 #endif // WXWIN_COMPATIBILITY
837 // --------------------------------------------------------------------------
839 // --------------------------------------------------------------------------
841 // A note on how events are processed, which is probably the most
842 // difficult thing to get working right while keeping the same API
843 // and functionality for all platforms.
845 // When GSocket detects an event, it calls wx_socket_callback, which in
846 // turn just calls wxSocketBase::OnRequest in the corresponding wxSocket
847 // object. OnRequest does some housekeeping, and if the event is to be
848 // propagated to the user, it creates a new wxSocketEvent object and
849 // posts it. The event is not processed immediately, but delayed with
850 // AddPendingEvent instead. This is necessary in order to decouple the
851 // event processing from wx_socket_callback; otherwise, subsequent IO
852 // calls made from the user event handler would fail, as gtk callbacks
853 // are not reentrant.
855 // Note that, unlike events, user callbacks (now deprecated) are _not_
856 // decoupled from wx_socket_callback and thus they suffer from a variety
857 // of problems. Avoid them where possible and use events instead.
859 static void LINKAGEMODE
wx_socket_callback(GSocket
* WXUNUSED(socket
),
860 GSocketEvent notification
,
863 wxSocketBase
*sckobj
= (wxSocketBase
*)cdata
;
865 sckobj
->OnRequest((wxSocketNotify
) notification
);
868 void wxSocketBase::OnRequest(wxSocketNotify notification
)
870 // NOTE: We duplicate some of the code in _Wait, but this doesn't
871 // hurt. It has to be here because the (GSocket) event might arrive
872 // a bit delayed, and it has to be in _Wait as well because we don't
873 // know whether the Wait functions are being used.
877 case wxSOCKET_CONNECTION
:
878 m_establishing
= FALSE
;
882 // If we are in the middle of a R/W operation, do not
883 // propagate events to users. Also, filter 'late' events
884 // which are no longer valid.
887 if (m_reading
|| !GSocket_Select(m_socket
, GSOCK_INPUT_FLAG
))
891 case wxSOCKET_OUTPUT
:
892 if (m_writing
|| !GSocket_Select(m_socket
, GSOCK_OUTPUT_FLAG
))
898 m_establishing
= FALSE
;
905 // Schedule the event
907 wxSocketEventFlags flag
= 0;
908 switch (notification
)
910 case GSOCK_INPUT
: flag
= GSOCK_INPUT_FLAG
; break;
911 case GSOCK_OUTPUT
: flag
= GSOCK_OUTPUT_FLAG
; break;
912 case GSOCK_CONNECTION
: flag
= GSOCK_CONNECTION_FLAG
; break;
913 case GSOCK_LOST
: flag
= GSOCK_LOST_FLAG
; break;
915 wxLogWarning(_("wxSocket: unknown event!."));
919 if (((m_eventmask
& flag
) == flag
) && m_notify
)
923 wxSocketEvent
event(m_id
);
924 event
.m_event
= notification
;
925 event
.m_clientData
= m_clientData
;
926 event
.SetEventObject(this);
928 m_handler
->AddPendingEvent(event
);
931 #if WXWIN_COMPATIBILITY
933 m_cbk(*this, notification
, m_cdata
);
934 #endif // WXWIN_COMPATIBILITY
938 void wxSocketBase::Notify(bool notify
)
943 void wxSocketBase::SetNotify(wxSocketEventFlags flags
)
948 void wxSocketBase::SetEventHandler(wxEvtHandler
& handler
, int id
)
950 m_handler
= &handler
;
954 // --------------------------------------------------------------------------
956 // --------------------------------------------------------------------------
958 void wxSocketBase::Pushback(const void *buffer
, wxUint32 size
)
962 if (m_unread
== NULL
)
963 m_unread
= malloc(size
);
968 tmp
= malloc(m_unrd_size
+ size
);
969 memcpy((char *)tmp
+ size
, m_unread
, m_unrd_size
);
977 memcpy(m_unread
, buffer
, size
);
980 wxUint32
wxSocketBase::GetPushback(void *buffer
, wxUint32 size
, bool peek
)
985 if (size
> (m_unrd_size
-m_unrd_cur
))
986 size
= m_unrd_size
-m_unrd_cur
;
988 memcpy(buffer
, (char *)m_unread
+ m_unrd_cur
, size
);
993 if (m_unrd_size
== m_unrd_cur
)
1006 // ==========================================================================
1008 // ==========================================================================
1010 // --------------------------------------------------------------------------
1012 // --------------------------------------------------------------------------
1014 wxSocketServer::wxSocketServer(wxSockAddress
& addr_man
,
1015 wxSocketFlags flags
)
1016 : wxSocketBase(flags
, wxSOCKET_SERVER
)
1018 // Create the socket
1019 m_socket
= GSocket_new();
1024 // Setup the socket as server
1025 GSocket_SetLocal(m_socket
, addr_man
.GetAddress());
1026 if (GSocket_SetServer(m_socket
) != GSOCK_NOERROR
)
1028 GSocket_destroy(m_socket
);
1033 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
1034 GSocket_SetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1035 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1036 wx_socket_callback
, (char *)this);
1040 // --------------------------------------------------------------------------
1042 // --------------------------------------------------------------------------
1044 bool wxSocketServer::AcceptWith(wxSocketBase
& sock
, bool wait
)
1046 GSocket
*child_socket
;
1051 // If wait == FALSE, then the call should be nonblocking.
1052 // When we are finished, we put the socket to blocking mode
1056 GSocket_SetNonBlocking(m_socket
, 1);
1058 child_socket
= GSocket_WaitConnection(m_socket
);
1061 GSocket_SetNonBlocking(m_socket
, 0);
1066 sock
.m_type
= wxSOCKET_BASE
;
1067 sock
.m_socket
= child_socket
;
1068 sock
.m_connected
= TRUE
;
1070 GSocket_SetTimeout(sock
.m_socket
, sock
.m_timeout
* 1000);
1071 GSocket_SetCallback(sock
.m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1072 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1073 wx_socket_callback
, (char *)&sock
);
1078 wxSocketBase
*wxSocketServer::Accept(bool wait
)
1080 wxSocketBase
* sock
= new wxSocketBase();
1082 sock
->SetFlags(m_flags
);
1084 if (!AcceptWith(*sock
, wait
))
1090 bool wxSocketServer::WaitForAccept(long seconds
, long milliseconds
)
1092 return _Wait(seconds
, milliseconds
, GSOCK_CONNECTION_FLAG
);
1095 // ==========================================================================
1097 // ==========================================================================
1099 // --------------------------------------------------------------------------
1101 // --------------------------------------------------------------------------
1103 wxSocketClient::wxSocketClient(wxSocketFlags flags
)
1104 : wxSocketBase(flags
, wxSOCKET_CLIENT
)
1108 wxSocketClient::~wxSocketClient()
1112 // --------------------------------------------------------------------------
1114 // --------------------------------------------------------------------------
1116 bool wxSocketClient::Connect(wxSockAddress
& addr_man
, bool wait
)
1122 // Shutdown and destroy the socket
1124 GSocket_destroy(m_socket
);
1127 m_socket
= GSocket_new();
1128 m_connected
= FALSE
;
1129 m_establishing
= FALSE
;
1134 GSocket_SetTimeout(m_socket
, m_timeout
* 1000);
1135 GSocket_SetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1136 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1137 wx_socket_callback
, (char *)this);
1139 // If wait == FALSE, then the call should be nonblocking.
1140 // When we are finished, we put the socket to blocking mode
1144 GSocket_SetNonBlocking(m_socket
, 1);
1146 GSocket_SetPeer(m_socket
, addr_man
.GetAddress());
1147 err
= GSocket_Connect(m_socket
, GSOCK_STREAMED
);
1150 GSocket_SetNonBlocking(m_socket
, 0);
1152 if (err
!= GSOCK_NOERROR
)
1154 if (err
== GSOCK_WOULDBLOCK
)
1155 m_establishing
= TRUE
;
1164 bool wxSocketClient::WaitOnConnect(long seconds
, long milliseconds
)
1166 if (m_connected
) // Already connected
1169 if (!m_establishing
|| !m_socket
) // No connection in progress
1172 return _Wait(seconds
, milliseconds
, GSOCK_CONNECTION_FLAG
|
1176 // ==========================================================================
1178 // ==========================================================================
1180 /* NOTE: experimental stuff - might change */
1182 wxDatagramSocket::wxDatagramSocket( wxSockAddress
& addr
,
1183 wxSocketFlags flags
)
1184 : wxSocketBase( flags
, wxSOCKET_DATAGRAM
)
1186 // Create the socket
1187 m_socket
= GSocket_new();
1192 // Setup the socket as non connection oriented
1193 GSocket_SetLocal(m_socket
, addr
.GetAddress());
1194 if( GSocket_SetNonOriented(m_socket
) != GSOCK_NOERROR
)
1196 GSocket_destroy(m_socket
);
1201 // Initialize all stuff
1202 m_connected
= FALSE
;
1203 m_establishing
= FALSE
;
1204 GSocket_SetTimeout( m_socket
, m_timeout
);
1205 GSocket_SetCallback( m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
1206 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
,
1207 wx_socket_callback
, (char*)this );
1211 wxDatagramSocket
& wxDatagramSocket::RecvFrom( wxSockAddress
& addr
,
1220 wxDatagramSocket
& wxDatagramSocket::SendTo( wxSockAddress
& addr
,
1224 GSocket_SetPeer(m_socket
, addr
.GetAddress());
1229 // ==========================================================================
1231 // ==========================================================================
1233 wxSocketEvent::wxSocketEvent(int id
) : wxEvent(id
)
1235 SetEventType( (wxEventType
)wxEVT_SOCKET
);
1238 void wxSocketEvent::CopyObject(wxObject
& object_dest
) const
1240 wxSocketEvent
*event
= (wxSocketEvent
*)&object_dest
;
1242 wxEvent::CopyObject(object_dest
);
1244 event
->m_event
= m_event
;
1245 event
->m_clientData
= m_clientData
;
1248 // ==========================================================================
1250 // ==========================================================================
1252 class WXDLLEXPORT wxSocketModule
: public wxModule
1254 DECLARE_DYNAMIC_CLASS(wxSocketModule
)
1257 bool OnInit() { return GSocket_Init(); }
1258 void OnExit() { GSocket_Cleanup(); }
1261 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule
, wxModule
)