1 ////////////////////////////////////////////////////////////////////////////////
3 // Purpose: Socket handler classes
4 // Authors: Guilhem Lavaux
7 // Copyright: (C) 1999, 1998, 1997, Guilhem Lavaux
9 // License: see wxWindows license
10 ////////////////////////////////////////////////////////////////////////////////
12 #pragma implementation "socket.h"
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
24 /////////////////////////////////////////////////////////////////////////////
26 /////////////////////////////////////////////////////////////////////////////
28 #include <wx/object.h>
29 #include <wx/string.h>
38 /////////////////////////////////////////////////////////////////////////////
40 /////////////////////////////////////////////////////////////////////////////
41 #include <wx/module.h>
42 #include <wx/sckaddr.h>
43 #include <wx/socket.h>
45 // --------------------------------------------------------------
47 // --------------------------------------------------------------
48 #if !USE_SHARED_LIBRARY
49 IMPLEMENT_CLASS(wxSocketBase
, wxObject
)
50 IMPLEMENT_CLASS(wxSocketServer
, wxSocketBase
)
51 IMPLEMENT_CLASS(wxSocketClient
, wxSocketBase
)
52 IMPLEMENT_DYNAMIC_CLASS(wxSocketEvent
, wxEvent
)
55 class wxSocketState
: public wxObject
{
58 GSocketEventFlags evt_notify_state
;
59 wxSocketBase::wxSockFlags socket_flags
;
60 wxSocketBase::wxSockCbk c_callback
;
61 char *c_callback_data
;
64 wxSocketState() : wxObject() {}
67 // --------------------------------------------------------------
68 // --------- wxSocketBase CONSTRUCTOR ---------------------------
69 // --------------------------------------------------------------
70 wxSocketBase::wxSocketBase(wxSocketBase::wxSockFlags _flags
,
71 wxSocketBase::wxSockType _type
) :
73 m_socket(NULL
), m_flags(_flags
), m_type(_type
),
74 m_neededreq(GSOCK_INPUT_FLAG
| GSOCK_LOST_FLAG
),
75 m_lcount(0), m_timeout(3600),
76 m_unread(NULL
), m_unrd_size(0), m_unrd_cur(0),
77 m_cbk(NULL
), m_cdata(NULL
),
78 m_connected(FALSE
), m_notify_state(FALSE
), m_id(-1),
84 wxSocketBase::wxSocketBase() :
86 m_socket(NULL
), m_flags(SPEED
| WAITALL
), m_type(SOCK_UNINIT
),
87 m_neededreq(GSOCK_INPUT_FLAG
| GSOCK_LOST_FLAG
),
88 m_lcount(0), m_timeout(3600),
89 m_unread(NULL
), m_unrd_size(0), m_unrd_cur(0),
90 m_cbk(NULL
), m_cdata(NULL
),
91 m_connected(FALSE
), m_notify_state(FALSE
), m_id(-1),
97 // --------------------------------------------------------------
98 // wxSocketBase destructor
99 // --------------------------------------------------------------
101 wxSocketBase::~wxSocketBase()
106 // At last, close the file descriptor.
110 GSocket_destroy(m_socket
);
113 bool wxSocketBase::Close()
117 if (m_notify_state
== TRUE
)
120 // Shutdown the connection.
121 GSocket_Shutdown(m_socket
);
128 // --------------------------------------------------------------
129 // wxSocketBase base IO function
130 // --------------------------------------------------------------
132 int wxSocketBase::DeferRead(char *buffer
, size_t nbytes
)
134 GSocketEventFlags old_event_flags
;
135 bool old_notify_state
;
137 wxASSERT(m_defering
== NO_DEFER
);
139 m_defering
= DEFER_READ
;
141 old_event_flags
= NeededReq();
142 old_notify_state
= m_notify_state
;
144 SetNotify(GSOCK_INPUT_FLAG
| GSOCK_LOST_FLAG
);
147 m_defer_buffer
= buffer
;
148 m_defer_nbytes
= nbytes
;
149 while (m_defer_buffer
!= NULL
)
152 Notify(old_notify_state
);
153 SetNotify(old_event_flags
);
155 m_defering
= NO_DEFER
;
157 return nbytes
-m_defer_nbytes
;
160 wxSocketBase
& wxSocketBase::Read(char* buffer
, size_t nbytes
)
164 m_lcount
= GetPushback(buffer
, nbytes
, FALSE
);
171 // If we have got the whole needed buffer or if we don't want to
172 // wait then it returns immediately.
173 if (!nbytes
|| (m_lcount
&& !(m_flags
& WAITALL
)) ) {
177 if ((m_flags
& SPEED
) != 0) {
179 if ((m_flags
& WAITALL
) != 0) {
180 while (ret
> 0 && nbytes
> 0) {
181 ret
= GSocket_Read(m_socket
, buffer
, nbytes
);
186 // In case the last call was an error ...
190 ret
= GSocket_Read(m_socket
, buffer
, nbytes
);
196 ret
= DeferRead(buffer
, nbytes
);
205 wxSocketBase
& wxSocketBase::ReadMsg(char* buffer
, size_t nbytes
)
207 unsigned long len
, len2
, sig
;
213 // sig should be an explicit 32-bit unsigned integer; I've seen
214 // compilers in which size_t was actually a 16-bit unsigned integer
216 Read((char *)&msg
, sizeof(msg
));
217 if (m_lcount
!= sizeof(msg
))
220 sig
= msg
.sig
[0] & 0xff;
221 sig
|= (size_t)(msg
.sig
[1] & 0xff) << 8;
222 sig
|= (size_t)(msg
.sig
[2] & 0xff) << 16;
223 sig
|= (size_t)(msg
.sig
[3] & 0xff) << 24;
225 if (sig
!= 0xfeeddead)
227 len
= msg
.len
[0] & 0xff;
228 len
|= (size_t)(msg
.len
[1] & 0xff) << 8;
229 len
|= (size_t)(msg
.len
[2] & 0xff) << 16;
230 len
|= (size_t)(msg
.len
[3] & 0xff) << 24;
232 // len2 is incorrectly computed in the original; this sequence is
241 // the "len &&" in the following statement is necessary so that
242 // we don't attempt to read (and possibly hang the system)
243 // if the message was zero bytes long
244 if (len
&& Read(buffer
, len
).LastCount() != len
)
246 if (len2
&& (Read(NULL
, len2
).LastCount() != len2
))
248 if (Read((char *)&msg
, sizeof(msg
)).LastCount() != sizeof(msg
))
251 sig
= msg
.sig
[0] & 0xff;
252 sig
|= (size_t)(msg
.sig
[1] & 0xff) << 8;
253 sig
|= (size_t)(msg
.sig
[2] & 0xff) << 16;
254 sig
|= (size_t)(msg
.sig
[3] & 0xff) << 24;
257 if (sig
!= 0xdeadfeed)
258 wxLogDebug(_T("Warning: invalid signature returned to ReadMsg\n"));
263 wxSocketBase
& wxSocketBase::Peek(char* buffer
, size_t nbytes
)
265 Read(buffer
, nbytes
);
266 CreatePushbackAfter(buffer
, nbytes
);
271 int wxSocketBase::DeferWrite(const char *buffer
, size_t nbytes
)
273 GSocketEventFlags old_event_flags
;
274 bool old_notify_state
;
276 wxASSERT(m_defering
== NO_DEFER
);
278 m_defering
= DEFER_WRITE
;
280 old_event_flags
= NeededReq();
281 old_notify_state
= m_notify_state
;
283 SetNotify(GSOCK_OUTPUT_FLAG
| GSOCK_LOST_FLAG
);
286 m_defer_buffer
= (char *)buffer
;
287 m_defer_nbytes
= nbytes
;
288 while (m_defer_buffer
!= NULL
)
291 Notify(old_notify_state
);
292 SetNotify(old_event_flags
);
294 m_defering
= NO_DEFER
;
296 return nbytes
-m_defer_nbytes
;
299 wxSocketBase
& wxSocketBase::Write(const char *buffer
, size_t nbytes
)
303 if ((m_flags
& SPEED
) != 0)
304 ret
= GSocket_Write(m_socket
, buffer
, nbytes
);
306 ret
= DeferWrite(buffer
, nbytes
);
314 wxSocketBase
& wxSocketBase::WriteMsg(const char *buffer
, size_t nbytes
)
321 // warning about 'cast truncates constant value'
323 #pragma warning(disable: 4310)
324 #endif // __VISUALC__
326 msg
.sig
[0] = (char) 0xad;
327 msg
.sig
[1] = (char) 0xde;
328 msg
.sig
[2] = (char) 0xed;
329 msg
.sig
[3] = (char) 0xfe;
331 msg
.len
[0] = (char) nbytes
& 0xff;
332 msg
.len
[1] = (char) (nbytes
>> 8) & 0xff;
333 msg
.len
[2] = (char) (nbytes
>> 16) & 0xff;
334 msg
.len
[3] = (char) (nbytes
>> 24) & 0xff;
336 if (Write((char *)&msg
, sizeof(msg
)).LastCount() < sizeof(msg
))
338 if (Write(buffer
, nbytes
).LastCount() < nbytes
)
341 msg
.sig
[0] = (char) 0xed;
342 msg
.sig
[1] = (char) 0xfe;
343 msg
.sig
[2] = (char) 0xad;
344 msg
.sig
[3] = (char) 0xde;
345 msg
.len
[0] = msg
.len
[1] = msg
.len
[2] = msg
.len
[3] = (char) 0;
346 Write((char *)&msg
, sizeof(msg
));
351 #pragma warning(default: 4310)
352 #endif // __VISUALC__
355 wxSocketBase
& wxSocketBase::Unread(const char *buffer
, size_t nbytes
)
359 CreatePushbackAfter(buffer
, nbytes
);
365 bool wxSocketBase::IsData() const
370 return (GSocket_DataAvailable(m_socket
));
373 void wxSocketBase::DoDefer(GSocketEvent req_evt
)
377 if (req_evt
== GSOCK_LOST
) {
379 m_defer_buffer
= NULL
;
382 switch (m_defering
) {
384 ret
= GSocket_Read(m_socket
, m_defer_buffer
, m_defer_nbytes
);
387 ret
= GSocket_Write(m_socket
, m_defer_buffer
, m_defer_nbytes
);
394 m_defer_nbytes
-= ret
;
399 if ((m_flags
& WAITALL
) == 0 || m_defer_nbytes
== 0 || ret
< 0) {
400 m_defer_buffer
= NULL
;
403 m_defer_buffer
+= ret
;
406 // ---------------------------------------------------------------------
407 // --------- wxSocketBase Discard(): deletes all byte in the input queue
408 // ---------------------------------------------------------------------
409 void wxSocketBase::Discard()
411 #define MAX_BUFSIZE (10*1024)
412 char *my_data
= new char[MAX_BUFSIZE
];
413 size_t recv_size
= MAX_BUFSIZE
;
416 SetFlags(NOWAIT
| SPEED
);
418 while (recv_size
== MAX_BUFSIZE
)
420 recv_size
= Read(my_data
, MAX_BUFSIZE
).LastCount();
429 // --------------------------------------------------------------
430 // wxSocketBase socket info functions
431 // --------------------------------------------------------------
433 bool wxSocketBase::GetPeer(wxSockAddress
& addr_man
) const
440 peer
= GSocket_GetPeer(m_socket
);
441 addr_man
.SetAddress(peer
);
442 GAddress_destroy(peer
);
447 bool wxSocketBase::GetLocal(wxSockAddress
& addr_man
) const
454 local
= GSocket_GetLocal(m_socket
);
455 addr_man
.SetAddress(local
);
456 GAddress_destroy(local
);
461 // --------------------------------------------------------------
462 // wxSocketBase wait functions
463 // --------------------------------------------------------------
465 void wxSocketBase::SaveState()
467 wxSocketState
*state
;
469 state
= new wxSocketState();
471 state
->notify_state
= m_notify_state
;
472 state
->evt_notify_state
= m_neededreq
;
473 state
->socket_flags
= m_flags
;
474 state
->c_callback
= m_cbk
;
475 state
->c_callback_data
= m_cdata
;
477 m_states
.Append(state
);
480 void wxSocketBase::RestoreState()
483 wxSocketState
*state
;
485 node
= m_states
.Last();
489 state
= (wxSocketState
*)node
->Data();
491 SetFlags(state
->socket_flags
);
492 m_neededreq
= state
->evt_notify_state
;
493 m_cbk
= state
->c_callback
;
494 m_cdata
= state
->c_callback_data
;
495 Notify(state
->notify_state
);
501 // --------------------------------------------------------------
502 // --------- wxSocketBase callback functions --------------------
503 // --------------------------------------------------------------
505 wxSocketBase::wxSockCbk
wxSocketBase::Callback(wxSockCbk cbk_
)
507 wxSockCbk old_cbk
= cbk_
;
513 char *wxSocketBase::CallbackData(char *data
)
515 char *old_data
= m_cdata
;
521 // --------------------------------------------------------------
522 // --------- wxSocketBase wait functions ------------------------
523 // --------------------------------------------------------------
525 class _wxSocketInternalTimer
: public wxTimer
{
531 *m_state
= GSOCK_MAX_EVENT
; // Just to say it's a timeout.
535 static void wx_socket_wait(GSocket
*socket
, GSocketEvent event
, char *cdata
)
537 int *state
= (int *)cdata
;
542 bool wxSocketBase::_Wait(long seconds
, long milliseconds
, int type
)
544 bool old_notify_state
= m_notify_state
;
546 _wxSocketInternalTimer timer
;
548 if (!m_connected
|| !m_socket
)
551 timer
.m_state
= &state
;
555 timer
.Start(seconds
* 1000 + milliseconds
, TRUE
);
556 GSocket_SetFallback(m_socket
, type
, wx_socket_wait
, (char *)&state
);
561 GSocket_UnsetFallback(m_socket
, type
);
564 Notify(old_notify_state
);
566 return (state
!= GSOCK_MAX_EVENT
);
569 bool wxSocketBase::Wait(long seconds
, long milliseconds
)
571 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
572 GSOCK_CONNECTION_FLAG
| GSOCK_LOST_FLAG
);
575 bool wxSocketBase::WaitForRead(long seconds
, long milliseconds
)
577 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
| GSOCK_LOST_FLAG
);
580 bool wxSocketBase::WaitForWrite(long seconds
, long milliseconds
)
582 return _Wait(seconds
, milliseconds
, GSOCK_OUTPUT_FLAG
| GSOCK_LOST_FLAG
);
585 bool wxSocketBase::WaitForLost(long seconds
, long milliseconds
)
587 return _Wait(seconds
, milliseconds
, GSOCK_LOST_FLAG
);
590 // --------------------------------------------------------------
591 // --------- wxSocketBase callback management -------------------
592 // --------------------------------------------------------------
594 GSocketEventFlags
wxSocketBase::EventToNotify(GSocketEvent evt
)
599 return GSOCK_INPUT_FLAG
;
601 return GSOCK_OUTPUT_FLAG
;
602 case GSOCK_CONNECTION
:
603 return GSOCK_CONNECTION_FLAG
;
605 return GSOCK_LOST_FLAG
;
612 void wxSocketBase::SetFlags(wxSockFlags _flags
)
617 wxSocketBase::wxSockFlags
wxSocketBase::GetFlags() const
622 void wxSocketBase::SetNotify(GSocketEventFlags flags
)
624 /* Check if server */
625 if (m_type
!= SOCK_SERVER
)
626 flags
&= ~GSOCK_CONNECTION_FLAG
;
629 if (m_neededreq
== 0)
632 Notify(m_notify_state
);
635 // --------------------------------------------------------------
636 // Automatic notifier
637 // --------------------------------------------------------------
639 static void wx_socket_fallback(GSocket
*socket
, GSocketEvent event
, char *cdata
)
641 wxSocketBase
*sckobj
= (wxSocketBase
*)cdata
;
643 sckobj
->OnRequest(event
);
646 void wxSocketBase::Notify(bool notify
)
648 m_notify_state
= notify
;
652 GSocket_UnsetFallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
653 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
);
657 GSocket_SetFallback(m_socket
, m_neededreq
, wx_socket_fallback
, (char *)this);
660 void wxSocketBase::OnRequest(GSocketEvent req_evt
)
662 wxSocketEvent
event(m_id
);
663 GSocketEventFlags notify
= EventToNotify(req_evt
);
665 if (m_defering
!= NO_DEFER
) {
670 if ((m_neededreq
& notify
) == notify
) {
671 event
.m_socket
= this;
672 event
.m_skevt
= req_evt
;
674 OldOnNotify(req_evt
);
677 if (req_evt
== GSOCK_LOST
)
681 void wxSocketBase::OldOnNotify(GSocketEvent evt
)
685 // --------------------------------------------------------------
686 // --------- wxSocketBase functions [Callback, CallbackData] ----
687 // --------------------------------------------------------------
689 void wxSocketBase::SetEventHandler(wxEvtHandler
& h_evt
, int id
)
691 SetNextHandler(&h_evt
);
695 // --------------------------------------------------------------
696 // --------- wxSocketBase pushback library ----------------------
697 // --------------------------------------------------------------
699 void wxSocketBase::CreatePushbackAfter(const char *buffer
, size_t size
)
703 if (m_unread
!= NULL
)
704 m_unread
= (char *) realloc(m_unread
, m_unrd_size
+size
);
706 m_unread
= (char *) malloc(size
);
708 curr_pos
= m_unread
+ m_unrd_size
;
710 memcpy(curr_pos
, buffer
, size
);
714 void wxSocketBase::CreatePushbackBefore(const char *buffer
, size_t size
)
716 if (m_unread
== NULL
)
717 m_unread
= (char *)malloc(size
);
721 tmp
= (char *)malloc(m_unrd_size
+ size
);
722 memcpy(tmp
+size
, m_unread
, m_unrd_size
);
730 memcpy(m_unread
, buffer
, size
);
733 size_t wxSocketBase::GetPushback(char *buffer
, size_t size
, bool peek
)
738 if (size
> (m_unrd_size
-m_unrd_cur
))
739 size
= m_unrd_size
-m_unrd_cur
;
740 memcpy(buffer
, (m_unread
+m_unrd_cur
), size
);
744 if (m_unrd_size
== m_unrd_cur
) {
755 // --------------------------------------------------------------
757 // --------------------------------------------------------------
759 wxSocketServer::wxSocketServer(wxSockAddress
& addr_man
,
761 wxSocketBase(flags
, SOCK_SERVER
)
763 m_socket
= GSocket_new();
768 GSocket_SetLocal(m_socket
, addr_man
.GetAddress());
769 if (GSocket_SetServer(m_socket
) != GSOCK_NOERROR
) {
770 GSocket_destroy(m_socket
);
778 // --------------------------------------------------------------
779 // wxSocketServer Accept
780 // --------------------------------------------------------------
782 bool wxSocketServer::AcceptWith(wxSocketBase
& sock
)
784 GSocket
*child_socket
;
786 child_socket
= GSocket_WaitConnection(m_socket
);
788 sock
.m_type
= SOCK_INTERNAL
;
789 sock
.m_socket
= child_socket
;
790 sock
.m_connected
= TRUE
;
795 wxSocketBase
*wxSocketServer::Accept()
797 wxSocketBase
* sock
= new wxSocketBase();
799 sock
->SetFlags((wxSockFlags
)m_flags
);
801 if (!AcceptWith(*sock
))
807 // --------------------------------------------------------------
809 // --------------------------------------------------------------
811 // --------- wxSocketClient CONSTRUCTOR -------------------------
812 // --------------------------------------------------------------
813 wxSocketClient::wxSocketClient(wxSockFlags _flags
) :
814 wxSocketBase(_flags
, SOCK_CLIENT
)
818 // --------------------------------------------------------------
819 // --------- wxSocketClient DESTRUCTOR --------------------------
820 // --------------------------------------------------------------
821 wxSocketClient::~wxSocketClient()
825 // --------------------------------------------------------------
826 // --------- wxSocketClient Connect functions -------------------
827 // --------------------------------------------------------------
828 bool wxSocketClient::Connect(wxSockAddress
& addr_man
, bool WXUNUSED(wait
) )
833 // This should never happen.
835 GSocket_destroy(m_socket
);
837 // Initializes all socket stuff ...
838 // --------------------------------
839 m_socket
= GSocket_new();
846 // Update the flags of m_socket.
848 GSocket_SetPeer(m_socket
, addr_man
.GetAddress());
849 if (GSocket_Connect(m_socket
, GSOCK_STREAMED
) != GSOCK_NOERROR
)
852 // Enables bg events.
853 // ------------------
860 bool wxSocketClient::WaitOnConnect(long seconds
, long microseconds
)
862 int ret
= _Wait(seconds
, microseconds
, GSOCK_CONNECTION_FLAG
| GSOCK_LOST_FLAG
);
870 void wxSocketClient::OnRequest(GSocketEvent evt
)
872 if (evt
== GSOCK_CONNECTION
)
876 m_neededreq
&= ~GSOCK_CONNECTION_FLAG
;
882 wxSocketBase::OnRequest(evt
);
885 // --------------------------------------------------------------
887 // --------------------------------------------------------------
889 wxSocketEvent::wxSocketEvent(int id
)
892 wxEventType type
= (wxEventType
)wxEVT_SOCKET
;
897 void wxSocketEvent::CopyObject(wxObject
& obj_d
) const
899 wxSocketEvent
*event
= (wxSocketEvent
*)&obj_d
;
901 wxEvent::CopyObject(obj_d
);
903 event
->m_skevt
= m_skevt
;
904 event
->m_socket
= m_socket
;
907 // --------------------------------------------------------------------------
909 // --------------------------------------------------------------------------
910 class WXDLLEXPORT wxSocketModule
: public wxModule
{
911 DECLARE_DYNAMIC_CLASS(wxSocketModule
)
914 return GSocket_Init();
921 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule
, wxModule
)