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 // -------------------------------------------------------------- 
 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
)