]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/gsockosx.cpp
use wxString::Format(), calling string.Format() has no effect patch 1267345)
[wxWidgets.git] / src / mac / carbon / gsockosx.cpp
CommitLineData
02dad85e 1/* -------------------------------------------------------------------------
99d80019
JS
2 * Project: GSocket (Generic Socket) for WX
3 * Name: gsockosx.c
4 * Copyright: (c) Brian Victor
5 * Licence: wxWindows Licence
6 * Purpose: GSocket: Mac OS X mach-o part
7 * CVSID: $Id$
02dad85e
DE
8 * Mac code by Brian Victor, February 2002. Email comments to bhv1@psu.edu
9 * ------------------------------------------------------------------------- */
10
11#include "wx/setup.h"
12
13#if wxUSE_SOCKETS
14
15#include <stdlib.h>
16#include "wx/gsocket.h"
17#include "wx/unix/gsockunx.h"
18
19#include <CoreFoundation/CoreFoundation.h>
20
21#define ALL_CALLBACK_TYPES (kCFSocketReadCallBack | kCFSocketWriteCallBack | kCFSocketConnectCallBack)
22
23struct MacGSocketData
24{
25 CFSocketRef socket;
26 CFRunLoopSourceRef source;
27};
28
7725dc7c
KH
29// Sockets must use the event loop on the main thread
30// We will store the main loop's reference when Initialize is called
31static CFRunLoopRef s_mainRunLoop = NULL;
32
02dad85e
DE
33void Mac_Socket_Callback(CFSocketRef s, CFSocketCallBackType callbackType,
34 CFDataRef address, const void* data, void* info)
35{
36 GSocket* socket = (GSocket*)info;
37 struct MacGSocketData* macdata;
38 macdata = (struct MacGSocketData*)socket->m_gui_dependent;
39 if (!macdata) return;
40 switch (callbackType)
41 {
42 case kCFSocketConnectCallBack:
43 assert(!socket->m_server);
0a647691 44 socket->Detected_Write();
02dad85e
DE
45 break;
46 case kCFSocketReadCallBack:
0a647691 47 socket->Detected_Read();
02dad85e
DE
48 break;
49 case kCFSocketWriteCallBack:
0a647691 50 socket->Detected_Write();
02dad85e
DE
51 break;
52 default:
53 break; /* We shouldn't get here. */
54 }
55}
56
57struct MacGSocketData* _GSocket_Get_Mac_Socket(GSocket *socket)
58{
59 /* If socket is already created, returns a pointer to the data */
60 /* Otherwise, creates socket and returns the pointer */
61 CFSocketContext cont;
62 struct MacGSocketData* data = (struct MacGSocketData*)socket->m_gui_dependent;
63
64 if (data && data->source) return data;
65
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;
70 cont.info = socket;
71
72 CFSocketRef cf = CFSocketCreateWithNative(NULL, socket->m_fd,
73 ALL_CALLBACK_TYPES, Mac_Socket_Callback, &cont);
74 CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(NULL, cf, 0);
75 assert(source);
76 socket->m_gui_dependent = (char*)data;
77
78 /* Keep the source and the socket around. */
79 data->source = source;
80 data->socket = cf;
81
82 return data;
83}
84
0a647691
DE
85bool GSocketGUIFunctionsTableConcrete::CanUseEventLoop()
86{ return true; }
87
88bool GSocketGUIFunctionsTableConcrete::OnInit(void)
02dad85e 89{
7725dc7c
KH
90 // No need to store the main loop again
91 if (s_mainRunLoop != NULL)
92 return true;
93
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);
99
0a647691 100 return true;
02dad85e
DE
101}
102
0a647691 103void GSocketGUIFunctionsTableConcrete::OnExit(void)
02dad85e 104{
7725dc7c
KH
105 // Release the reference count, and set the reference back to NULL
106 CFRelease(s_mainRunLoop);
107 s_mainRunLoop = NULL;
02dad85e
DE
108}
109
0a647691 110bool GSocketGUIFunctionsTableConcrete::Init_Socket(GSocket *socket)
02dad85e 111{
facd6764 112 struct MacGSocketData *data = (struct MacGSocketData *)malloc(sizeof(struct MacGSocketData));
02dad85e
DE
113 if (data)
114 {
115 socket->m_gui_dependent = (char*)data;
116 data->socket = NULL;
117 data->source = NULL;
118 return 1;
119 }
120 return 0;
121}
122
0a647691 123void GSocketGUIFunctionsTableConcrete::Destroy_Socket(GSocket *socket)
02dad85e
DE
124{
125 struct MacGSocketData *data = (struct MacGSocketData*)(socket->m_gui_dependent);
126 if (data)
127 {
128 CFRelease(data->socket);
129 free(data);
130 }
131}
132
0a647691 133void GSocketGUIFunctionsTableConcrete::Install_Callback(GSocket *socket, GSocketEvent event)
02dad85e
DE
134{
135 int c;
136 struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
137 if (!data) return;
138 switch (event)
139 {
140 case GSOCK_CONNECTION:
141 if(socket->m_server)
142 c = kCFSocketReadCallBack;
143 else
144 c = kCFSocketConnectCallBack;
145 break;
146 case GSOCK_LOST:
147 case GSOCK_INPUT:
148 c = kCFSocketReadCallBack;
149 break;
150 case GSOCK_OUTPUT:
151 c = kCFSocketWriteCallBack;
152 break;
153 default:
154 c = 0;
155 }
156 CFSocketEnableCallBacks(data->socket, c);
157}
158
0a647691 159void GSocketGUIFunctionsTableConcrete::Uninstall_Callback(GSocket *socket, GSocketEvent event)
02dad85e
DE
160{
161 int c;
162 struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
163 if (!data) return;
164 switch (event)
165 {
166 case GSOCK_CONNECTION:
167 if(socket->m_server)
168 c = kCFSocketReadCallBack;
169 else
170 c = kCFSocketConnectCallBack;
171 break;
172 case GSOCK_LOST:
173 case GSOCK_INPUT:
174 c = kCFSocketReadCallBack;
175 break;
176 case GSOCK_OUTPUT:
177 c = kCFSocketWriteCallBack;
178 break;
179 default:
180 c = 0;
181 }
182 CFSocketDisableCallBacks(data->socket, c);
183}
184
0a647691 185void GSocketGUIFunctionsTableConcrete::Enable_Events(GSocket *socket)
02dad85e
DE
186{
187 struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
188 if (!data) return;
189
7725dc7c 190 CFRunLoopAddSource(s_mainRunLoop, data->source, kCFRunLoopCommonModes);
02dad85e
DE
191}
192
0a647691 193void GSocketGUIFunctionsTableConcrete::Disable_Events(GSocket *socket)
02dad85e
DE
194{
195 struct MacGSocketData* data = _GSocket_Get_Mac_Socket(socket);
196 if (!data) return;
197
198 /* CFSocketInvalidate does CFRunLoopRemoveSource anyway */
7725dc7c 199 CFRunLoopRemoveSource(s_mainRunLoop, data->source, kCFRunLoopCommonModes);
02dad85e
DE
200 CFSocketInvalidate(data->socket);
201}
202
203#endif // wxUSE_SOCKETS