1 /* -------------------------------------------------------------------------
2 * Project: GSocket (Generic Socket) for WX
4 * Copyright: (c) Brian Victor
5 * Licence: wxWindows Licence
6 * Purpose: GSocket: Mac OS X mach-o part
8 * Mac code by Brian Victor, February 2002. Email comments to bhv1@psu.edu
9 * ------------------------------------------------------------------------- */
16 #include "wx/gsocket.h"
17 #include "wx/unix/gsockunx.h"
19 #include <CoreFoundation/CoreFoundation.h>
21 #define ALL_CALLBACK_TYPES (kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack)
26 CFRunLoopSourceRef source
;
29 // Sockets must use the event loop on the main thread
30 // We will store the main loop's reference when Initialize is called
31 static CFRunLoopRef s_mainRunLoop
= NULL
;
33 void Mac_Socket_Callback(CFSocketRef s
, CFSocketCallBackType callbackType
,
34 CFDataRef address
, const void* data
, void* info
)
36 GSocket
* socket
= (GSocket
*)info
;
37 struct MacGSocketData
* macdata
;
38 macdata
= (struct MacGSocketData
*)socket
->m_gui_dependent
;
42 case kCFSocketConnectCallBack
:
43 assert(!socket
->m_server
);
44 socket
->Detected_Write();
46 case kCFSocketReadCallBack
:
47 socket
->Detected_Read();
49 case kCFSocketWriteCallBack
:
50 socket
->Detected_Write();
53 break; /* We shouldn't get here. */
57 struct MacGSocketData
* _GSocket_Get_Mac_Socket(GSocket
*socket
)
59 /* If socket is already created, returns a pointer to the data */
60 /* Otherwise, creates socket and returns the pointer */
62 struct MacGSocketData
* data
= (struct MacGSocketData
*)socket
->m_gui_dependent
;
64 if (data
&& data
->source
) return data
;
66 /* CFSocket has not been created, create it: */
67 if (socket
->m_fd
< 0 || !data
) return NULL
;
68 cont
.version
= 0; cont
.retain
= NULL
;
69 cont
.release
= NULL
; cont
.copyDescription
= NULL
;
72 CFSocketRef cf
= CFSocketCreateWithNative(NULL
, socket
->m_fd
,
73 ALL_CALLBACK_TYPES
, Mac_Socket_Callback
, &cont
);
74 CFRunLoopSourceRef source
= CFSocketCreateRunLoopSource(NULL
, cf
, 0);
76 socket
->m_gui_dependent
= (char*)data
;
78 /* Keep the source and the socket around. */
79 data
->source
= source
;
85 bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop()
88 bool GSocketGUIFunctionsTableConcrete::OnInit(void)
90 // No need to store the main loop again
91 if (s_mainRunLoop
!= NULL
)
94 // Get the loop for the main thread so our events will actually fire.
95 // The common socket.cpp code will assert if initialize is called from a
96 // secondary thread, otherwise Mac would have the same problems as MSW
97 s_mainRunLoop
= CFRunLoopGetCurrent();
98 CFRetain(s_mainRunLoop
);
103 void GSocketGUIFunctionsTableConcrete::OnExit(void)
105 // Release the reference count, and set the reference back to NULL
106 CFRelease(s_mainRunLoop
);
107 s_mainRunLoop
= NULL
;
110 bool GSocketGUIFunctionsTableConcrete::Init_Socket(GSocket
*socket
)
112 struct MacGSocketData
*data
= (struct MacGSocketData
*)malloc(sizeof(struct MacGSocketData
));
115 socket
->m_gui_dependent
= (char*)data
;
123 void GSocketGUIFunctionsTableConcrete::Destroy_Socket(GSocket
*socket
)
125 struct MacGSocketData
*data
= (struct MacGSocketData
*)(socket
->m_gui_dependent
);
128 CFRelease(data
->socket
);
133 void GSocketGUIFunctionsTableConcrete::Install_Callback(GSocket
*socket
, GSocketEvent event
)
136 struct MacGSocketData
* data
= _GSocket_Get_Mac_Socket(socket
);
140 case GSOCK_CONNECTION
:
142 c
= kCFSocketReadCallBack
;
144 c
= kCFSocketConnectCallBack
;
148 c
= kCFSocketReadCallBack
;
151 c
= kCFSocketWriteCallBack
;
156 CFSocketEnableCallBacks(data
->socket
, c
);
159 void GSocketGUIFunctionsTableConcrete::Uninstall_Callback(GSocket
*socket
, GSocketEvent event
)
162 struct MacGSocketData
* data
= _GSocket_Get_Mac_Socket(socket
);
166 case GSOCK_CONNECTION
:
168 c
= kCFSocketReadCallBack
;
170 c
= kCFSocketConnectCallBack
;
174 c
= kCFSocketReadCallBack
;
177 c
= kCFSocketWriteCallBack
;
182 CFSocketDisableCallBacks(data
->socket
, c
);
185 void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket
*socket
)
187 struct MacGSocketData
* data
= _GSocket_Get_Mac_Socket(socket
);
190 CFRunLoopAddSource(s_mainRunLoop
, data
->source
, kCFRunLoopCommonModes
);
193 void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket
*socket
)
195 struct MacGSocketData
* data
= _GSocket_Get_Mac_Socket(socket
);
198 /* CFSocketInvalidate does CFRunLoopRemoveSource anyway */
199 CFRunLoopRemoveSource(s_mainRunLoop
, data
->source
, kCFRunLoopCommonModes
);
200 CFSocketInvalidate(data
->socket
);
203 #endif // wxUSE_SOCKETS