1 /* ------------------------------------------------------------------------- 
   2  * Project:     GSocket (Generic Socket) for WX 
   3  * Name:        src/mac/carbon/gsocket.cpp 
   4  * Copyright:   (c) Guilhem Lavaux 
   5  * Licence:     wxWindows Licence 
   6  * Authors:     Guilhem Lavaux, 
   7  *              Guillermo Rodriguez Garcia <guille@iies.es> (maintainer) 
   9  * Purpose:     GSocket main mac file 
  11  * ------------------------------------------------------------------------- 
  15  * PLEASE don't put C++ comments here - this is a C source file. 
  18 #ifndef __GSOCKET_STANDALONE__ 
  19 #include "wx/platform.h" 
  22 #if wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) 
  25     #include <CoreServices/CoreServices.h> 
  27     #include <MacHeaders.c> 
  28     #define OTUNIXERRORS 1 
  29     #include <OpenTransport.h> 
  30     #include <OpenTransportProviders.h> 
  31     #include <OpenTptInternet.h> 
  33 #if TARGET_CARBON && !defined(OTAssert) 
  34     #define OTAssert( str , cond ) /* does not exists in Carbon */ 
  48  * INADDR_BROADCAST is identical to INADDR_NONE which is not defined 
  49  * on all unices. INADDR_BROADCAST should be fine to indicate an error. 
  51 #ifndef INADDR_BROADCAST 
  52 #define INADDR_BROADCAST 0xFFFFFFFFUL 
  55 #define INADDR_NONE INADDR_BROADCAST 
  58 #define INADDR_ANY 0x0UL 
  60 #ifndef __GSOCKET_STANDALONE__ 
  62     #include "wx/mac/macnotfy.h" 
  63     #include "wx/mac/gsockmac.h" 
  64     #include "wx/gsocket.h" 
  71 #endif /* __GSOCKET_STANDALONE__ */ 
  84 extern pascal void OTDebugStr(const char* str
); 
  89 InetSvcRef gInetSvcRef 
= 0 ; 
  91 OTNotifyUPP gOTNotifierUPP 
= NULL 
; 
  93 OSStatus 
DoNegotiateIPReuseAddrOption(EndpointRef ep
, Boolean enableReuseIPMode
); 
  95 /* Input: ep - endpointref on which to negotiate the option 
  96                enableReuseIPMode - desired option setting - true/false 
  97    Return: kOTNoError indicates that the option was successfully negotiated 
  98            OSStatus is an error if < 0, otherwise, the status field is 
 101    IMPORTANT NOTE: The endpoint is assumed to be in synchronous more, otherwise 
 102                    this code will not function as desired 
 106 OSStatus 
DoNegotiateIPReuseAddrOption(EndpointRef ep
, Boolean enableReuseIPMode
) 
 109     UInt8        buf
[kOTFourByteOptionSize
]; // define buffer for fourByte Option size 
 110     TOption
*     opt
;                        // option ptr to make items easier to access 
 115     if (!OTIsSynchronous(ep
)) 
 119     opt 
= (TOption
*)buf
; // set option ptr to buffer 
 121     req
.opt
.len 
= sizeof(buf
); 
 122     req
.flags   
= T_NEGOTIATE
;    // negotiate for option 
 125     ret
.opt
.maxlen 
= kOTFourByteOptionSize
; 
 127     opt
->level  
= INET_IP
;        // dealing with an IP Level function 
 129     opt
->name   
= kIP_REUSEADDR
; 
 131     opt
->name   
= IP_REUSEADDR
; 
 133     opt
->len    
= kOTFourByteOptionSize
; 
 135     *(UInt32
*)opt
->value 
= enableReuseIPMode
;   // set the desired option level, true or false 
 137     err 
= OTOptionManagement(ep
, &req
, &ret
); 
 139     // if no error then return the option status value 
 140     if (err 
== kOTNoError
) 
 142         if (opt
->status 
!= T_SUCCESS
) 
 152 pascal void OTInetEventHandler(void*s
, OTEventCode event
, OTResult
, void *cookie
) ; 
 153 pascal void OTInetEventHandler(void*s
, OTEventCode event
, OTResult result
, void *cookie
) 
 156     GSocket
* sock 
= (GSocket
*) s 
; 
 158     if ( event 
== kOTSyncIdleEvent 
) 
 165         wxMacAddEvent( sock
->m_mac_events 
, _GSocket_Internal_Proc 
, event 
, s 
, wakeUp 
) ; 
 171 static void SetDefaultEndpointModes(EndpointRef ep 
, void *data 
) 
 172     // This routine sets the supplied endpoint into the default 
 173     // mode used in this application.  The specifics are: 
 174     // blocking, synchronous, and using synch idle events with 
 175     // the standard YieldingNotifier. 
 177     OSStatus junk 
= kOTNoError 
; 
 178     OTAssert ("SetDefaultEndpointModes:invalid ref", ep 
!= kOTInvalidEndpointRef 
) ; 
 179     junk 
= OTSetAsynchronous(ep
); 
 180     OTAssert("SetDefaultEndpointModes: Could not set asynchronous", junk 
== noErr
); 
 182     junk = OTSetBlocking(ep); 
 183     OTAssert("SetDefaultEndpointModes: Could not set blocking", junk == noErr); 
 184     junk = OTSetSynchronous(ep); 
 185     OTAssert("SetDefaultEndpointModes: Could not set synchronous", junk == noErr); 
 186     junk = OTSetBlocking(ep); 
 187     OTAssert("SetDefaultEndpointModes: Could not set blocking", junk == noErr); 
 189     junk 
= OTInstallNotifier(ep
, gOTNotifierUPP
, data
); 
 190     OTAssert("SetDefaultEndpointModes: Could not install notifier", junk 
== noErr
); 
 192     junk = OTUseSyncIdleEvents(ep, true); 
 193     OTAssert("SetDefaultEndpointModes: Could not use sync idle events", junk == noErr); 
 202 bool GSocket_Verify_Inited() 
 206     // Marc Newsam: added the clientcontext variable 
 207     //              however, documentation is unclear how this works 
 208     OTClientContextPtr clientcontext
; 
 213     InitOpenTransportInContext(kInitOTForApplicationMask
, &clientcontext
); 
 215     gInetSvcRef 
= OTOpenInternetServicesInContext(kDefaultInternetServicesPath
, 
 216                                                   NULL
, &err
, clientcontext
); 
 221     InitOpenTransport() ; 
 223     gInetSvcRef 
= OTOpenInternetServices(kDefaultInternetServicesPath
, NULL
, &err
); 
 225     if ( gInetSvcRef 
== NULL 
||  err 
!= kOTNoError 
) 
 227         OTAssert("Could not open Inet Services", err 
== noErr
); 
 230     gOTNotifierUPP 
= NewOTNotifyUPP( OTInetEventHandler 
) ; 
 234 void GSocket_Cleanup() 
 236     if ( gOTInited 
!= 0 ) 
 238         if ( gInetSvcRef 
!= NULL 
) 
 239             OTCloseProvider( gInetSvcRef 
); 
 241       CloseOpenTransportInContext( NULL 
) ; 
 243       CloseOpenTransport() ; 
 245         if ( gOTNotifierUPP 
) 
 246             DisposeOTNotifyUPP( gOTNotifierUPP 
) ; 
 250 /* Constructors / Destructors for GSocket */ 
 256   m_ok 
= GSocket_Verify_Inited(); 
 259   for (i
=0;i
<GSOCK_MAX_EVENT
;i
++) 
 266   m_error               
= GSOCK_NOERROR
; 
 269   m_non_blocking        
= false; 
 271                                 /* 10 sec * 1000 millisec */ 
 272   m_takesEvents         
= true ; 
 273   m_mac_events          
= wxMacGetNotifierTable() ; 
 280     /* Check that the socket is really shutdowned */ 
 281     if (m_endpoint 
!= kOTInvalidEndpointRef
) 
 285     /* Destroy private addresses */ 
 287         GAddress_destroy(m_local
); 
 290         GAddress_destroy(m_peer
); 
 294  *  Disallow further read/write operations on this socket, close 
 295  *  the fd and disable all callbacks. 
 297 void GSocket::Shutdown() 
 304     /* If socket has been created, shutdown it */ 
 305     if (m_endpoint 
!= kOTInvalidEndpointRef 
) 
 307         err 
= OTSndOrderlyDisconnect( m_endpoint 
) ; 
 308         if ( err 
!= kOTNoError 
) 
 312         err 
= OTRcvOrderlyDisconnect( m_endpoint 
) ; 
 313         err 
= OTUnbind( m_endpoint 
) ; 
 314         err 
= OTCloseProvider( m_endpoint 
) ; 
 315         m_endpoint 
= kOTInvalidEndpointRef 
; 
 318     /* Disable GUI callbacks */ 
 319     for (evt 
= 0; evt 
< GSOCK_MAX_EVENT
; evt
++) 
 320         m_cbacks
[evt
] = NULL
; 
 324     wxMacRemoveAllNotifiersForData( wxMacGetNotifierTable() , this ) ; 
 328 /* Address handling */ 
 334  *  Set or get the local or peer address for this socket. The 'set' 
 335  *  functions return GSOCK_NOERROR on success, an error code otherwise. 
 336  *  The 'get' functions return a pointer to a GAddress object on success, 
 337  *  or NULL otherwise, in which case they set the error code of the 
 338  *  corresponding GSocket. 
 341  *    GSOCK_INVSOCK - the socket is not valid. 
 342  *    GSOCK_INVADDR - the address is not valid. 
 344 GSocketError 
GSocket::SetLocal(GAddress 
*address
) 
 348     /* the socket must be initialized, or it must be a server */ 
 349     if ((m_endpoint 
!= kOTInvalidEndpointRef 
&& !m_server
)) 
 351         m_error 
= GSOCK_INVSOCK
; 
 352         return GSOCK_INVSOCK
; 
 356     if (address 
== NULL 
|| address
->m_family 
== GSOCK_NOFAMILY
) 
 358         m_error 
= GSOCK_INVADDR
; 
 359         return GSOCK_INVADDR
; 
 363         GAddress_destroy(m_local
); 
 365     m_local 
= GAddress_copy(address
); 
 367     return GSOCK_NOERROR
; 
 370 GSocketError 
GSocket::SetPeer(GAddress 
*address
) 
 375     if (address 
== NULL 
|| address
->m_family 
== GSOCK_NOFAMILY
) 
 377         m_error 
= GSOCK_INVADDR
; 
 378         return GSOCK_INVADDR
; 
 382         GAddress_destroy(m_peer
); 
 384     m_peer 
= GAddress_copy(address
); 
 386     return GSOCK_NOERROR
; 
 389 GAddress 
*GSocket::GetLocal() 
 391     GAddress 
*address 
= NULL 
; 
 397     /* try to get it from the m_local var first */ 
 399         return GAddress_copy(m_local
); 
 401     /* else, if the socket is initialized, try getsockname */ 
 402     if (m_endpoint 
== kOTInvalidEndpointRef
) 
 404         m_error 
= GSOCK_INVSOCK
; 
 409 /* we do not support multihoming with this code at the moment 
 410    OTGetProtAddress will have to be used then - but we don't have a handy 
 411    method to use right now 
 414         InetInterfaceInfo info
; 
 415         OTInetGetInterfaceInfo(&info
, kDefaultInetInterface
); 
 416         loc
.fHost 
= info
.fAddress 
; 
 418         loc
.fAddressType 
= AF_INET 
; 
 421     /* got a valid address from getsockname, create a GAddress object */ 
 422     address 
= GAddress_new(); 
 425         m_error 
= GSOCK_MEMERR
; 
 429     err 
= _GAddress_translate_from(address
, &loc
); 
 430     if (err 
!= GSOCK_NOERROR
) 
 432         GAddress_destroy(address
); 
 440 GAddress 
*GSocket::GetPeer() 
 444     /* try to get it from the m_peer var */ 
 446         return GAddress_copy(m_peer
); 
 451 /* Server specific parts */ 
 453 /* GSocket_SetServer: 
 454  *  Sets up this socket as a server. The local address must have been 
 455  *  set with GSocket_SetLocal() before GSocket_SetServer() is called. 
 456  *  Returns GSOCK_NOERROR on success, one of the following otherwise: 
 459  *    GSOCK_INVSOCK - the socket is in use. 
 460  *    GSOCK_INVADDR - the local address has not been set. 
 461  *    GSOCK_IOERR   - low-level error. 
 463 GSocketError 
GSocket::SetServer() 
 467   /* must not be in use */ 
 468   if (m_endpoint 
!= kOTInvalidEndpointRef 
) 
 470     m_error 
= GSOCK_INVSOCK
; 
 471     return GSOCK_INVSOCK
; 
 474   /* the local addr must have been set */ 
 477     m_error 
= GSOCK_INVADDR
; 
 478     return GSOCK_INVADDR
; 
 481   /* Initialize all fields */ 
 488   /* Create the socket */ 
 489   m_endpoint 
= socket(m_local
->m_realfamily
, SOCK_STREAM
, 0); 
 490   socket_set_ref( m_endpoint 
, (unsigned long) &gMacNetEvents 
,  (unsigned long) this ) ; 
 491   if (m_endpoint 
== kOTInvalidEndpointRef
) 
 493     m_error 
= GSOCK_IOERR
; 
 497   ioctl(m_endpoint
, FIONBIO
, &arg
); 
 500   /* Bind to the local address, 
 501    * retrieve the actual address bound, 
 502    * and listen up to 5 connections. 
 504   if ((bind(m_endpoint
, m_local
->m_addr
, m_local
->m_len
) != 0) || 
 505       (getsockname(m_endpoint
, 
 507                    (WX_SOCKLEN_T 
*) &m_local
->m_len
) != 0) || 
 508       (listen(m_endpoint
, 5) != 0)) 
 512     m_error 
= GSOCK_IOERR
; 
 516   return GSOCK_NOERROR
; 
 519 /* GSocket_WaitConnection: 
 520  *  Waits for an incoming client connection. Returns a pointer to 
 521  *  a GSocket object, or NULL if there was an error, in which case 
 522  *  the last error field will be updated for the calling GSocket. 
 524  *  Error codes (set in the calling GSocket) 
 525  *    GSOCK_INVSOCK    - the socket is not valid or not a server. 
 526  *    GSOCK_TIMEDOUT   - timeout, no incoming connections. 
 527  *    GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking. 
 528  *    GSOCK_MEMERR     - couldn't allocate memory. 
 529  *    GSOCK_IOERR      - low-level error. 
 531 GSocket 
*GSocket::WaitConnection() 
 533   GSocket 
*connection 
= NULL 
; 
 537   /* Reenable CONNECTION events */ 
 538   m_detected 
&= ~GSOCK_CONNECTION_FLAG
; 
 540   /* If the socket has already been created, we exit immediately */ 
 541   if (m_endpoint 
== kOTInvalidEndpointRef 
|| !m_server
) 
 543     m_error 
= GSOCK_INVSOCK
; 
 547   /* Create a GSocket object for the new connection */ 
 548   connection 
= GSocket_new(); 
 552     m_error 
= GSOCK_MEMERR
; 
 556   /* Wait for a connection (with timeout) */ 
 557   if (Input_Timeout() == GSOCK_TIMEDOUT
) 
 560     /* m_error set by _GSocket_Input_Timeout */ 
 566   connection
->m_endpoint 
= accept(m_endpoint
, &from
, (WX_SOCKLEN_T 
*) &fromlen
); 
 569   if (connection
->m_endpoint 
== kOTInvalidEndpointRef 
) 
 571     if (errno 
== EWOULDBLOCK
) 
 572       m_error 
= GSOCK_WOULDBLOCK
; 
 574       m_error 
= GSOCK_IOERR
; 
 580   /* Initialize all fields */ 
 581   connection
->m_server   
= false; 
 582   connection
->m_stream   
= true; 
 583   connection
->m_oriented 
= true; 
 585   /* Setup the peer address field */ 
 586   connection
->m_peer 
= GAddress_new(); 
 587   if (!connection
->m_peer
) 
 590     m_error 
= GSOCK_MEMERR
; 
 595   err 
= _GAddress_translate_from(connection
->m_peer
, &from
, fromlen
); 
 596   if (err 
!= GSOCK_NOERROR
) 
 598     GAddress_destroy(connection
->m_peer
); 
 599     GSocket_destroy(connection
); 
 604   ioctl(connection
->m_endpoint
, FIONBIO
, &arg
); 
 606   connection
->Enable_Events(); 
 611 /* Datagram sockets */ 
 613 /* GSocket_SetNonOriented: 
 614  *  Sets up this socket as a non-connection oriented (datagram) socket. 
 615  *  Before using this function, the local address must have been set 
 616  *  with GSocket_SetLocal(), or the call will fail. Returns GSOCK_NOERROR 
 617  *  on success, or one of the following otherwise. 
 620  *    GSOCK_INVSOCK - the socket is in use. 
 621  *    GSOCK_INVADDR - the local address has not been set. 
 622  *    GSOCK_IOERR   - low-level error. 
 624 GSocketError 
GSocket::SetNonOriented() 
 628   if (m_endpoint 
!= kOTInvalidEndpointRef 
) 
 630     m_error 
= GSOCK_INVSOCK
; 
 631     return GSOCK_INVSOCK
; 
 636     m_error 
= GSOCK_INVADDR
; 
 637     return GSOCK_INVADDR
; 
 640   /* Initialize all fields */ 
 645   /* Create the socket */ 
 649   m_endpoint 
= socket(m_local
->m_realfamily
, SOCK_DGRAM
, 0); 
 650   socket_set_ref( m_endpoint 
, (unsigned long) &gMacNetEvents 
,  (unsigned long) this ) ; 
 652   if (m_endpoint 
== kOTInvalidEndpointRef 
) 
 654     m_error 
= GSOCK_IOERR
; 
 660   ioctl(m_endpoint
, FIONBIO
, &arg
); 
 664   /* Bind to the local address, 
 665    * and retrieve the actual address bound. 
 669   if ((bind(m_endpoint
, m_local
->m_addr
, m_local
->m_len
) != 0) || 
 670       (getsockname(m_endpoint
, 
 672                    (WX_SOCKLEN_T 
*) &m_local
->m_len
) != 0)) 
 676     m_error 
= GSOCK_IOERR
; 
 680   return GSOCK_NOERROR
; 
 683 /* Client specific parts */ 
 686  *  For stream (connection oriented) sockets, GSocket_Connect() tries 
 687  *  to establish a client connection to a server using the peer address 
 688  *  as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the 
 689  *  connection has been successfully established, or one of the error 
 690  *  codes listed below. Note that for nonblocking sockets, a return 
 691  *  value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection 
 692  *  request can be completed later; you should use GSocket_Select() 
 693  *  to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the 
 694  *  corresponding asynchronous events. 
 696  *  For datagram (non connection oriented) sockets, GSocket_Connect() 
 697  *  just sets the peer address established with GSocket_SetPeer() as 
 698  *  default destination. 
 701  *    GSOCK_INVSOCK    - the socket is in use or not valid. 
 702  *    GSOCK_INVADDR    - the peer address has not been established. 
 703  *    GSOCK_TIMEDOUT   - timeout, the connection failed. 
 704  *    GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only) 
 705  *    GSOCK_MEMERR     - couldn't allocate memory. 
 706  *    GSOCK_IOERR      - low-level error. 
 708 GSocketError 
GSocket::Connect(GSocketStream stream
) 
 712    OSStatus       err 
= kOTNoError
; 
 717   /* Enable CONNECTION events (needed for nonblocking connections) */ 
 718   m_detected 
&= ~GSOCK_CONNECTION_FLAG
; 
 720   if (m_endpoint 
!= kOTInvalidEndpointRef 
) 
 722     m_error 
= GSOCK_INVSOCK
; 
 723     return GSOCK_INVSOCK
; 
 728     m_error 
= GSOCK_INVADDR
; 
 729     return GSOCK_INVADDR
; 
 732   /* Streamed or dgram socket? */ 
 733   m_stream   
= (stream 
== GSOCK_STREAMED
); 
 737   /* Create the socket */ 
 740       OTOpenEndpointInContext( OTCreateConfiguration( kTCPName
) , 0 , &info 
, &err 
, NULL 
) ; 
 743       OTOpenEndpoint( OTCreateConfiguration( kTCPName
) , 0 , &info 
, &err 
) ; 
 745   if ( m_endpoint 
== kOTInvalidEndpointRef 
|| err 
!= kOTNoError 
) 
 747     m_endpoint 
= kOTInvalidEndpointRef 
; 
 748     m_error 
= GSOCK_IOERR
; 
 751   err 
= OTBind( m_endpoint 
, nil 
, nil 
) ; 
 752   if ( err 
!= kOTNoError 
) 
 756   SetDefaultEndpointModes( m_endpoint 
, this ) ; 
 759   ioctl(m_endpoint
, FIONBIO
, &arg
); 
 763   _GAddress_translate_to( m_peer 
, &addr 
) ; 
 764   memset( &peer 
, 0 , sizeof( TCall 
) ) ; 
 765   peer
.addr
.len 
= sizeof( InetAddress 
) ; 
 766   peer
.addr
.buf 
= (unsigned char*) &addr 
; 
 767   err 
= OTConnect( m_endpoint 
, &peer 
, nil 
) ; 
 770     /* If connect failed with EINPROGRESS and the GSocket object 
 771      * is in blocking mode, we select() for the specified timeout 
 772      * checking for writability to see if the connection request 
 776     if ((err 
== kOTNoDataErr 
) && (!m_non_blocking
)) 
 778       if (Output_Timeout() == GSOCK_TIMEDOUT
) 
 780         OTSndOrderlyDisconnect( m_endpoint 
) ; 
 781         m_endpoint 
= kOTInvalidEndpointRef 
; 
 782         /* m_error is set in _GSocket_Output_Timeout */ 
 783         return GSOCK_TIMEDOUT
; 
 789         WX_SOCKLEN_T len = sizeof(error); 
 791         getsockopt(m_endpoint, SOL_SOCKET, SO_ERROR, (void*) &error, &len); 
 795           return GSOCK_NOERROR
; 
 799     /* If connect failed with EINPROGRESS and the GSocket object 
 800      * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK 
 801      * (and return GSOCK_WOULDBLOCK) but we don't close the socket; 
 802      * this way if the connection completes, a GSOCK_CONNECTION 
 803      * event will be generated, if enabled. 
 805     if ((err 
== kOTNoDataErr
) && (m_non_blocking
)) 
 807       m_error 
= GSOCK_WOULDBLOCK
; 
 808       return GSOCK_WOULDBLOCK
; 
 811     /* If connect failed with an error other than EINPROGRESS, 
 812      * then the call to GSocket_Connect has failed. 
 814     OTSndOrderlyDisconnect( m_endpoint 
) ; 
 816     m_endpoint 
= kOTInvalidEndpointRef 
; 
 817     m_error 
= GSOCK_IOERR
; 
 820 //  OTInetEventHandler(this, T_CONNECT , kOTNoError , NULL ) ; 
 821   return GSOCK_NOERROR
; 
 826 /* Like recv(), send(), ... */ 
 827 int GSocket::Read(char *buffer
, int size
) 
 833   /* Reenable INPUT events */ 
 834   m_detected 
&= ~GSOCK_INPUT_FLAG
; 
 836   if (m_endpoint 
== kOTInvalidEndpointRef 
|| m_server
) 
 838     m_error 
= GSOCK_INVSOCK
; 
 842   /* If the socket is blocking, wait for data (with a timeout) */ 
 843   if (Input_Timeout() == GSOCK_TIMEDOUT
) 
 848     ret 
= Recv_Stream(buffer
, size
); 
 850     ret 
= Recv_Dgram(buffer
, size
); 
 854     if (errno 
== EWOULDBLOCK
) 
 855       m_error 
= GSOCK_WOULDBLOCK
; 
 857       m_error 
= GSOCK_IOERR
; 
 863 int GSocket::Write(const char *buffer
, int size
) 
 869   if (m_endpoint 
== kOTInvalidEndpointRef 
|| m_server
) 
 871     m_error 
= GSOCK_INVSOCK
; 
 875   /* If the socket is blocking, wait for writability (with a timeout) */ 
 876   if (Output_Timeout() == GSOCK_TIMEDOUT
) 
 881     ret 
= Send_Stream(buffer
, size
); 
 883     ret 
= Send_Dgram(buffer
, size
); 
 887     if (errno 
== EWOULDBLOCK
) 
 888       m_error 
= GSOCK_WOULDBLOCK
; 
 890       m_error 
= GSOCK_IOERR
; 
 892     /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect 
 893      * in MSW). Once the first OUTPUT event is received, users can assume 
 894      * that the socket is writable until a read operation fails. Only then 
 895      * will further OUTPUT events be posted. 
 897     m_detected 
&= ~GSOCK_OUTPUT_FLAG
; 
 905  *  Polls the socket to determine its status. This function will 
 906  *  check for the events specified in the 'flags' parameter, and 
 907  *  it will return a mask indicating which operations can be 
 908  *  performed. This function won't block, regardless of the 
 909  *  mode (blocking | nonblocking) of the socket. 
 911 GSocketEventFlags 
GSocket::Select(GSocketEventFlags flags
) 
 914   wxMacProcessNotifierEvents() ; 
 916   state = OTGetEndpointState(m_endpoint); 
 918   if ( ( flags & GSOCK_INPUT_FLAG ) && ! ( m_detected & GSOCK_INPUT_FLAG ) ) 
 921     OTCountDataBytes( m_endpoint , &sz ) ; 
 922     if ( state == T_INCON || sz > 0 ) 
 924       m_detected |= GSOCK_INPUT_FLAG ; 
 925       (m_cbacks[GSOCK_INPUT])(this, GSOCK_INPUT, m_data[GSOCK_INPUT]); 
 928   if ( ( flags & GSOCK_INPUT_FLAG ) && ! ( m_detected & GSOCK_OUTPUT_FLAG ) ) 
 930     if ( state == T_DATAXFER || state == T_INREL ) 
 932       m_detected |=GSOCK_OUTPUT_FLAG ; 
 933       (m_cbacks[GSOCK_OUTPUT])(this, GSOCK_OUTPUT, m_data[GSOCK_OUTPUT]); 
 937   return ( flags 
& m_detected 
) ; 
 942 /* GSocket_SetNonBlocking: 
 943  *  Sets the socket to non-blocking mode. All IO calls will return 
 946 void GSocket::SetNonBlocking(bool non_block
) 
 950   m_non_blocking 
= non_block
; 
 953 /* GSocket_SetTimeout: 
 954  *  Sets the timeout for blocking calls. Time is expressed in 
 957 void GSocket::SetTimeout(unsigned long millisec
) 
 961 //  this is usually set too high and we have not yet been able to detect a closed 
 962 //  stream, thus we leave the 10 sec timeout 
 963 //  m_timeout = millisec; 
 967  *  Returns the last error which occurred for this socket. Note that successful 
 968  *  operations do not clear this back to GSOCK_NOERROR, so use it only 
 971 GSocketError WXDLLIMPEXP_NET 
GSocket::GetError() 
 981  *   There is data to be read in the input buffer. If, after a read 
 982  *   operation, there is still data available, the callback function will 
 985  *   The socket is available for writing. That is, the next write call 
 986  *   won't block. This event is generated only once, when the connection is 
 987  *   first established, and then only if a call failed with GSOCK_WOULDBLOCK, 
 988  *   when the output buffer empties again. This means that the app should 
 989  *   assume that it can write since the first OUTPUT event, and no more 
 990  *   OUTPUT events will be generated unless an error occurs. 
 992  *   Connection successfully established, for client sockets, or incoming 
 993  *   client connection, for server sockets. Wait for this event (also watch 
 994  *   out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call. 
 996  *   The connection is lost (or a connection request failed); this could 
 997  *   be due to a failure, or due to the peer closing it gracefully. 
1000 /* GSocket_SetCallback: 
1001  *  Enables the callbacks specified by 'flags'. Note that 'flags' 
1002  *  may be a combination of flags OR'ed toghether, so the same 
1003  *  callback function can be made to accept different events. 
1004  *  The callback function must have the following prototype: 
1006  *  void function(GSocket *socket, GSocketEvent event, char *cdata) 
1008 void GSocket::SetCallback(GSocketEventFlags flags
, 
1009                          GSocketCallback callback
, char *cdata
) 
1015   for (count 
= 0; count 
< GSOCK_MAX_EVENT
; count
++) 
1017     if ((flags 
& (1 << count
)) != 0) 
1019       m_cbacks
[count
] = callback
; 
1020       m_data
[count
] = cdata
; 
1025 /* GSocket_UnsetCallback: 
1026  *  Disables all callbacks specified by 'flags', which may be a 
1027  *  combination of flags OR'ed toghether. 
1029 void GSocket::UnsetCallback(GSocketEventFlags flags
) 
1035   for (count 
= 0; count 
< GSOCK_MAX_EVENT
; count
++) 
1037     if ((flags 
& (1 << count
)) != 0) 
1039       m_cbacks
[count
] = NULL
; 
1040       m_data
[count
] = NULL
; 
1046 #define CALL_CALLBACK(socket, event) {                                  \ 
1047   _GSocket_Disable(socket, event);                                      \ 
1048   if (socket->m_cbacks[event])                                          \ 
1049     socket->m_cbacks[event](socket, event, socket->m_data[event]);      \ 
1052 int GSocket::Recv_Stream(char *buffer
, int size
) 
1056     OTByteCount sz 
= 0 ; 
1058     OTCountDataBytes( m_endpoint 
, &sz 
) ; 
1059     if ( size 
> (int)sz 
) 
1061     res 
= OTRcv( m_endpoint 
, buffer 
, size 
, &flags 
) ; 
1067     // we simulate another read event if there are still bytes 
1068     if ( m_takesEvents 
) 
1070         OTByteCount sz 
= 0 ; 
1071         OTCountDataBytes( m_endpoint 
, &sz 
) ; 
1074             m_detected 
|= GSOCK_INPUT_FLAG 
; 
1075             (m_cbacks
[GSOCK_INPUT
])(this, GSOCK_INPUT
, m_data
[GSOCK_INPUT
]); 
1081 int GSocket::Recv_Dgram(char *buffer
, int size
) 
1086   struct sockaddr from
; 
1087   WX_SOCKLEN_T fromlen 
= sizeof(from
); 
1090   fromlen 
= sizeof(from
); 
1092   ret 
= recvfrom(m_endpoint
, buffer
, size
, 0, &from
, (WX_SOCKLEN_T 
*) &fromlen
); 
1097   /* Translate a system address into a GSocket address */ 
1100     m_peer 
= GAddress_new(); 
1103       m_error 
= GSOCK_MEMERR
; 
1107   err 
= _GAddress_translate_from(m_peer
, &from
, fromlen
); 
1108   if (err 
!= GSOCK_NOERROR
) 
1110     GAddress_destroy(m_peer
); 
1119 int GSocket::Send_Stream(const char *buffer
, int size
) 
1124     res 
= OTSnd( m_endpoint 
, (void*) buffer 
, size 
, flags 
) ; 
1128 int GSocket::Send_Dgram(const char *buffer
, int size
) 
1133   struct sockaddr 
*addr
; 
1139     m_error 
= GSOCK_INVADDR
; 
1143   err 
= _GAddress_translate_to(m_peer
, &addr
, &len
); 
1144   if (err 
!= GSOCK_NOERROR
) 
1150   ret 
= sendto(m_endpoint
, buffer
, size
, 0, addr
, len
); 
1152   /* Frees memory allocated from _GAddress_translate_to */ 
1158 /* Compatibility functions for GSocket */ 
1159 GSocket 
*GSocket_new(void) 
1161     GSocket 
*newsocket 
= new GSocket(); 
1162     if(newsocket
->IsOk()) 
1170  * ------------------------------------------------------------------------- 
1172  * ------------------------------------------------------------------------- 
1175 /* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY 
1176  * or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it initalizes address 
1177  * to be a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR. 
1179 #define CHECK_ADDRESS(address, family, retval)                      \ 
1181   if (address->m_family == GSOCK_NOFAMILY)                          \ 
1182     if (_GAddress_Init_##family(address) != GSOCK_NOERROR)          \ 
1183       return address->m_error;                                      \ 
1184   if (address->m_family != GSOCK_##family)                          \ 
1186     address->m_error = GSOCK_INVADDR;                               \ 
1191 GAddress 
*GAddress_new() 
1195   if ((address 
= (GAddress 
*) malloc(sizeof(GAddress
))) == NULL
) 
1198   address
->m_family  
= GSOCK_NOFAMILY
; 
1199   address
->m_host 
= INADDR_NONE 
; 
1200   address
->m_port 
= 0 ; 
1205 GAddress 
*GAddress_copy(GAddress 
*address
) 
1209   assert(address 
!= NULL
); 
1211   if ((addr2 
= (GAddress 
*) malloc(sizeof(GAddress
))) == NULL
) 
1214   memcpy(addr2
, address
, sizeof(GAddress
)); 
1218 void GAddress_destroy(GAddress 
*address
) 
1220   assert(address 
!= NULL
); 
1225 void GAddress_SetFamily(GAddress 
*address
, GAddressType type
) 
1227   assert(address 
!= NULL
); 
1229   address
->m_family 
= type
; 
1232 GAddressType 
GAddress_GetFamily(GAddress 
*address
) 
1234   assert(address 
!= NULL
); 
1236   return address
->m_family
; 
1239 GSocketError 
_GAddress_translate_from(GAddress 
*address
, 
1242   switch (addr
->fAddressType
) 
1245       address
->m_family 
= GSOCK_INET
; 
1249       address
->m_family 
= GSOCK_INET6
; 
1254       address
->m_error 
= GSOCK_INVOP
; 
1258   address
->m_host 
= addr
->fHost 
; 
1259   address
->m_port 
= addr
->fPort 
; 
1260   return GSOCK_NOERROR
; 
1263 GSocketError 
_GAddress_translate_to(GAddress 
*address
, 
1266   if ( !GSocket_Verify_Inited() ) 
1267     return GSOCK_IOERR 
; 
1268   memset(addr
, 0 , sizeof(struct InetAddress
)); 
1269   OTInitInetAddress( addr 
, address
->m_port 
, address
->m_host 
) ; 
1270   return GSOCK_NOERROR
; 
1274  * ------------------------------------------------------------------------- 
1275  * Internet address family 
1276  * ------------------------------------------------------------------------- 
1279 GSocketError 
_GAddress_Init_INET(GAddress 
*address
) 
1281   address
->m_family 
= GSOCK_INET
; 
1282   address
->m_host 
= kOTAnyInetAddress 
; 
1284   return GSOCK_NOERROR
; 
1287 GSocketError 
GAddress_INET_SetHostName(GAddress 
*address
, const char *hostname
) 
1289   InetHostInfo hinfo 
; 
1292  if ( !GSocket_Verify_Inited() ) 
1293     return GSOCK_IOERR 
; 
1295   assert(address 
!= NULL
); 
1297   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1298   ret 
= OTInetStringToAddress( gInetSvcRef 
, (char*) hostname 
, &hinfo 
) ; 
1299   if ( ret 
!= kOTNoError 
) 
1301     address
->m_host 
= INADDR_NONE 
; 
1302     address
->m_error 
= GSOCK_NOHOST
; 
1303     return GSOCK_NOHOST
; 
1305   address
->m_host 
= hinfo
.addrs
[0] ; 
1306   return GSOCK_NOERROR
; 
1309 GSocketError 
GAddress_INET_SetBroadcastAddress(GAddress 
*address
) 
1311   return GAddress_INET_SetHostAddress(address
, INADDR_BROADCAST
); 
1314 GSocketError 
GAddress_INET_SetAnyAddress(GAddress 
*address
) 
1316   return GAddress_INET_SetHostAddress(address
, INADDR_ANY
); 
1319 GSocketError 
GAddress_INET_SetHostAddress(GAddress 
*address
, 
1320                                           unsigned long hostaddr
) 
1322   assert(address 
!= NULL
); 
1324   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1326   address
->m_host 
= htonl(hostaddr
) ; 
1328   return GSOCK_NOERROR
; 
1331 struct service_entry
 
1334     unsigned short port 
; 
1335     const char * protocol 
; 
1337 typedef struct service_entry service_entry 
; 
1339 service_entry gServices
[] = 
1341     { "http" , 80 , "tcp" } 
1344 GSocketError 
GAddress_INET_SetPortName(GAddress 
*address
, const char *port
, 
1345                                        const char *protocol
) 
1349   assert(address 
!= NULL
); 
1350   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1354     address
->m_error 
= GSOCK_INVPORT
; 
1355     return GSOCK_INVPORT
; 
1357   for ( i 
= 0 ; i 
< sizeof( gServices
) / sizeof( service_entry 
) ; ++i 
) 
1359     if ( strcmp( port 
, gServices
[i
].name 
) == 0 ) 
1361       if ( protocol 
== NULL 
|| strcmp( protocol 
, gServices
[i
].protocol 
) ) 
1363         address
->m_port 
= gServices
[i
].port 
; 
1364         return GSOCK_NOERROR
; 
1369   if (isdigit(port
[0])) 
1371      address
->m_port 
= atoi(port
); 
1372      return GSOCK_NOERROR
; 
1375   address
->m_error 
= GSOCK_INVPORT
; 
1376   return GSOCK_INVPORT
; 
1379 GSocketError 
GAddress_INET_SetPort(GAddress 
*address
, unsigned short port
) 
1381   assert(address 
!= NULL
); 
1382   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1383   address
->m_port 
= port 
; 
1385   return GSOCK_NOERROR
; 
1388 GSocketError 
GAddress_INET_GetHostName(GAddress 
*address
, char *hostname
, size_t sbuf
) 
1390   InetDomainName name 
; 
1391   if ( !GSocket_Verify_Inited() ) 
1392     return GSOCK_IOERR 
; 
1394   assert(address 
!= NULL
); 
1395   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1397   OTInetAddressToName( gInetSvcRef 
, address
->m_host 
, name 
) ; 
1398   strncpy( hostname 
, name 
, sbuf 
) ; 
1399   return GSOCK_NOERROR
; 
1402 unsigned long GAddress_INET_GetHostAddress(GAddress 
*address
) 
1404   assert(address 
!= NULL
); 
1405   CHECK_ADDRESS(address
, INET
, 0); 
1407   return ntohl(address
->m_host
); 
1410 unsigned short GAddress_INET_GetPort(GAddress 
*address
) 
1412   assert(address 
!= NULL
); 
1413   CHECK_ADDRESS(address
, INET
, 0); 
1415   return address
->m_port
; 
1418 void GSocket::Enable_Events() 
1420     if ( m_takesEvents 
) 
1425         m_takesEvents 
= true ; 
1426         state 
= OTGetEndpointState(m_endpoint
); 
1429             OTByteCount sz 
= 0 ; 
1430             OTCountDataBytes( m_endpoint 
, &sz 
) ; 
1431             if ( state 
== T_INCON 
|| sz 
> 0 ) 
1433                 m_detected 
|= GSOCK_INPUT_FLAG 
; 
1434                 (m_cbacks
[GSOCK_INPUT
])(this, GSOCK_INPUT
, m_data
[GSOCK_INPUT
]); 
1438             if ( state 
== T_DATAXFER 
|| state 
== T_INREL 
) 
1440                 m_detected 
|=GSOCK_OUTPUT_FLAG 
; 
1441                 (m_cbacks
[GSOCK_OUTPUT
])(this, GSOCK_OUTPUT
, m_data
[GSOCK_OUTPUT
]); 
1447 void GSocket::Disable_Events() 
1449     m_takesEvents 
= false ; 
1452 /* _GSocket_Input_Timeout: 
1453  *  For blocking sockets, wait until data is available or 
1454  *  until timeout ellapses. 
1456 GSocketError 
GSocket::Input_Timeout() 
1458   if ( !m_non_blocking 
) 
1460     UnsignedWide now 
, start 
; 
1461     bool formerTakesEvents 
= m_takesEvents 
; 
1462     Microseconds(&start
); 
1464     m_takesEvents 
= false ; 
1466     while( (now
.hi 
* 4294967296.0 + now
.lo
) - (start
.hi 
* 4294967296.0 + start
.lo
) < m_timeout 
* 1000.0 ) 
1469         OTByteCount sz 
= 0 ; 
1470         state 
= OTGetEndpointState(m_endpoint
); 
1472         OTCountDataBytes( m_endpoint 
, &sz 
) ; 
1473         if ( state 
== T_INCON 
|| sz 
> 0 ) 
1475             m_takesEvents 
= formerTakesEvents 
; 
1476             return GSOCK_NOERROR
; 
1480     m_takesEvents 
= formerTakesEvents 
; 
1481     m_error 
= GSOCK_TIMEDOUT
; 
1482     return GSOCK_TIMEDOUT
; 
1484   return GSOCK_NOERROR
; 
1487 /* _GSocket_Output_Timeout: 
1488  *  For blocking sockets, wait until data can be sent without 
1489  *  blocking or until timeout ellapses. 
1491 GSocketError 
GSocket::Output_Timeout() 
1493   if ( !m_non_blocking 
) 
1495     UnsignedWide now 
, start 
; 
1496     bool formerTakesEvents 
= m_takesEvents 
; 
1497     Microseconds(&start
); 
1499     m_takesEvents 
= false ; 
1501     while( (now
.hi 
* 4294967296.0 + now
.lo
) - (start
.hi 
* 4294967296.0 + start
.lo
) < m_timeout 
* 1000.0 ) 
1504         state 
= OTGetEndpointState(m_endpoint
); 
1506         if ( state 
== T_DATAXFER 
|| state 
== T_INREL 
) 
1508             m_takesEvents 
= formerTakesEvents 
; 
1509             return GSOCK_NOERROR
; 
1513     m_takesEvents 
= formerTakesEvents 
; 
1514     m_error 
= GSOCK_TIMEDOUT
; 
1515     return GSOCK_TIMEDOUT
; 
1517   return GSOCK_NOERROR
; 
1521  *   There is data to be read in the input buffer. If, after a read 
1522  *   operation, there is still data available, the callback function will 
1525  *   The socket is available for writing. That is, the next write call 
1526  *   won't block. This event is generated only once, when the connection is 
1527  *   first established, and then only if a call failed with GSOCK_WOULDBLOCK, 
1528  *   when the output buffer empties again. This means that the app should 
1529  *   assume that it can write since the first OUTPUT event, and no more 
1530  *   OUTPUT events will be generated unless an error occurs. 
1532  *   Connection successfully established, for client sockets, or incoming 
1533  *   client connection, for server sockets. Wait for this event (also watch 
1534  *   out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call. 
1536  *   The connection is lost (or a connection request failed); this could 
1537  *   be due to a failure, or due to the peer closing it gracefully. 
1540 void _GSocket_Internal_Proc(unsigned long e 
, void* d 
) 
1542     GSocket 
*socket 
= (GSocket
*) d 
; 
1547     OTEventCode ev 
= (OTEventCode
) e 
; 
1549     GSocketEvent event2
; 
1550     GSocketCallback cback
; 
1552     GSocketCallback cback2
; 
1555     event 
= GSOCK_MAX_EVENT 
; 
1556     event2 
= GSOCK_MAX_EVENT 
; 
1562     /* Check that the socket still exists (it has not been 
1563      * destroyed) and for safety, check that the m_endpoint field 
1564      * is what we expect it to be. 
1566     if ( /* (socket != NULL) && */ (socket
->m_takesEvents
)) 
1571                 event 
= GSOCK_CONNECTION 
; 
1574                 event 
= GSOCK_CONNECTION 
; 
1575                 event2 
= GSOCK_OUTPUT 
; 
1579                     retCall
.addr
.buf     
= NULL
; 
1580                     retCall
.addr
.maxlen  
= 0; 
1581                     retCall
.opt
.buf      
= NULL
; 
1582                     retCall
.opt
.maxlen   
= 0; 
1583                     retCall
.udata
.buf    
= NULL
; 
1584                     retCall
.udata
.maxlen 
= 0; 
1585                     OTRcvConnect( socket
->m_endpoint 
, &retCall 
) ; 
1589                 event 
= GSOCK_LOST 
; 
1593                 event 
= GSOCK_OUTPUT 
; 
1596                 event 
= GSOCK_INPUT 
; 
1599                 event 
= GSOCK_INPUT 
; 
1602       if (event 
!= GSOCK_MAX_EVENT
) 
1604         cback 
= socket
->m_cbacks
[event
]; 
1605         data 
= socket
->m_data
[event
]; 
1607         if (event 
== GSOCK_LOST
) 
1608           socket
->m_detected 
= GSOCK_LOST_FLAG
; 
1610           socket
->m_detected 
|= (1 << event
); 
1612       if (event2 
!= GSOCK_MAX_EVENT
) 
1614         cback2 
= socket
->m_cbacks
[event2
]; 
1615         data2 
= socket
->m_data
[event2
]; 
1617         if (event2 
== GSOCK_LOST
) 
1618           socket
->m_detected 
= GSOCK_LOST_FLAG
; 
1620           socket
->m_detected 
|= (1 << event2
); 
1624     /* OK, we can now leave the critical section because we have 
1625      * already obtained the callback address (we make no further 
1626      * accesses to socket->whatever). However, the app should 
1627      * be prepared to handle events from a socket that has just 
1632       (cback
)(socket
, event
, data
); 
1634       (cback2
)(socket
, event2
, data2
); 
1638 /* Hack added for Mac OS X */ 
1639 GSocketError 
GAddress_UNIX_GetPath(GAddress 
*addr
, char *path
, size_t buf
) 
1641     return GSOCK_INVADDR
; 
1644 GSocketError 
GAddress_UNIX_SetPath(GAddress 
*addr
, const char *path
) 
1646     return GSOCK_INVADDR
; 
1649 #endif  /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */