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 void Mac_Socket_Callback(CFSocketRef s
, CFSocketCallBackType callbackType
,
28 CFDataRef address
, const void* data
, void* info
)
30 GSocket
* socket
= (GSocket
*)info
;
31 struct MacGSocketData
* macdata
;
32 macdata
= (struct MacGSocketData
*)socket
->m_gui_dependent
;
36 case kCFSocketConnectCallBack
:
37 assert(!socket
->m_server
);
38 socket
->m_functions
->Detected_Write(socket
);
40 case kCFSocketReadCallBack
:
41 socket
->m_functions
->Detected_Read(socket
);
43 case kCFSocketWriteCallBack
:
44 socket
->m_functions
->Detected_Write(socket
);
47 break; /* We shouldn't get here. */
51 struct MacGSocketData
* _GSocket_Get_Mac_Socket(GSocket
*socket
)
53 /* If socket is already created, returns a pointer to the data */
54 /* Otherwise, creates socket and returns the pointer */
56 struct MacGSocketData
* data
= (struct MacGSocketData
*)socket
->m_gui_dependent
;
58 if (data
&& data
->source
) return data
;
60 /* CFSocket has not been created, create it: */
61 if (socket
->m_fd
< 0 || !data
) return NULL
;
62 cont
.version
= 0; cont
.retain
= NULL
;
63 cont
.release
= NULL
; cont
.copyDescription
= NULL
;
66 CFSocketRef cf
= CFSocketCreateWithNative(NULL
, socket
->m_fd
,
67 ALL_CALLBACK_TYPES
, Mac_Socket_Callback
, &cont
);
68 /* Disable the callbacks until we are asked by GSocket to enable them. */
69 CFSocketDisableCallBacks(cf
, ALL_CALLBACK_TYPES
);
70 CFRunLoopSourceRef source
= CFSocketCreateRunLoopSource(NULL
, cf
, 0);
72 /* Turn off kCFSocketCloseOnInvalidate (NOTE: > 10.2 only!) */
73 /* Another default flag that we don't turn on here is for DataCallBack and
74 also AcceptCallback (which overlap in bits) which we don't use anyway */
75 /* FIXME: For < 10.2 compatibility fix GSocket to call a platform-dependent
76 function to close the socket so that we can just call invalidate and
77 avoid having to set any special flags at all. */
78 CFSocketSetSocketFlags(cf
, kCFSocketAutomaticallyReenableReadCallBack
| kCFSocketAutomaticallyReenableWriteCallBack
);
79 socket
->m_gui_dependent
= (char*)data
;
80 CFRunLoopAddSource(CFRunLoopGetCurrent(), source
, kCFRunLoopDefaultMode
);
82 /* Keep the source and the socket around. */
83 data
->source
= source
;
89 int _GSocket_GUI_Init(void)
94 void _GSocket_GUI_Cleanup(void)
98 int _GSocket_GUI_Init_Socket(GSocket
*socket
)
100 struct MacGSocketData
*data
= malloc(sizeof(struct MacGSocketData
));
103 socket
->m_gui_dependent
= (char*)data
;
111 void _GSocket_GUI_Destroy_Socket(GSocket
*socket
)
113 struct MacGSocketData
*data
= (struct MacGSocketData
*)(socket
->m_gui_dependent
);
116 /* CFSocketInvalidate does this anyway, so perhaps get rid of this: */
117 CFRunLoopRemoveSource(CFRunLoopGetCurrent(), data
->source
, kCFRunLoopCommonModes
);
118 CFSocketInvalidate(data
->socket
);
119 CFRelease(data
->socket
);
124 void _GSocket_Install_Callback(GSocket
*socket
, GSocketEvent event
)
127 struct MacGSocketData
* data
= _GSocket_Get_Mac_Socket(socket
);
131 case GSOCK_CONNECTION
:
133 c
= kCFSocketReadCallBack
;
135 c
= kCFSocketConnectCallBack
;
139 c
= kCFSocketReadCallBack
;
142 c
= kCFSocketWriteCallBack
;
147 CFSocketEnableCallBacks(data
->socket
, c
);
150 void _GSocket_Uninstall_Callback(GSocket
*socket
, GSocketEvent event
)
153 struct MacGSocketData
* data
= _GSocket_Get_Mac_Socket(socket
);
157 case GSOCK_CONNECTION
:
159 c
= kCFSocketReadCallBack
;
161 c
= kCFSocketConnectCallBack
;
165 c
= kCFSocketReadCallBack
;
168 c
= kCFSocketWriteCallBack
;
173 CFSocketDisableCallBacks(data
->socket
, c
);
176 void _GSocket_Enable_Events(GSocket
*socket
)
178 CFOptionFlags callBackTypes
= kCFSocketReadCallBack
| kCFSocketWriteCallBack
;
179 struct MacGSocketData
* data
= _GSocket_Get_Mac_Socket(socket
);
182 if(!socket
->m_server
)
183 callBackTypes
|= kCFSocketConnectCallBack
;
184 CFSocketEnableCallBacks(data
->socket
, callBackTypes
);
187 void _GSocket_Disable_Events(GSocket
*socket
)
189 struct MacGSocketData
* data
= _GSocket_Get_Mac_Socket(socket
);
191 CFSocketDisableCallBacks(data
->socket
, ALL_CALLBACK_TYPES
);
194 #endif // wxUSE_SOCKETS