1 /* ------------------------------------------------------------------------- 
   2  * Project: GSocket (Generic Socket) for WX 
   4  * Purpose: GSocket: Mac OS X mach-o part 
   6  * Mac code by Brian Victor, February 2002.  Email comments to bhv1@psu.edu 
   7  * ------------------------------------------------------------------------- */ 
  14 #include "wx/gsocket.h" 
  15 #include "wx/unix/gsockunx.h" 
  17 #include <CoreFoundation/CoreFoundation.h> 
  19 #define ALL_CALLBACK_TYPES (kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack) 
  24   CFRunLoopSourceRef source
; 
  27 // Sockets must use the event loop on the main thread 
  28 // We will store the main loop's reference when Initialize is called 
  29 static CFRunLoopRef s_mainRunLoop 
= NULL
; 
  31 void Mac_Socket_Callback(CFSocketRef s
, CFSocketCallBackType callbackType
, 
  32                          CFDataRef address
, const void* data
, void* info
) 
  34   GSocket
* socket 
= (GSocket
*)info
; 
  35   struct MacGSocketData
* macdata
; 
  36   macdata 
= (struct MacGSocketData
*)socket
->m_gui_dependent
; 
  40     case kCFSocketConnectCallBack
: 
  41       assert(!socket
->m_server
); 
  42       socket
->Detected_Write(); 
  44     case kCFSocketReadCallBack
: 
  45       socket
->Detected_Read(); 
  47     case kCFSocketWriteCallBack
: 
  48       socket
->Detected_Write(); 
  51       break;  /* We shouldn't get here. */ 
  55 struct MacGSocketData
* _GSocket_Get_Mac_Socket(GSocket 
*socket
) 
  57   /* If socket is already created, returns a pointer to the data */ 
  58   /* Otherwise, creates socket and returns the pointer */ 
  60   struct MacGSocketData
* data 
= (struct MacGSocketData
*)socket
->m_gui_dependent
; 
  62   if (data 
&& data
->source
) return data
; 
  64   /* CFSocket has not been created, create it: */ 
  65   if (socket
->m_fd 
< 0 || !data
) return NULL
; 
  66   cont
.version 
= 0; cont
.retain 
= NULL
; 
  67   cont
.release 
= NULL
; cont
.copyDescription 
= NULL
; 
  70   CFSocketRef cf 
= CFSocketCreateWithNative(NULL
, socket
->m_fd
, 
  71                         ALL_CALLBACK_TYPES
, Mac_Socket_Callback
, &cont
); 
  72   CFRunLoopSourceRef source 
= CFSocketCreateRunLoopSource(NULL
, cf
, 0); 
  74   socket
->m_gui_dependent 
= (char*)data
; 
  76   /* Keep the source and the socket around. */ 
  77   data
->source 
= source
; 
  83 bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop() 
  86 bool GSocketGUIFunctionsTableConcrete::OnInit(void) 
  88     // No need to store the main loop again 
  89     if (s_mainRunLoop 
!= NULL
) 
  92     // Get the loop for the main thread so our events will actually fire. 
  93     // The common socket.cpp code will assert if initialize is called from a 
  94     // secondary thread, otherwise Mac would have the same problems as MSW 
  95     s_mainRunLoop 
= CFRunLoopGetCurrent(); 
  96     CFRetain(s_mainRunLoop
); 
 101 void GSocketGUIFunctionsTableConcrete::OnExit(void) 
 103     // Release the reference count, and set the reference back to NULL 
 104     CFRelease(s_mainRunLoop
); 
 105     s_mainRunLoop 
= NULL
; 
 108 bool GSocketGUIFunctionsTableConcrete::Init_Socket(GSocket 
*socket
) 
 110     struct MacGSocketData 
*data 
= (struct MacGSocketData 
*)malloc(sizeof(struct MacGSocketData
)); 
 113         socket
->m_gui_dependent 
= (char*)data
; 
 121 void GSocketGUIFunctionsTableConcrete::Destroy_Socket(GSocket 
*socket
) 
 123     struct MacGSocketData 
*data 
= (struct MacGSocketData
*)(socket
->m_gui_dependent
); 
 126         CFRelease(data
->socket
); 
 131 void GSocketGUIFunctionsTableConcrete::Install_Callback(GSocket 
*socket
, GSocketEvent event
) 
 134     struct MacGSocketData
* data 
= _GSocket_Get_Mac_Socket(socket
); 
 138      case GSOCK_CONNECTION
: 
 140             c 
= kCFSocketReadCallBack
; 
 142             c 
= kCFSocketConnectCallBack
; 
 146          c 
= kCFSocketReadCallBack
; 
 149          c 
= kCFSocketWriteCallBack
; 
 154     CFSocketEnableCallBacks(data
->socket
, c
); 
 157 void GSocketGUIFunctionsTableConcrete::Uninstall_Callback(GSocket 
*socket
, GSocketEvent event
) 
 160     struct MacGSocketData
* data 
= _GSocket_Get_Mac_Socket(socket
); 
 164      case GSOCK_CONNECTION
: 
 166             c 
= kCFSocketReadCallBack
; 
 168             c 
= kCFSocketConnectCallBack
; 
 172          c 
= kCFSocketReadCallBack
; 
 175          c 
= kCFSocketWriteCallBack
; 
 180     CFSocketDisableCallBacks(data
->socket
, c
); 
 183 void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket 
*socket
) 
 185     struct MacGSocketData
* data 
= _GSocket_Get_Mac_Socket(socket
); 
 188     CFRunLoopAddSource(s_mainRunLoop
, data
->source
, kCFRunLoopCommonModes
); 
 191 void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket 
*socket
) 
 193     struct MacGSocketData
* data 
= _GSocket_Get_Mac_Socket(socket
); 
 196     /* CFSocketInvalidate does CFRunLoopRemoveSource anyway */ 
 197     CFRunLoopRemoveSource(s_mainRunLoop
, data
->source
, kCFRunLoopCommonModes
); 
 198     CFSocketInvalidate(data
->socket
); 
 201 #endif // wxUSE_SOCKETS