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(600),
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(600),
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 // --------------------------------------------------------------
131 class _wxSocketInternalTimer
: public wxTimer
{
134 unsigned long m_new_val
;
138 *m_state
= m_new_val
; // Change the value
142 int wxSocketBase::DeferRead(char *buffer
, size_t nbytes
)
144 GSocketEventFlags old_event_flags
;
145 bool old_notify_state
;
147 _wxSocketInternalTimer timer
;
149 wxASSERT(m_defering
== NO_DEFER
);
151 // Set the defering mode to READ.
152 m_defering
= DEFER_READ
;
154 // Save the old state.
155 old_event_flags
= NeededReq();
156 old_notify_state
= m_notify_state
;
158 // Set the new async flag.
159 SetNotify(GSOCK_INPUT_FLAG
| GSOCK_LOST_FLAG
);
162 // Set the current buffer.
163 m_defer_buffer
= buffer
;
164 m_defer_nbytes
= nbytes
;
165 m_defer_timer
= &timer
;
167 timer
.m_state
= (int *)&m_defer_buffer
;
170 timer
.Start(m_timeout
* 1000, FALSE
);
172 // Wait for buffer completion.
173 while (m_defer_buffer
!= NULL
)
178 // Restore the old state.
179 Notify(old_notify_state
);
180 SetNotify(old_event_flags
);
182 // Disable defering mode.
183 m_defering
= NO_DEFER
;
184 m_defer_timer
= NULL
;
186 // Return the number of bytes read from the socket.
187 return nbytes
-m_defer_nbytes
;
190 wxSocketBase
& wxSocketBase::Read(char* buffer
, size_t nbytes
)
194 m_lcount
= GetPushback(buffer
, nbytes
, FALSE
);
201 // If we have got the whole needed buffer or if we don't want to
202 // wait then it returns immediately.
203 if (!nbytes
|| (m_lcount
&& !(m_flags
& WAITALL
)) ) {
207 if ((m_flags
& SPEED
) != 0) {
209 if ((m_flags
& WAITALL
) != 0) {
210 while (ret
> 0 && nbytes
> 0) {
211 ret
= GSocket_Read(m_socket
, buffer
, nbytes
);
216 // In case the last call was an error ...
220 ret
= GSocket_Read(m_socket
, buffer
, nbytes
);
226 ret
= DeferRead(buffer
, nbytes
);
235 wxSocketBase
& wxSocketBase::ReadMsg(char* buffer
, size_t nbytes
)
237 unsigned long len
, len2
, sig
;
243 // sig should be an explicit 32-bit unsigned integer; I've seen
244 // compilers in which size_t was actually a 16-bit unsigned integer
246 Read((char *)&msg
, sizeof(msg
));
247 if (m_lcount
!= sizeof(msg
))
250 sig
= msg
.sig
[0] & 0xff;
251 sig
|= (size_t)(msg
.sig
[1] & 0xff) << 8;
252 sig
|= (size_t)(msg
.sig
[2] & 0xff) << 16;
253 sig
|= (size_t)(msg
.sig
[3] & 0xff) << 24;
255 if (sig
!= 0xfeeddead)
257 len
= msg
.len
[0] & 0xff;
258 len
|= (size_t)(msg
.len
[1] & 0xff) << 8;
259 len
|= (size_t)(msg
.len
[2] & 0xff) << 16;
260 len
|= (size_t)(msg
.len
[3] & 0xff) << 24;
262 // len2 is incorrectly computed in the original; this sequence is
271 // the "len &&" in the following statement is necessary so that
272 // we don't attempt to read (and possibly hang the system)
273 // if the message was zero bytes long
274 if (len
&& Read(buffer
, len
).LastCount() != len
)
276 if (len2
&& (Read(NULL
, len2
).LastCount() != len2
))
278 if (Read((char *)&msg
, sizeof(msg
)).LastCount() != sizeof(msg
))
281 sig
= msg
.sig
[0] & 0xff;
282 sig
|= (size_t)(msg
.sig
[1] & 0xff) << 8;
283 sig
|= (size_t)(msg
.sig
[2] & 0xff) << 16;
284 sig
|= (size_t)(msg
.sig
[3] & 0xff) << 24;
287 if (sig
!= 0xdeadfeed)
288 wxLogDebug(_T("Warning: invalid signature returned to ReadMsg\n"));
293 wxSocketBase
& wxSocketBase::Peek(char* buffer
, size_t nbytes
)
295 Read(buffer
, nbytes
);
296 CreatePushbackAfter(buffer
, nbytes
);
301 int wxSocketBase::DeferWrite(const char *buffer
, size_t nbytes
)
303 GSocketEventFlags old_event_flags
;
304 bool old_notify_state
;
306 _wxSocketInternalTimer timer
;
308 wxASSERT(m_defering
== NO_DEFER
);
310 m_defering
= DEFER_WRITE
;
312 // Save the old state
313 old_event_flags
= NeededReq();
314 old_notify_state
= m_notify_state
;
316 SetNotify(GSOCK_OUTPUT_FLAG
| GSOCK_LOST_FLAG
);
319 // Set the current buffer
320 m_defer_buffer
= (char *)buffer
;
321 m_defer_nbytes
= nbytes
;
324 timer
.m_state
= (int *)&m_defer_buffer
;
327 m_defer_timer
= &timer
;
328 timer
.Start(m_timeout
* 1000, FALSE
);
330 while (m_defer_buffer
!= NULL
)
334 m_defer_timer
= NULL
;
337 // Restore the old state
338 Notify(old_notify_state
);
339 SetNotify(old_event_flags
);
341 m_defering
= NO_DEFER
;
343 return nbytes
-m_defer_nbytes
;
346 wxSocketBase
& wxSocketBase::Write(const char *buffer
, size_t nbytes
)
350 if ((m_flags
& SPEED
) != 0)
351 ret
= GSocket_Write(m_socket
, buffer
, nbytes
);
353 ret
= DeferWrite(buffer
, nbytes
);
361 wxSocketBase
& wxSocketBase::WriteMsg(const char *buffer
, size_t nbytes
)
368 // warning about 'cast truncates constant value'
370 #pragma warning(disable: 4310)
371 #endif // __VISUALC__
373 msg
.sig
[0] = (char) 0xad;
374 msg
.sig
[1] = (char) 0xde;
375 msg
.sig
[2] = (char) 0xed;
376 msg
.sig
[3] = (char) 0xfe;
378 msg
.len
[0] = (char) nbytes
& 0xff;
379 msg
.len
[1] = (char) (nbytes
>> 8) & 0xff;
380 msg
.len
[2] = (char) (nbytes
>> 16) & 0xff;
381 msg
.len
[3] = (char) (nbytes
>> 24) & 0xff;
383 if (Write((char *)&msg
, sizeof(msg
)).LastCount() < sizeof(msg
))
385 if (Write(buffer
, nbytes
).LastCount() < nbytes
)
388 msg
.sig
[0] = (char) 0xed;
389 msg
.sig
[1] = (char) 0xfe;
390 msg
.sig
[2] = (char) 0xad;
391 msg
.sig
[3] = (char) 0xde;
392 msg
.len
[0] = msg
.len
[1] = msg
.len
[2] = msg
.len
[3] = (char) 0;
393 Write((char *)&msg
, sizeof(msg
));
398 #pragma warning(default: 4310)
399 #endif // __VISUALC__
402 wxSocketBase
& wxSocketBase::Unread(const char *buffer
, size_t nbytes
)
406 CreatePushbackAfter(buffer
, nbytes
);
412 bool wxSocketBase::IsData() const
417 return (GSocket_DataAvailable(m_socket
));
420 void wxSocketBase::DoDefer(GSocketEvent req_evt
)
424 if (req_evt
== GSOCK_LOST
) {
426 m_defer_buffer
= NULL
;
429 switch (m_defering
) {
431 ret
= GSocket_Read(m_socket
, m_defer_buffer
, m_defer_nbytes
);
434 ret
= GSocket_Write(m_socket
, m_defer_buffer
, m_defer_nbytes
);
441 m_defer_nbytes
-= ret
;
446 // If we are waiting for all bytes to be acquired, keep the defering modei
448 if ((m_flags
& WAITALL
) == 0 || m_defer_nbytes
== 0 || ret
< 0) {
449 m_defer_buffer
= NULL
;
452 m_defer_buffer
+= ret
;
453 m_defer_timer
->Start(m_timeout
* 1000, FALSE
);
457 // ---------------------------------------------------------------------
458 // --------- wxSocketBase Discard(): deletes all byte in the input queue
459 // ---------------------------------------------------------------------
460 void wxSocketBase::Discard()
462 #define MAX_BUFSIZE (10*1024)
463 char *my_data
= new char[MAX_BUFSIZE
];
464 size_t recv_size
= MAX_BUFSIZE
;
467 SetFlags(NOWAIT
| SPEED
);
469 while (recv_size
== MAX_BUFSIZE
)
471 recv_size
= Read(my_data
, MAX_BUFSIZE
).LastCount();
480 // --------------------------------------------------------------
481 // wxSocketBase socket info functions
482 // --------------------------------------------------------------
484 bool wxSocketBase::GetPeer(wxSockAddress
& addr_man
) const
491 peer
= GSocket_GetPeer(m_socket
);
492 addr_man
.SetAddress(peer
);
493 GAddress_destroy(peer
);
498 bool wxSocketBase::GetLocal(wxSockAddress
& addr_man
) const
505 local
= GSocket_GetLocal(m_socket
);
506 addr_man
.SetAddress(local
);
507 GAddress_destroy(local
);
512 // --------------------------------------------------------------
513 // wxSocketBase wait functions
514 // --------------------------------------------------------------
516 void wxSocketBase::SaveState()
518 wxSocketState
*state
;
520 state
= new wxSocketState();
522 state
->notify_state
= m_notify_state
;
523 state
->evt_notify_state
= m_neededreq
;
524 state
->socket_flags
= m_flags
;
525 state
->c_callback
= m_cbk
;
526 state
->c_callback_data
= m_cdata
;
528 m_states
.Append(state
);
531 void wxSocketBase::RestoreState()
534 wxSocketState
*state
;
536 node
= m_states
.Last();
540 state
= (wxSocketState
*)node
->Data();
542 SetFlags(state
->socket_flags
);
543 m_neededreq
= state
->evt_notify_state
;
544 m_cbk
= state
->c_callback
;
545 m_cdata
= state
->c_callback_data
;
546 Notify(state
->notify_state
);
552 // --------------------------------------------------------------
553 // --------- wxSocketBase callback functions --------------------
554 // --------------------------------------------------------------
556 wxSocketBase::wxSockCbk
wxSocketBase::Callback(wxSockCbk cbk_
)
558 wxSockCbk old_cbk
= cbk_
;
564 char *wxSocketBase::CallbackData(char *data
)
566 char *old_data
= m_cdata
;
572 // --------------------------------------------------------------
573 // --------- wxSocketBase wait functions ------------------------
574 // --------------------------------------------------------------
576 static void wx_socket_wait(GSocket
*socket
, GSocketEvent event
, char *cdata
)
578 int *state
= (int *)cdata
;
583 bool wxSocketBase::_Wait(long seconds
, long milliseconds
, int type
)
585 bool old_notify_state
= m_notify_state
;
587 _wxSocketInternalTimer timer
;
589 if (!m_connected
|| !m_socket
)
592 // Set the variable to change
593 timer
.m_state
= &state
;
594 timer
.m_new_val
= GSOCK_MAX_EVENT
;
596 // Disable the previous handler
600 timer
.Start(seconds
* 1000 + milliseconds
, TRUE
);
601 GSocket_SetCallback(m_socket
, type
, wx_socket_wait
, (char *)&state
);
606 GSocket_UnsetCallback(m_socket
, type
);
609 // Notify will restore automatically the old GSocket flags
610 Notify(old_notify_state
);
612 return (state
!= GSOCK_MAX_EVENT
);
615 bool wxSocketBase::Wait(long seconds
, long milliseconds
)
617 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
618 GSOCK_CONNECTION_FLAG
| GSOCK_LOST_FLAG
);
621 bool wxSocketBase::WaitForRead(long seconds
, long milliseconds
)
623 return _Wait(seconds
, milliseconds
, GSOCK_INPUT_FLAG
| GSOCK_LOST_FLAG
);
626 bool wxSocketBase::WaitForWrite(long seconds
, long milliseconds
)
628 return _Wait(seconds
, milliseconds
, GSOCK_OUTPUT_FLAG
| GSOCK_LOST_FLAG
);
631 bool wxSocketBase::WaitForLost(long seconds
, long milliseconds
)
633 return _Wait(seconds
, milliseconds
, GSOCK_LOST_FLAG
);
636 // --------------------------------------------------------------
637 // --------- wxSocketBase callback management -------------------
638 // --------------------------------------------------------------
640 GSocketEventFlags
wxSocketBase::EventToNotify(GSocketEvent evt
)
645 return GSOCK_INPUT_FLAG
;
647 return GSOCK_OUTPUT_FLAG
;
648 case GSOCK_CONNECTION
:
649 return GSOCK_CONNECTION_FLAG
;
651 return GSOCK_LOST_FLAG
;
658 void wxSocketBase::SetFlags(wxSockFlags _flags
)
663 wxSocketBase::wxSockFlags
wxSocketBase::GetFlags() const
668 void wxSocketBase::SetNotify(GSocketEventFlags flags
)
670 /* Check if server */
671 if (m_type
!= SOCK_SERVER
)
672 flags
&= ~GSOCK_CONNECTION_FLAG
;
675 if (m_neededreq
== 0)
678 Notify(m_notify_state
);
681 // --------------------------------------------------------------
682 // Automatic notifier
683 // --------------------------------------------------------------
685 static void wx_socket_fallback(GSocket
*socket
, GSocketEvent event
, char *cdata
)
687 wxSocketBase
*sckobj
= (wxSocketBase
*)cdata
;
689 sckobj
->OnRequest(event
);
692 void wxSocketBase::Notify(bool notify
)
694 m_notify_state
= notify
;
698 GSocket_UnsetCallback(m_socket
, GSOCK_INPUT_FLAG
| GSOCK_OUTPUT_FLAG
|
699 GSOCK_LOST_FLAG
| GSOCK_CONNECTION_FLAG
);
703 GSocket_SetCallback(m_socket
, m_neededreq
, wx_socket_fallback
, (char *)this);
706 void wxSocketBase::OnRequest(GSocketEvent req_evt
)
708 wxSocketEvent
event(m_id
);
709 GSocketEventFlags notify
= EventToNotify(req_evt
);
711 if (m_defering
!= NO_DEFER
) {
716 if ((m_neededreq
& notify
) == notify
) {
717 event
.m_socket
= this;
718 event
.m_skevt
= req_evt
;
720 OldOnNotify(req_evt
);
723 if (req_evt
== GSOCK_LOST
)
727 void wxSocketBase::OldOnNotify(GSocketEvent evt
)
731 // --------------------------------------------------------------
732 // --------- wxSocketBase functions [Callback, CallbackData] ----
733 // --------------------------------------------------------------
735 void wxSocketBase::SetEventHandler(wxEvtHandler
& h_evt
, int id
)
737 SetNextHandler(&h_evt
);
741 // --------------------------------------------------------------
742 // --------- wxSocketBase pushback library ----------------------
743 // --------------------------------------------------------------
745 void wxSocketBase::CreatePushbackAfter(const char *buffer
, size_t size
)
749 if (m_unread
!= NULL
)
750 m_unread
= (char *) realloc(m_unread
, m_unrd_size
+size
);
752 m_unread
= (char *) malloc(size
);
754 curr_pos
= m_unread
+ m_unrd_size
;
756 memcpy(curr_pos
, buffer
, size
);
760 void wxSocketBase::CreatePushbackBefore(const char *buffer
, size_t size
)
762 if (m_unread
== NULL
)
763 m_unread
= (char *)malloc(size
);
767 tmp
= (char *)malloc(m_unrd_size
+ size
);
768 memcpy(tmp
+size
, m_unread
, m_unrd_size
);
776 memcpy(m_unread
, buffer
, size
);
779 size_t wxSocketBase::GetPushback(char *buffer
, size_t size
, bool peek
)
784 if (size
> (m_unrd_size
-m_unrd_cur
))
785 size
= m_unrd_size
-m_unrd_cur
;
786 memcpy(buffer
, (m_unread
+m_unrd_cur
), size
);
790 if (m_unrd_size
== m_unrd_cur
) {
801 // --------------------------------------------------------------
803 // --------------------------------------------------------------
805 wxSocketServer::wxSocketServer(wxSockAddress
& addr_man
,
807 wxSocketBase(flags
, SOCK_SERVER
)
809 m_socket
= GSocket_new();
814 GSocket_SetLocal(m_socket
, addr_man
.GetAddress());
815 if (GSocket_SetServer(m_socket
) != GSOCK_NOERROR
) {
816 GSocket_destroy(m_socket
);
824 // --------------------------------------------------------------
825 // wxSocketServer Accept
826 // --------------------------------------------------------------
828 bool wxSocketServer::AcceptWith(wxSocketBase
& sock
)
830 GSocket
*child_socket
;
832 child_socket
= GSocket_WaitConnection(m_socket
);
834 sock
.m_type
= SOCK_INTERNAL
;
835 sock
.m_socket
= child_socket
;
836 sock
.m_connected
= TRUE
;
841 wxSocketBase
*wxSocketServer::Accept()
843 wxSocketBase
* sock
= new wxSocketBase();
845 sock
->SetFlags((wxSockFlags
)m_flags
);
847 if (!AcceptWith(*sock
))
853 // --------------------------------------------------------------
855 // --------------------------------------------------------------
857 // --------- wxSocketClient CONSTRUCTOR -------------------------
858 // --------------------------------------------------------------
859 wxSocketClient::wxSocketClient(wxSockFlags _flags
) :
860 wxSocketBase(_flags
, SOCK_CLIENT
)
864 // --------------------------------------------------------------
865 // --------- wxSocketClient DESTRUCTOR --------------------------
866 // --------------------------------------------------------------
867 wxSocketClient::~wxSocketClient()
871 // --------------------------------------------------------------
872 // --------- wxSocketClient Connect functions -------------------
873 // --------------------------------------------------------------
874 bool wxSocketClient::Connect(wxSockAddress
& addr_man
, bool WXUNUSED(wait
) )
879 // This should never happen.
881 GSocket_destroy(m_socket
);
883 // Initializes all socket stuff ...
884 // --------------------------------
885 m_socket
= GSocket_new();
892 // Update the flags of m_socket.
894 GSocket_SetPeer(m_socket
, addr_man
.GetAddress());
895 if (GSocket_Connect(m_socket
, GSOCK_STREAMED
) != GSOCK_NOERROR
)
898 // Enables bg events.
899 // ------------------
906 bool wxSocketClient::WaitOnConnect(long seconds
, long microseconds
)
908 int ret
= _Wait(seconds
, microseconds
, GSOCK_CONNECTION_FLAG
| GSOCK_LOST_FLAG
);
916 void wxSocketClient::OnRequest(GSocketEvent evt
)
918 if (evt
== GSOCK_CONNECTION
)
922 m_neededreq
&= ~GSOCK_CONNECTION_FLAG
;
928 wxSocketBase::OnRequest(evt
);
931 // --------------------------------------------------------------
933 // --------------------------------------------------------------
935 wxSocketEvent::wxSocketEvent(int id
)
938 wxEventType type
= (wxEventType
)wxEVT_SOCKET
;
943 void wxSocketEvent::CopyObject(wxObject
& obj_d
) const
945 wxSocketEvent
*event
= (wxSocketEvent
*)&obj_d
;
947 wxEvent::CopyObject(obj_d
);
949 event
->m_skevt
= m_skevt
;
950 event
->m_socket
= m_socket
;
953 // --------------------------------------------------------------------------
955 // --------------------------------------------------------------------------
956 class WXDLLEXPORT wxSocketModule
: public wxModule
{
957 DECLARE_DYNAMIC_CLASS(wxSocketModule
)
960 return GSocket_Init();
967 IMPLEMENT_DYNAMIC_CLASS(wxSocketModule
, wxModule
)