]> git.saurik.com Git - wxWidgets.git/commitdiff
* Implemented according to Apple CFSocket documentation:
authorDavid Elliott <dfe@tgwbd.org>
Wed, 24 Dec 2003 04:04:40 +0000 (04:04 +0000)
committerDavid Elliott <dfe@tgwbd.org>
Wed, 24 Dec 2003 04:04:40 +0000 (04:04 +0000)
  kCFSocketConnectCallBack: Called in response to a successful connect() and
    of course applies to client sockets only. Fails assertion if received
    from a server socket. Calls GSocket's Detected_Write otherwise.
  kCFSocketReadCallBack: Called whenever data is available to read or in
    the event that a new connection is waiting to be accepted. Call's
    GSocket's Detected_Read.
  kCFSocketWriteCallBack: Called whenever data can be written to kernel buffer.
    Call's GSocket's Detected_Write
* Added ALL_CALLBACK_TYPES macro which specifies all of the above three.
* Added (by virtue of ALL_CALLBACK_TYPES) the kCFSocketConnectCallBack to
  the calls to CFSocketCreateWithNative and CFSocketDisableCallBacks during
  GUI socket data creation.
* Use the default flags for CFSocket which automatically reenable the
  callbacks, but continue to disable close of fd on CFSocket invalidation.
  Eventually, GSocket should allow the GUI implementation to override close
  so that we can avoid calling the > 10.2 CFSocketSetSocketFlags function.
* CFRelease the socket after invalidating it (fixes memory leak)
* When adding/removing callbacks use kCFSocketReadCallBack for server
  GSOCK_CONNECTION and kCFSocketConnectCallback for client.
* When adding/removing callbacks GSOCK_LOST should do the same thing as
  GSOCK_INPUT (Thanks Kevin Hock)
* When enabling events, do not enable kCFSocketConnectCallBack for servers.
  It should never be called anyway since connect() should never be used
  on a server socket.
* When disabling events, disable ALL_CALLBACK_TYPES.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24999 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/mac/carbon/gsockosx.c
src/mac/gsockosx.c

index c93e4c9e2e3d138732ee53de78bcf748b2d35650..fd9703227c87c6811daf09e250351828d6305a20 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <CoreFoundation/CoreFoundation.h>
 
+#define ALL_CALLBACK_TYPES (kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack)
+
 struct MacGSocketData
 {
   CFSocketRef socket;
@@ -32,7 +34,8 @@ void Mac_Socket_Callback(CFSocketRef s, CFSocketCallBackType callbackType,
   switch (callbackType)
   {
     case kCFSocketConnectCallBack:
-      socket->m_functions->Detected_Read(socket);
+      assert(!socket->m_server);
+      socket->m_functions->Detected_Write(socket);
       break;
     case kCFSocketReadCallBack:
       socket->m_functions->Detected_Read(socket);
@@ -49,23 +52,30 @@ struct MacGSocketData* _GSocket_Get_Mac_Socket(GSocket *socket)
 {
   /* If socket is already created, returns a pointer to the data */
   /* Otherwise, creates socket and returns the pointer */
-  CFOptionFlags c;
   CFSocketContext cont;
   struct MacGSocketData* data = (struct MacGSocketData*)socket->m_gui_dependent;
 
   if (data && data->source) return data;
+
+  /* CFSocket has not been created, create it: */
   if (socket->m_fd < 0 || !data) return NULL;
   cont.version = 0; cont.retain = NULL;
   cont.release = NULL; cont.copyDescription = NULL;
   cont.info = socket;
-  c = kCFSocketReadCallBack | kCFSocketWriteCallBack;
 
-  CFSocketRef cf = CFSocketCreateWithNative(NULL, socket->m_fd, c,
-                                            Mac_Socket_Callback, &cont);
-  CFSocketDisableCallBacks(cf, kCFSocketReadCallBack | kCFSocketWriteCallBack);
+  CFSocketRef cf = CFSocketCreateWithNative(NULL, socket->m_fd,
+                       ALL_CALLBACK_TYPES, Mac_Socket_Callback, &cont);
+  /* Disable the callbacks until we are asked by GSocket to enable them. */
+  CFSocketDisableCallBacks(cf, ALL_CALLBACK_TYPES);
   CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(NULL, cf, 0);
   assert(source);
-  CFSocketSetSocketFlags(cf, 0);  /* Callbacks must be reenabled manually */
+  /* Turn off kCFSocketCloseOnInvalidate  (NOTE: > 10.2 only!) */
+  /* Another default flag that we don't turn on here is for DataCallBack and
+     also AcceptCallback (which overlap in bits) which we don't use anyway */
+  /* FIXME: For < 10.2 compatibility fix GSocket to call a platform-dependent
+     function to close the socket so that we can just call invalidate and
+     avoid having to set any special flags at all. */
+  CFSocketSetSocketFlags(cf, kCFSocketAutomaticallyReenableReadCallBack | kCFSocketAutomaticallyReenableWriteCallBack);
   socket->m_gui_dependent = (char*)data;
   CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
 
@@ -103,8 +113,10 @@ void _GSocket_GUI_Destroy_Socket(GSocket *socket)
     struct MacGSocketData *data = (struct MacGSocketData*)(socket->m_gui_dependent);
     if (data)
     {
+        /* CFSocketInvalidate does this anyway, so perhaps get rid of this: */
         CFRunLoopRemoveSource(CFRunLoopGetCurrent(), data->source, kCFRunLoopCommonModes);
         CFSocketInvalidate(data->socket);
+        CFRelease(data->socket);
         free(data);
     }
 }
@@ -117,8 +129,12 @@ void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event)
     switch (event)
     {
      case GSOCK_CONNECTION:
-         c = kCFSocketReadCallBack;  /* This works, but I don't know why. */
+         if(socket->m_server)
+            c = kCFSocketReadCallBack;
+         else
+            c = kCFSocketConnectCallBack;
          break;
+     case GSOCK_LOST:
      case GSOCK_INPUT:
          c = kCFSocketReadCallBack;
          break;
@@ -139,8 +155,12 @@ void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
     switch (event)
     {
      case GSOCK_CONNECTION:
-         c = kCFSocketConnectCallBack;
+         if(socket->m_server)
+            c = kCFSocketReadCallBack;
+         else
+            c = kCFSocketConnectCallBack;
          break;
+     case GSOCK_LOST:
      case GSOCK_INPUT:
          c = kCFSocketReadCallBack;
          break;
@@ -155,16 +175,20 @@ void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
 
 void _GSocket_Enable_Events(GSocket *socket)
 {
+    CFOptionFlags callBackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
     struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
     if (!data) return;
-    CFSocketEnableCallBacks(data->socket, kCFSocketReadCallBack | kCFSocketWriteCallBack);
+
+    if(!socket->m_server)
+        callBackTypes |= kCFSocketConnectCallBack;
+    CFSocketEnableCallBacks(data->socket, callBackTypes);
 }
 
 void _GSocket_Disable_Events(GSocket *socket)
 {
     struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
     if (!data) return;
-    CFSocketDisableCallBacks(data->socket, kCFSocketReadCallBack | kCFSocketWriteCallBack);
+    CFSocketDisableCallBacks(data->socket, ALL_CALLBACK_TYPES);
 }
 
 #endif // wxUSE_SOCKETS
index c93e4c9e2e3d138732ee53de78bcf748b2d35650..fd9703227c87c6811daf09e250351828d6305a20 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <CoreFoundation/CoreFoundation.h>
 
+#define ALL_CALLBACK_TYPES (kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack)
+
 struct MacGSocketData
 {
   CFSocketRef socket;
@@ -32,7 +34,8 @@ void Mac_Socket_Callback(CFSocketRef s, CFSocketCallBackType callbackType,
   switch (callbackType)
   {
     case kCFSocketConnectCallBack:
-      socket->m_functions->Detected_Read(socket);
+      assert(!socket->m_server);
+      socket->m_functions->Detected_Write(socket);
       break;
     case kCFSocketReadCallBack:
       socket->m_functions->Detected_Read(socket);
@@ -49,23 +52,30 @@ struct MacGSocketData* _GSocket_Get_Mac_Socket(GSocket *socket)
 {
   /* If socket is already created, returns a pointer to the data */
   /* Otherwise, creates socket and returns the pointer */
-  CFOptionFlags c;
   CFSocketContext cont;
   struct MacGSocketData* data = (struct MacGSocketData*)socket->m_gui_dependent;
 
   if (data && data->source) return data;
+
+  /* CFSocket has not been created, create it: */
   if (socket->m_fd < 0 || !data) return NULL;
   cont.version = 0; cont.retain = NULL;
   cont.release = NULL; cont.copyDescription = NULL;
   cont.info = socket;
-  c = kCFSocketReadCallBack | kCFSocketWriteCallBack;
 
-  CFSocketRef cf = CFSocketCreateWithNative(NULL, socket->m_fd, c,
-                                            Mac_Socket_Callback, &cont);
-  CFSocketDisableCallBacks(cf, kCFSocketReadCallBack | kCFSocketWriteCallBack);
+  CFSocketRef cf = CFSocketCreateWithNative(NULL, socket->m_fd,
+                       ALL_CALLBACK_TYPES, Mac_Socket_Callback, &cont);
+  /* Disable the callbacks until we are asked by GSocket to enable them. */
+  CFSocketDisableCallBacks(cf, ALL_CALLBACK_TYPES);
   CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(NULL, cf, 0);
   assert(source);
-  CFSocketSetSocketFlags(cf, 0);  /* Callbacks must be reenabled manually */
+  /* Turn off kCFSocketCloseOnInvalidate  (NOTE: > 10.2 only!) */
+  /* Another default flag that we don't turn on here is for DataCallBack and
+     also AcceptCallback (which overlap in bits) which we don't use anyway */
+  /* FIXME: For < 10.2 compatibility fix GSocket to call a platform-dependent
+     function to close the socket so that we can just call invalidate and
+     avoid having to set any special flags at all. */
+  CFSocketSetSocketFlags(cf, kCFSocketAutomaticallyReenableReadCallBack | kCFSocketAutomaticallyReenableWriteCallBack);
   socket->m_gui_dependent = (char*)data;
   CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
 
@@ -103,8 +113,10 @@ void _GSocket_GUI_Destroy_Socket(GSocket *socket)
     struct MacGSocketData *data = (struct MacGSocketData*)(socket->m_gui_dependent);
     if (data)
     {
+        /* CFSocketInvalidate does this anyway, so perhaps get rid of this: */
         CFRunLoopRemoveSource(CFRunLoopGetCurrent(), data->source, kCFRunLoopCommonModes);
         CFSocketInvalidate(data->socket);
+        CFRelease(data->socket);
         free(data);
     }
 }
@@ -117,8 +129,12 @@ void _GSocket_Install_Callback(GSocket *socket, GSocketEvent event)
     switch (event)
     {
      case GSOCK_CONNECTION:
-         c = kCFSocketReadCallBack;  /* This works, but I don't know why. */
+         if(socket->m_server)
+            c = kCFSocketReadCallBack;
+         else
+            c = kCFSocketConnectCallBack;
          break;
+     case GSOCK_LOST:
      case GSOCK_INPUT:
          c = kCFSocketReadCallBack;
          break;
@@ -139,8 +155,12 @@ void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
     switch (event)
     {
      case GSOCK_CONNECTION:
-         c = kCFSocketConnectCallBack;
+         if(socket->m_server)
+            c = kCFSocketReadCallBack;
+         else
+            c = kCFSocketConnectCallBack;
          break;
+     case GSOCK_LOST:
      case GSOCK_INPUT:
          c = kCFSocketReadCallBack;
          break;
@@ -155,16 +175,20 @@ void _GSocket_Uninstall_Callback(GSocket *socket, GSocketEvent event)
 
 void _GSocket_Enable_Events(GSocket *socket)
 {
+    CFOptionFlags callBackTypes = kCFSocketReadCallBack | kCFSocketWriteCallBack;
     struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
     if (!data) return;
-    CFSocketEnableCallBacks(data->socket, kCFSocketReadCallBack | kCFSocketWriteCallBack);
+
+    if(!socket->m_server)
+        callBackTypes |= kCFSocketConnectCallBack;
+    CFSocketEnableCallBacks(data->socket, callBackTypes);
 }
 
 void _GSocket_Disable_Events(GSocket *socket)
 {
     struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
     if (!data) return;
-    CFSocketDisableCallBacks(data->socket, kCFSocketReadCallBack | kCFSocketWriteCallBack);
+    CFSocketDisableCallBacks(data->socket, ALL_CALLBACK_TYPES);
 }
 
 #endif // wxUSE_SOCKETS