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); 
 197 /* Global initialisers */ 
 199 void GSocket_SetGUIFunctions(GSocketGUIFunctionsTable 
*table
) 
 201     // do nothing, wxMac doesn't have wxBase-GUI separation yet 
 209 bool GSocket_Verify_Inited() ; 
 210 bool GSocket_Verify_Inited() 
 214     // Marc Newsam: added the clientcontext variable 
 215     //              however, documentation is unclear how this works 
 216     OTClientContextPtr clientcontext
; 
 221     InitOpenTransportInContext(kInitOTForApplicationMask
, &clientcontext
); 
 223     gInetSvcRef 
= OTOpenInternetServicesInContext(kDefaultInternetServicesPath
, 
 224                                                   NULL
, &err
, clientcontext
); 
 229     InitOpenTransport() ; 
 231     gInetSvcRef 
= OTOpenInternetServices(kDefaultInternetServicesPath
, NULL
, &err
); 
 233     if ( gInetSvcRef 
== NULL 
||  err 
!= kOTNoError 
) 
 235         OTAssert("Could not open Inet Services", err 
== noErr
); 
 238     gOTNotifierUPP 
= NewOTNotifyUPP( OTInetEventHandler 
) ; 
 242 void GSocket_Cleanup() 
 244     if ( gOTInited 
!= 0 ) 
 246         if ( gInetSvcRef 
!= NULL 
) 
 247             OTCloseProvider( gInetSvcRef 
); 
 249       CloseOpenTransportInContext( NULL 
) ; 
 251       CloseOpenTransport() ; 
 253         if ( gOTNotifierUPP 
) 
 254             DisposeOTNotifyUPP( gOTNotifierUPP 
) ; 
 258 /* Constructors / Destructors for GSocket */ 
 264   m_ok 
= GSocket_Verify_Inited(); 
 267   for (i
=0;i
<GSOCK_MAX_EVENT
;i
++) 
 274   m_error               
= GSOCK_NOERROR
; 
 277   m_non_blocking        
= false; 
 279                                 /* 10 sec * 1000 millisec */ 
 280   m_takesEvents         
= true ; 
 281   m_mac_events          
= wxMacGetNotifierTable() ; 
 288     /* Check that the socket is really shutdowned */ 
 289     if (m_endpoint 
!= kOTInvalidEndpointRef
) 
 293     /* Destroy private addresses */ 
 295         GAddress_destroy(m_local
); 
 298         GAddress_destroy(m_peer
); 
 302  *  Disallow further read/write operations on this socket, close 
 303  *  the fd and disable all callbacks. 
 305 void GSocket::Shutdown() 
 312     /* If socket has been created, shutdown it */ 
 313     if (m_endpoint 
!= kOTInvalidEndpointRef 
) 
 315         err 
= OTSndOrderlyDisconnect( m_endpoint 
) ; 
 316         if ( err 
!= kOTNoError 
) 
 320         err 
= OTRcvOrderlyDisconnect( m_endpoint 
) ; 
 321         err 
= OTUnbind( m_endpoint 
) ; 
 322         err 
= OTCloseProvider( m_endpoint 
) ; 
 323         m_endpoint 
= kOTInvalidEndpointRef 
; 
 326     /* Disable GUI callbacks */ 
 327     for (evt 
= 0; evt 
< GSOCK_MAX_EVENT
; evt
++) 
 328         m_cbacks
[evt
] = NULL
; 
 332     wxMacRemoveAllNotifiersForData( wxMacGetNotifierTable() , this ) ; 
 336 /* Address handling */ 
 342  *  Set or get the local or peer address for this socket. The 'set' 
 343  *  functions return GSOCK_NOERROR on success, an error code otherwise. 
 344  *  The 'get' functions return a pointer to a GAddress object on success, 
 345  *  or NULL otherwise, in which case they set the error code of the 
 346  *  corresponding GSocket. 
 349  *    GSOCK_INVSOCK - the socket is not valid. 
 350  *    GSOCK_INVADDR - the address is not valid. 
 352 GSocketError 
GSocket::SetLocal(GAddress 
*address
) 
 356     /* the socket must be initialized, or it must be a server */ 
 357     if ((m_endpoint 
!= kOTInvalidEndpointRef 
&& !m_server
)) 
 359         m_error 
= GSOCK_INVSOCK
; 
 360         return GSOCK_INVSOCK
; 
 364     if (address 
== NULL 
|| address
->m_family 
== GSOCK_NOFAMILY
) 
 366         m_error 
= GSOCK_INVADDR
; 
 367         return GSOCK_INVADDR
; 
 371         GAddress_destroy(m_local
); 
 373     m_local 
= GAddress_copy(address
); 
 375     return GSOCK_NOERROR
; 
 378 GSocketError 
GSocket::SetPeer(GAddress 
*address
) 
 383     if (address 
== NULL 
|| address
->m_family 
== GSOCK_NOFAMILY
) 
 385         m_error 
= GSOCK_INVADDR
; 
 386         return GSOCK_INVADDR
; 
 390         GAddress_destroy(m_peer
); 
 392     m_peer 
= GAddress_copy(address
); 
 394     return GSOCK_NOERROR
; 
 397 GAddress 
*GSocket::GetLocal() 
 399     GAddress 
*address 
= NULL 
; 
 405     /* try to get it from the m_local var first */ 
 407         return GAddress_copy(m_local
); 
 409     /* else, if the socket is initialized, try getsockname */ 
 410     if (m_endpoint 
== kOTInvalidEndpointRef
) 
 412         m_error 
= GSOCK_INVSOCK
; 
 417 /* we do not support multihoming with this code at the moment 
 418    OTGetProtAddress will have to be used then - but we don't have a handy 
 419    method to use right now 
 422         InetInterfaceInfo info
; 
 423         OTInetGetInterfaceInfo(&info
, kDefaultInetInterface
); 
 424         loc
.fHost 
= info
.fAddress 
; 
 426         loc
.fAddressType 
= AF_INET 
; 
 429     /* got a valid address from getsockname, create a GAddress object */ 
 430     address 
= GAddress_new(); 
 433         m_error 
= GSOCK_MEMERR
; 
 437     err 
= _GAddress_translate_from(address
, &loc
); 
 438     if (err 
!= GSOCK_NOERROR
) 
 440         GAddress_destroy(address
); 
 448 GAddress 
*GSocket::GetPeer() 
 452     /* try to get it from the m_peer var */ 
 454         return GAddress_copy(m_peer
); 
 459 /* Server specific parts */ 
 461 /* GSocket_SetServer: 
 462  *  Sets up this socket as a server. The local address must have been 
 463  *  set with GSocket_SetLocal() before GSocket_SetServer() is called. 
 464  *  Returns GSOCK_NOERROR on success, one of the following otherwise: 
 467  *    GSOCK_INVSOCK - the socket is in use. 
 468  *    GSOCK_INVADDR - the local address has not been set. 
 469  *    GSOCK_IOERR   - low-level error. 
 471 GSocketError 
GSocket::SetServer() 
 475   /* must not be in use */ 
 476   if (m_endpoint 
!= kOTInvalidEndpointRef 
) 
 478     m_error 
= GSOCK_INVSOCK
; 
 479     return GSOCK_INVSOCK
; 
 482   /* the local addr must have been set */ 
 485     m_error 
= GSOCK_INVADDR
; 
 486     return GSOCK_INVADDR
; 
 489   /* Initialize all fields */ 
 496   /* Create the socket */ 
 497   m_endpoint 
= socket(m_local
->m_realfamily
, SOCK_STREAM
, 0); 
 498   socket_set_ref( m_endpoint 
, (unsigned long) &gMacNetEvents 
,  (unsigned long) this ) ; 
 499   if (m_endpoint 
== kOTInvalidEndpointRef
) 
 501     m_error 
= GSOCK_IOERR
; 
 505   ioctl(m_endpoint
, FIONBIO
, &arg
); 
 508   /* Bind to the local address, 
 509    * retrieve the actual address bound, 
 510    * and listen up to 5 connections. 
 512   if ((bind(m_endpoint
, m_local
->m_addr
, m_local
->m_len
) != 0) || 
 513       (getsockname(m_endpoint
, 
 515                    (WX_SOCKLEN_T 
*) &m_local
->m_len
) != 0) || 
 516       (listen(m_endpoint
, 5) != 0)) 
 520     m_error 
= GSOCK_IOERR
; 
 524   return GSOCK_NOERROR
; 
 527 /* GSocket_WaitConnection: 
 528  *  Waits for an incoming client connection. Returns a pointer to 
 529  *  a GSocket object, or NULL if there was an error, in which case 
 530  *  the last error field will be updated for the calling GSocket. 
 532  *  Error codes (set in the calling GSocket) 
 533  *    GSOCK_INVSOCK    - the socket is not valid or not a server. 
 534  *    GSOCK_TIMEDOUT   - timeout, no incoming connections. 
 535  *    GSOCK_WOULDBLOCK - the call would block and the socket is nonblocking. 
 536  *    GSOCK_MEMERR     - couldn't allocate memory. 
 537  *    GSOCK_IOERR      - low-level error. 
 539 GSocket 
*GSocket::WaitConnection() 
 541   GSocket 
*connection 
= NULL 
; 
 545   /* Reenable CONNECTION events */ 
 546   m_detected 
&= ~GSOCK_CONNECTION_FLAG
; 
 548   /* If the socket has already been created, we exit immediately */ 
 549   if (m_endpoint 
== kOTInvalidEndpointRef 
|| !m_server
) 
 551     m_error 
= GSOCK_INVSOCK
; 
 555   /* Create a GSocket object for the new connection */ 
 556   connection 
= GSocket_new(); 
 560     m_error 
= GSOCK_MEMERR
; 
 564   /* Wait for a connection (with timeout) */ 
 565   if (Input_Timeout() == GSOCK_TIMEDOUT
) 
 568     /* m_error set by _GSocket_Input_Timeout */ 
 574   connection
->m_endpoint 
= accept(m_endpoint
, &from
, (WX_SOCKLEN_T 
*) &fromlen
); 
 577   if (connection
->m_endpoint 
== kOTInvalidEndpointRef 
) 
 579     if (errno 
== EWOULDBLOCK
) 
 580       m_error 
= GSOCK_WOULDBLOCK
; 
 582       m_error 
= GSOCK_IOERR
; 
 588   /* Initialize all fields */ 
 589   connection
->m_server   
= false; 
 590   connection
->m_stream   
= true; 
 591   connection
->m_oriented 
= true; 
 593   /* Setup the peer address field */ 
 594   connection
->m_peer 
= GAddress_new(); 
 595   if (!connection
->m_peer
) 
 598     m_error 
= GSOCK_MEMERR
; 
 603   err 
= _GAddress_translate_from(connection
->m_peer
, &from
, fromlen
); 
 604   if (err 
!= GSOCK_NOERROR
) 
 606     GAddress_destroy(connection
->m_peer
); 
 607     GSocket_destroy(connection
); 
 612   ioctl(connection
->m_endpoint
, FIONBIO
, &arg
); 
 614   connection
->Enable_Events(); 
 619 /* Datagram sockets */ 
 621 /* GSocket_SetNonOriented: 
 622  *  Sets up this socket as a non-connection oriented (datagram) socket. 
 623  *  Before using this function, the local address must have been set 
 624  *  with GSocket_SetLocal(), or the call will fail. Returns GSOCK_NOERROR 
 625  *  on success, or one of the following otherwise. 
 628  *    GSOCK_INVSOCK - the socket is in use. 
 629  *    GSOCK_INVADDR - the local address has not been set. 
 630  *    GSOCK_IOERR   - low-level error. 
 632 GSocketError 
GSocket::SetNonOriented() 
 636   if (m_endpoint 
!= kOTInvalidEndpointRef 
) 
 638     m_error 
= GSOCK_INVSOCK
; 
 639     return GSOCK_INVSOCK
; 
 644     m_error 
= GSOCK_INVADDR
; 
 645     return GSOCK_INVADDR
; 
 648   /* Initialize all fields */ 
 653   /* Create the socket */ 
 657   m_endpoint 
= socket(m_local
->m_realfamily
, SOCK_DGRAM
, 0); 
 658   socket_set_ref( m_endpoint 
, (unsigned long) &gMacNetEvents 
,  (unsigned long) this ) ; 
 660   if (m_endpoint 
== kOTInvalidEndpointRef 
) 
 662     m_error 
= GSOCK_IOERR
; 
 668   ioctl(m_endpoint
, FIONBIO
, &arg
); 
 672   /* Bind to the local address, 
 673    * and retrieve the actual address bound. 
 677   if ((bind(m_endpoint
, m_local
->m_addr
, m_local
->m_len
) != 0) || 
 678       (getsockname(m_endpoint
, 
 680                    (WX_SOCKLEN_T 
*) &m_local
->m_len
) != 0)) 
 684     m_error 
= GSOCK_IOERR
; 
 688   return GSOCK_NOERROR
; 
 691 /* Client specific parts */ 
 694  *  For stream (connection oriented) sockets, GSocket_Connect() tries 
 695  *  to establish a client connection to a server using the peer address 
 696  *  as established with GSocket_SetPeer(). Returns GSOCK_NOERROR if the 
 697  *  connection has been successfully established, or one of the error 
 698  *  codes listed below. Note that for nonblocking sockets, a return 
 699  *  value of GSOCK_WOULDBLOCK doesn't mean a failure. The connection 
 700  *  request can be completed later; you should use GSocket_Select() 
 701  *  to poll for GSOCK_CONNECTION | GSOCK_LOST, or wait for the 
 702  *  corresponding asynchronous events. 
 704  *  For datagram (non connection oriented) sockets, GSocket_Connect() 
 705  *  just sets the peer address established with GSocket_SetPeer() as 
 706  *  default destination. 
 709  *    GSOCK_INVSOCK    - the socket is in use or not valid. 
 710  *    GSOCK_INVADDR    - the peer address has not been established. 
 711  *    GSOCK_TIMEDOUT   - timeout, the connection failed. 
 712  *    GSOCK_WOULDBLOCK - connection in progress (nonblocking sockets only) 
 713  *    GSOCK_MEMERR     - couldn't allocate memory. 
 714  *    GSOCK_IOERR      - low-level error. 
 716 GSocketError 
GSocket::Connect(GSocketStream stream
) 
 720    OSStatus       err 
= kOTNoError
; 
 725   /* Enable CONNECTION events (needed for nonblocking connections) */ 
 726   m_detected 
&= ~GSOCK_CONNECTION_FLAG
; 
 728   if (m_endpoint 
!= kOTInvalidEndpointRef 
) 
 730     m_error 
= GSOCK_INVSOCK
; 
 731     return GSOCK_INVSOCK
; 
 736     m_error 
= GSOCK_INVADDR
; 
 737     return GSOCK_INVADDR
; 
 740   /* Streamed or dgram socket? */ 
 741   m_stream   
= (stream 
== GSOCK_STREAMED
); 
 745   /* Create the socket */ 
 748       OTOpenEndpointInContext( OTCreateConfiguration( kTCPName
) , 0 , &info 
, &err 
, NULL 
) ; 
 751       OTOpenEndpoint( OTCreateConfiguration( kTCPName
) , 0 , &info 
, &err 
) ; 
 753   if ( m_endpoint 
== kOTInvalidEndpointRef 
|| err 
!= kOTNoError 
) 
 755     m_endpoint 
= kOTInvalidEndpointRef 
; 
 756     m_error 
= GSOCK_IOERR
; 
 759   err 
= OTBind( m_endpoint 
, nil 
, nil 
) ; 
 760   if ( err 
!= kOTNoError 
) 
 764   SetDefaultEndpointModes( m_endpoint 
, this ) ; 
 767   ioctl(m_endpoint
, FIONBIO
, &arg
); 
 771   _GAddress_translate_to( m_peer 
, &addr 
) ; 
 772   memset( &peer 
, 0 , sizeof( TCall 
) ) ; 
 773   peer
.addr
.len 
= sizeof( InetAddress 
) ; 
 774   peer
.addr
.buf 
= (unsigned char*) &addr 
; 
 775   err 
= OTConnect( m_endpoint 
, &peer 
, nil 
) ; 
 778     /* If connect failed with EINPROGRESS and the GSocket object 
 779      * is in blocking mode, we select() for the specified timeout 
 780      * checking for writability to see if the connection request 
 784     if ((err 
== kOTNoDataErr 
) && (!m_non_blocking
)) 
 786       if (Output_Timeout() == GSOCK_TIMEDOUT
) 
 788         OTSndOrderlyDisconnect( m_endpoint 
) ; 
 789         m_endpoint 
= kOTInvalidEndpointRef 
; 
 790         /* m_error is set in _GSocket_Output_Timeout */ 
 791         return GSOCK_TIMEDOUT
; 
 797         WX_SOCKLEN_T len = sizeof(error); 
 799         getsockopt(m_endpoint, SOL_SOCKET, SO_ERROR, (void*) &error, &len); 
 803           return GSOCK_NOERROR
; 
 807     /* If connect failed with EINPROGRESS and the GSocket object 
 808      * is set to nonblocking, we set m_error to GSOCK_WOULDBLOCK 
 809      * (and return GSOCK_WOULDBLOCK) but we don't close the socket; 
 810      * this way if the connection completes, a GSOCK_CONNECTION 
 811      * event will be generated, if enabled. 
 813     if ((err 
== kOTNoDataErr
) && (m_non_blocking
)) 
 815       m_error 
= GSOCK_WOULDBLOCK
; 
 816       return GSOCK_WOULDBLOCK
; 
 819     /* If connect failed with an error other than EINPROGRESS, 
 820      * then the call to GSocket_Connect has failed. 
 822     OTSndOrderlyDisconnect( m_endpoint 
) ; 
 824     m_endpoint 
= kOTInvalidEndpointRef 
; 
 825     m_error 
= GSOCK_IOERR
; 
 828 //  OTInetEventHandler(this, T_CONNECT , kOTNoError , NULL ) ; 
 829   return GSOCK_NOERROR
; 
 834 /* Like recv(), send(), ... */ 
 835 int GSocket::Read(char *buffer
, int size
) 
 841   /* Reenable INPUT events */ 
 842   m_detected 
&= ~GSOCK_INPUT_FLAG
; 
 844   if (m_endpoint 
== kOTInvalidEndpointRef 
|| m_server
) 
 846     m_error 
= GSOCK_INVSOCK
; 
 850   /* If the socket is blocking, wait for data (with a timeout) */ 
 851   if (Input_Timeout() == GSOCK_TIMEDOUT
) 
 856     ret 
= Recv_Stream(buffer
, size
); 
 858     ret 
= Recv_Dgram(buffer
, size
); 
 862     if (errno 
== EWOULDBLOCK
) 
 863       m_error 
= GSOCK_WOULDBLOCK
; 
 865       m_error 
= GSOCK_IOERR
; 
 871 int GSocket::Write(const char *buffer
, int size
) 
 877   if (m_endpoint 
== kOTInvalidEndpointRef 
|| m_server
) 
 879     m_error 
= GSOCK_INVSOCK
; 
 883   /* If the socket is blocking, wait for writability (with a timeout) */ 
 884   if (Output_Timeout() == GSOCK_TIMEDOUT
) 
 889     ret 
= Send_Stream(buffer
, size
); 
 891     ret 
= Send_Dgram(buffer
, size
); 
 895     if (errno 
== EWOULDBLOCK
) 
 896       m_error 
= GSOCK_WOULDBLOCK
; 
 898       m_error 
= GSOCK_IOERR
; 
 900     /* Only reenable OUTPUT events after an error (just like WSAAsyncSelect 
 901      * in MSW). Once the first OUTPUT event is received, users can assume 
 902      * that the socket is writable until a read operation fails. Only then 
 903      * will further OUTPUT events be posted. 
 905     m_detected 
&= ~GSOCK_OUTPUT_FLAG
; 
 913  *  Polls the socket to determine its status. This function will 
 914  *  check for the events specified in the 'flags' parameter, and 
 915  *  it will return a mask indicating which operations can be 
 916  *  performed. This function won't block, regardless of the 
 917  *  mode (blocking | nonblocking) of the socket. 
 919 GSocketEventFlags 
GSocket::Select(GSocketEventFlags flags
) 
 922   wxMacProcessNotifierEvents() ; 
 924   state = OTGetEndpointState(m_endpoint); 
 926   if ( ( flags & GSOCK_INPUT_FLAG ) && ! ( m_detected & GSOCK_INPUT_FLAG ) ) 
 929     OTCountDataBytes( m_endpoint , &sz ) ; 
 930     if ( state == T_INCON || sz > 0 ) 
 932       m_detected |= GSOCK_INPUT_FLAG ; 
 933       (m_cbacks[GSOCK_INPUT])(this, GSOCK_INPUT, m_data[GSOCK_INPUT]); 
 936   if ( ( flags & GSOCK_INPUT_FLAG ) && ! ( m_detected & GSOCK_OUTPUT_FLAG ) ) 
 938     if ( state == T_DATAXFER || state == T_INREL ) 
 940       m_detected |=GSOCK_OUTPUT_FLAG ; 
 941       (m_cbacks[GSOCK_OUTPUT])(this, GSOCK_OUTPUT, m_data[GSOCK_OUTPUT]); 
 945   return ( flags 
& m_detected 
) ; 
 950 /* GSocket_SetNonBlocking: 
 951  *  Sets the socket to non-blocking mode. All IO calls will return 
 954 void GSocket::SetNonBlocking(bool non_block
) 
 958   m_non_blocking 
= non_block
; 
 961 /* GSocket_SetTimeout: 
 962  *  Sets the timeout for blocking calls. Time is expressed in 
 965 void GSocket::SetTimeout(unsigned long millisec
) 
 969 //  this is usually set too high and we have not yet been able to detect a closed 
 970 //  stream, thus we leave the 10 sec timeout 
 971 //  m_timeout = millisec; 
 975  *  Returns the last error which occurred for this socket. Note that successful 
 976  *  operations do not clear this back to GSOCK_NOERROR, so use it only 
 979 GSocketError WXDLLIMPEXP_NET 
GSocket::GetError() 
 989  *   There is data to be read in the input buffer. If, after a read 
 990  *   operation, there is still data available, the callback function will 
 993  *   The socket is available for writing. That is, the next write call 
 994  *   won't block. This event is generated only once, when the connection is 
 995  *   first established, and then only if a call failed with GSOCK_WOULDBLOCK, 
 996  *   when the output buffer empties again. This means that the app should 
 997  *   assume that it can write since the first OUTPUT event, and no more 
 998  *   OUTPUT events will be generated unless an error occurs. 
1000  *   Connection successfully established, for client sockets, or incoming 
1001  *   client connection, for server sockets. Wait for this event (also watch 
1002  *   out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call. 
1004  *   The connection is lost (or a connection request failed); this could 
1005  *   be due to a failure, or due to the peer closing it gracefully. 
1008 /* GSocket_SetCallback: 
1009  *  Enables the callbacks specified by 'flags'. Note that 'flags' 
1010  *  may be a combination of flags OR'ed toghether, so the same 
1011  *  callback function can be made to accept different events. 
1012  *  The callback function must have the following prototype: 
1014  *  void function(GSocket *socket, GSocketEvent event, char *cdata) 
1016 void GSocket::SetCallback(GSocketEventFlags flags
, 
1017                          GSocketCallback callback
, char *cdata
) 
1023   for (count 
= 0; count 
< GSOCK_MAX_EVENT
; count
++) 
1025     if ((flags 
& (1 << count
)) != 0) 
1027       m_cbacks
[count
] = callback
; 
1028       m_data
[count
] = cdata
; 
1033 /* GSocket_UnsetCallback: 
1034  *  Disables all callbacks specified by 'flags', which may be a 
1035  *  combination of flags OR'ed toghether. 
1037 void GSocket::UnsetCallback(GSocketEventFlags flags
) 
1043   for (count 
= 0; count 
< GSOCK_MAX_EVENT
; count
++) 
1045     if ((flags 
& (1 << count
)) != 0) 
1047       m_cbacks
[count
] = NULL
; 
1048       m_data
[count
] = NULL
; 
1054 #define CALL_CALLBACK(socket, event) {                                  \ 
1055   _GSocket_Disable(socket, event);                                      \ 
1056   if (socket->m_cbacks[event])                                          \ 
1057     socket->m_cbacks[event](socket, event, socket->m_data[event]);      \ 
1060 int GSocket::Recv_Stream(char *buffer
, int size
) 
1064     OTByteCount sz 
= 0 ; 
1066     OTCountDataBytes( m_endpoint 
, &sz 
) ; 
1067     if ( size 
> (int)sz 
) 
1069     res 
= OTRcv( m_endpoint 
, buffer 
, size 
, &flags 
) ; 
1075     // we simulate another read event if there are still bytes 
1076     if ( m_takesEvents 
) 
1078         OTByteCount sz 
= 0 ; 
1079         OTCountDataBytes( m_endpoint 
, &sz 
) ; 
1082             m_detected 
|= GSOCK_INPUT_FLAG 
; 
1083             (m_cbacks
[GSOCK_INPUT
])(this, GSOCK_INPUT
, m_data
[GSOCK_INPUT
]); 
1089 int GSocket::Recv_Dgram(char *buffer
, int size
) 
1094   struct sockaddr from
; 
1095   WX_SOCKLEN_T fromlen 
= sizeof(from
); 
1098   fromlen 
= sizeof(from
); 
1100   ret 
= recvfrom(m_endpoint
, buffer
, size
, 0, &from
, (WX_SOCKLEN_T 
*) &fromlen
); 
1105   /* Translate a system address into a GSocket address */ 
1108     m_peer 
= GAddress_new(); 
1111       m_error 
= GSOCK_MEMERR
; 
1115   err 
= _GAddress_translate_from(m_peer
, &from
, fromlen
); 
1116   if (err 
!= GSOCK_NOERROR
) 
1118     GAddress_destroy(m_peer
); 
1127 int GSocket::Send_Stream(const char *buffer
, int size
) 
1132     res 
= OTSnd( m_endpoint 
, (void*) buffer 
, size 
, flags 
) ; 
1136 int GSocket::Send_Dgram(const char *buffer
, int size
) 
1141   struct sockaddr 
*addr
; 
1147     m_error 
= GSOCK_INVADDR
; 
1151   err 
= _GAddress_translate_to(m_peer
, &addr
, &len
); 
1152   if (err 
!= GSOCK_NOERROR
) 
1158   ret 
= sendto(m_endpoint
, buffer
, size
, 0, addr
, len
); 
1160   /* Frees memory allocated from _GAddress_translate_to */ 
1166 /* Compatibility functions for GSocket */ 
1167 GSocket 
*GSocket_new(void) 
1169     GSocket 
*newsocket 
= new GSocket(); 
1170     if(newsocket
->IsOk()) 
1178  * ------------------------------------------------------------------------- 
1180  * ------------------------------------------------------------------------- 
1183 /* CHECK_ADDRESS verifies that the current family is either GSOCK_NOFAMILY 
1184  * or GSOCK_*family*, and if it is GSOCK_NOFAMILY, it initalizes address 
1185  * to be a GSOCK_*family*. In other cases, it returns GSOCK_INVADDR. 
1187 #define CHECK_ADDRESS(address, family, retval)                      \ 
1189   if (address->m_family == GSOCK_NOFAMILY)                          \ 
1190     if (_GAddress_Init_##family(address) != GSOCK_NOERROR)          \ 
1191       return address->m_error;                                      \ 
1192   if (address->m_family != GSOCK_##family)                          \ 
1194     address->m_error = GSOCK_INVADDR;                               \ 
1199 GAddress 
*GAddress_new() 
1203   if ((address 
= (GAddress 
*) malloc(sizeof(GAddress
))) == NULL
) 
1206   address
->m_family  
= GSOCK_NOFAMILY
; 
1207   address
->m_host 
= INADDR_NONE 
; 
1208   address
->m_port 
= 0 ; 
1213 GAddress 
*GAddress_copy(GAddress 
*address
) 
1217   assert(address 
!= NULL
); 
1219   if ((addr2 
= (GAddress 
*) malloc(sizeof(GAddress
))) == NULL
) 
1222   memcpy(addr2
, address
, sizeof(GAddress
)); 
1226 void GAddress_destroy(GAddress 
*address
) 
1228   assert(address 
!= NULL
); 
1233 void GAddress_SetFamily(GAddress 
*address
, GAddressType type
) 
1235   assert(address 
!= NULL
); 
1237   address
->m_family 
= type
; 
1240 GAddressType 
GAddress_GetFamily(GAddress 
*address
) 
1242   assert(address 
!= NULL
); 
1244   return address
->m_family
; 
1247 GSocketError 
_GAddress_translate_from(GAddress 
*address
, 
1250   switch (addr
->fAddressType
) 
1253       address
->m_family 
= GSOCK_INET
; 
1257       address
->m_family 
= GSOCK_INET6
; 
1262       address
->m_error 
= GSOCK_INVOP
; 
1266   address
->m_host 
= addr
->fHost 
; 
1267   address
->m_port 
= addr
->fPort 
; 
1268   return GSOCK_NOERROR
; 
1271 GSocketError 
_GAddress_translate_to(GAddress 
*address
, 
1274   if ( !GSocket_Verify_Inited() ) 
1275     return GSOCK_IOERR 
; 
1276   memset(addr
, 0 , sizeof(struct InetAddress
)); 
1277   OTInitInetAddress( addr 
, address
->m_port 
, address
->m_host 
) ; 
1278   return GSOCK_NOERROR
; 
1282  * ------------------------------------------------------------------------- 
1283  * Internet address family 
1284  * ------------------------------------------------------------------------- 
1287 GSocketError 
_GAddress_Init_INET(GAddress 
*address
) 
1289   address
->m_family 
= GSOCK_INET
; 
1290   address
->m_host 
= kOTAnyInetAddress 
; 
1292   return GSOCK_NOERROR
; 
1295 GSocketError 
GAddress_INET_SetHostName(GAddress 
*address
, const char *hostname
) 
1297   InetHostInfo hinfo 
; 
1300  if ( !GSocket_Verify_Inited() ) 
1301     return GSOCK_IOERR 
; 
1303   assert(address 
!= NULL
); 
1305   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1306   ret 
= OTInetStringToAddress( gInetSvcRef 
, (char*) hostname 
, &hinfo 
) ; 
1307   if ( ret 
!= kOTNoError 
) 
1309     address
->m_host 
= INADDR_NONE 
; 
1310     address
->m_error 
= GSOCK_NOHOST
; 
1311     return GSOCK_NOHOST
; 
1313   address
->m_host 
= hinfo
.addrs
[0] ; 
1314   return GSOCK_NOERROR
; 
1317 GSocketError 
GAddress_INET_SetBroadcastAddress(GAddress 
*address
) 
1319   return GAddress_INET_SetHostAddress(address
, INADDR_BROADCAST
); 
1322 GSocketError 
GAddress_INET_SetAnyAddress(GAddress 
*address
) 
1324   return GAddress_INET_SetHostAddress(address
, INADDR_ANY
); 
1327 GSocketError 
GAddress_INET_SetHostAddress(GAddress 
*address
, 
1328                                           unsigned long hostaddr
) 
1330   assert(address 
!= NULL
); 
1332   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1334   address
->m_host 
= htonl(hostaddr
) ; 
1336   return GSOCK_NOERROR
; 
1339 struct service_entry
 
1342     unsigned short port 
; 
1343     const char * protocol 
; 
1345 typedef struct service_entry service_entry 
; 
1347 service_entry gServices
[] = 
1349     { "http" , 80 , "tcp" } 
1352 GSocketError 
GAddress_INET_SetPortName(GAddress 
*address
, const char *port
, 
1353                                        const char *protocol
) 
1357   assert(address 
!= NULL
); 
1358   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1362     address
->m_error 
= GSOCK_INVPORT
; 
1363     return GSOCK_INVPORT
; 
1365   for ( i 
= 0 ; i 
< sizeof( gServices
) / sizeof( service_entry 
) ; ++i 
) 
1367     if ( strcmp( port 
, gServices
[i
].name 
) == 0 ) 
1369       if ( protocol 
== NULL 
|| strcmp( protocol 
, gServices
[i
].protocol 
) ) 
1371         address
->m_port 
= gServices
[i
].port 
; 
1372         return GSOCK_NOERROR
; 
1377   if (isdigit(port
[0])) 
1379      address
->m_port 
= atoi(port
); 
1380      return GSOCK_NOERROR
; 
1383   address
->m_error 
= GSOCK_INVPORT
; 
1384   return GSOCK_INVPORT
; 
1387 GSocketError 
GAddress_INET_SetPort(GAddress 
*address
, unsigned short port
) 
1389   assert(address 
!= NULL
); 
1390   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1391   address
->m_port 
= port 
; 
1393   return GSOCK_NOERROR
; 
1396 GSocketError 
GAddress_INET_GetHostName(GAddress 
*address
, char *hostname
, size_t sbuf
) 
1398   InetDomainName name 
; 
1399   if ( !GSocket_Verify_Inited() ) 
1400     return GSOCK_IOERR 
; 
1402   assert(address 
!= NULL
); 
1403   CHECK_ADDRESS(address
, INET
, GSOCK_INVADDR
); 
1405   OTInetAddressToName( gInetSvcRef 
, address
->m_host 
, name 
) ; 
1406   strncpy( hostname 
, name 
, sbuf 
) ; 
1407   return GSOCK_NOERROR
; 
1410 unsigned long GAddress_INET_GetHostAddress(GAddress 
*address
) 
1412   assert(address 
!= NULL
); 
1413   CHECK_ADDRESS(address
, INET
, 0); 
1415   return ntohl(address
->m_host
); 
1418 unsigned short GAddress_INET_GetPort(GAddress 
*address
) 
1420   assert(address 
!= NULL
); 
1421   CHECK_ADDRESS(address
, INET
, 0); 
1423   return address
->m_port
; 
1426 void GSocket::Enable_Events() 
1428     if ( m_takesEvents 
) 
1433         m_takesEvents 
= true ; 
1434         state 
= OTGetEndpointState(m_endpoint
); 
1437             OTByteCount sz 
= 0 ; 
1438             OTCountDataBytes( m_endpoint 
, &sz 
) ; 
1439             if ( state 
== T_INCON 
|| sz 
> 0 ) 
1441                 m_detected 
|= GSOCK_INPUT_FLAG 
; 
1442                 (m_cbacks
[GSOCK_INPUT
])(this, GSOCK_INPUT
, m_data
[GSOCK_INPUT
]); 
1446             if ( state 
== T_DATAXFER 
|| state 
== T_INREL 
) 
1448                 m_detected 
|=GSOCK_OUTPUT_FLAG 
; 
1449                 (m_cbacks
[GSOCK_OUTPUT
])(this, GSOCK_OUTPUT
, m_data
[GSOCK_OUTPUT
]); 
1455 void GSocket::Disable_Events() 
1457     m_takesEvents 
= false ; 
1460 /* _GSocket_Input_Timeout: 
1461  *  For blocking sockets, wait until data is available or 
1462  *  until timeout ellapses. 
1464 GSocketError 
GSocket::Input_Timeout() 
1466   if ( !m_non_blocking 
) 
1468     UnsignedWide now 
, start 
; 
1469     bool formerTakesEvents 
= m_takesEvents 
; 
1470     Microseconds(&start
); 
1472     m_takesEvents 
= false ; 
1474     while( (now
.hi 
* 4294967296.0 + now
.lo
) - (start
.hi 
* 4294967296.0 + start
.lo
) < m_timeout 
* 1000.0 ) 
1477         OTByteCount sz 
= 0 ; 
1478         state 
= OTGetEndpointState(m_endpoint
); 
1480         OTCountDataBytes( m_endpoint 
, &sz 
) ; 
1481         if ( state 
== T_INCON 
|| sz 
> 0 ) 
1483             m_takesEvents 
= formerTakesEvents 
; 
1484             return GSOCK_NOERROR
; 
1488     m_takesEvents 
= formerTakesEvents 
; 
1489     m_error 
= GSOCK_TIMEDOUT
; 
1490     return GSOCK_TIMEDOUT
; 
1492   return GSOCK_NOERROR
; 
1495 /* _GSocket_Output_Timeout: 
1496  *  For blocking sockets, wait until data can be sent without 
1497  *  blocking or until timeout ellapses. 
1499 GSocketError 
GSocket::Output_Timeout() 
1501   if ( !m_non_blocking 
) 
1503     UnsignedWide now 
, start 
; 
1504     bool formerTakesEvents 
= m_takesEvents 
; 
1505     Microseconds(&start
); 
1507     m_takesEvents 
= false ; 
1509     while( (now
.hi 
* 4294967296.0 + now
.lo
) - (start
.hi 
* 4294967296.0 + start
.lo
) < m_timeout 
* 1000.0 ) 
1512         state 
= OTGetEndpointState(m_endpoint
); 
1514         if ( state 
== T_DATAXFER 
|| state 
== T_INREL 
) 
1516             m_takesEvents 
= formerTakesEvents 
; 
1517             return GSOCK_NOERROR
; 
1521     m_takesEvents 
= formerTakesEvents 
; 
1522     m_error 
= GSOCK_TIMEDOUT
; 
1523     return GSOCK_TIMEDOUT
; 
1525   return GSOCK_NOERROR
; 
1529  *   There is data to be read in the input buffer. If, after a read 
1530  *   operation, there is still data available, the callback function will 
1533  *   The socket is available for writing. That is, the next write call 
1534  *   won't block. This event is generated only once, when the connection is 
1535  *   first established, and then only if a call failed with GSOCK_WOULDBLOCK, 
1536  *   when the output buffer empties again. This means that the app should 
1537  *   assume that it can write since the first OUTPUT event, and no more 
1538  *   OUTPUT events will be generated unless an error occurs. 
1540  *   Connection successfully established, for client sockets, or incoming 
1541  *   client connection, for server sockets. Wait for this event (also watch 
1542  *   out for GSOCK_LOST) after you issue a nonblocking GSocket_Connect() call. 
1544  *   The connection is lost (or a connection request failed); this could 
1545  *   be due to a failure, or due to the peer closing it gracefully. 
1548 void _GSocket_Internal_Proc(unsigned long e 
, void* d 
) 
1550     GSocket 
*socket 
= (GSocket
*) d 
; 
1555     OTEventCode ev 
= (OTEventCode
) e 
; 
1557     GSocketEvent event2
; 
1558     GSocketCallback cback
; 
1560     GSocketCallback cback2
; 
1563     event 
= GSOCK_MAX_EVENT 
; 
1564     event2 
= GSOCK_MAX_EVENT 
; 
1570     /* Check that the socket still exists (it has not been 
1571      * destroyed) and for safety, check that the m_endpoint field 
1572      * is what we expect it to be. 
1574     if ( /* (socket != NULL) && */ (socket
->m_takesEvents
)) 
1579                 event 
= GSOCK_CONNECTION 
; 
1582                 event 
= GSOCK_CONNECTION 
; 
1583                 event2 
= GSOCK_OUTPUT 
; 
1587                     retCall
.addr
.buf     
= NULL
; 
1588                     retCall
.addr
.maxlen  
= 0; 
1589                     retCall
.opt
.buf      
= NULL
; 
1590                     retCall
.opt
.maxlen   
= 0; 
1591                     retCall
.udata
.buf    
= NULL
; 
1592                     retCall
.udata
.maxlen 
= 0; 
1593                     OTRcvConnect( socket
->m_endpoint 
, &retCall 
) ; 
1597                 event 
= GSOCK_LOST 
; 
1601                 event 
= GSOCK_OUTPUT 
; 
1604                 event 
= GSOCK_INPUT 
; 
1607                 event 
= GSOCK_INPUT 
; 
1610       if (event 
!= GSOCK_MAX_EVENT
) 
1612         cback 
= socket
->m_cbacks
[event
]; 
1613         data 
= socket
->m_data
[event
]; 
1615         if (event 
== GSOCK_LOST
) 
1616           socket
->m_detected 
= GSOCK_LOST_FLAG
; 
1618           socket
->m_detected 
|= (1 << event
); 
1620       if (event2 
!= GSOCK_MAX_EVENT
) 
1622         cback2 
= socket
->m_cbacks
[event2
]; 
1623         data2 
= socket
->m_data
[event2
]; 
1625         if (event2 
== GSOCK_LOST
) 
1626           socket
->m_detected 
= GSOCK_LOST_FLAG
; 
1628           socket
->m_detected 
|= (1 << event2
); 
1632     /* OK, we can now leave the critical section because we have 
1633      * already obtained the callback address (we make no further 
1634      * accesses to socket->whatever). However, the app should 
1635      * be prepared to handle events from a socket that has just 
1640       (cback
)(socket
, event
, data
); 
1642       (cback2
)(socket
, event2
, data2
); 
1646 /* Hack added for Mac OS X */ 
1647 GSocketError 
GAddress_UNIX_GetPath(GAddress 
*addr
, char *path
, size_t buf
) 
1649     return GSOCK_INVADDR
; 
1652 GSocketError 
GAddress_UNIX_SetPath(GAddress 
*addr
, const char *path
) 
1654     return GSOCK_INVADDR
; 
1657 #endif  /* wxUSE_SOCKETS || defined(__GSOCKET_STANDALONE__) */