@@ -212,4 +212,175 @@ void MacCFSocketServer::OnWakeUpCallback() {
212
212
ASSERT (run_loop_ == CFRunLoopGetCurrent ());
213
213
CFRunLoopStop (run_loop_);
214
214
}
215
+
216
+ // /////////////////////////////////////////////////////////////////////////////
217
+ // MacCarbonSocketServer
218
+ // /////////////////////////////////////////////////////////////////////////////
219
+ #ifndef CARBON_DEPRECATED
220
+
221
+ const UInt32 kEventClassSocketServer = ' MCSS' ;
222
+ const UInt32 kEventWakeUp = ' WAKE' ;
223
+ const EventTypeSpec kEventWakeUpSpec [] = {
224
+ { kEventClassSocketServer , kEventWakeUp }
225
+ };
226
+
227
+ std::string DecodeEvent (EventRef event) {
228
+ std::string str;
229
+ DecodeFourChar (::GetEventClass (event), &str);
230
+ str.push_back (' :' );
231
+ DecodeFourChar (::GetEventKind (event), &str);
232
+ return str;
233
+ }
234
+
235
+ MacCarbonSocketServer::MacCarbonSocketServer ()
236
+ : event_queue_(GetCurrentEventQueue()), wake_up_(NULL ) {
237
+ VERIFY (noErr == CreateEvent (NULL , kEventClassSocketServer , kEventWakeUp , 0 ,
238
+ kEventAttributeUserEvent , &wake_up_));
239
+ }
240
+
241
+ MacCarbonSocketServer::~MacCarbonSocketServer () {
242
+ if (wake_up_) {
243
+ ReleaseEvent (wake_up_);
244
+ }
245
+ }
246
+
247
+ bool MacCarbonSocketServer::Wait (int cms, bool process_io) {
248
+ ASSERT (GetCurrentEventQueue () == event_queue_);
249
+
250
+ // Listen to all events if we're processing I/O.
251
+ // Only listen for our wakeup event if we're not.
252
+ UInt32 num_types = 0 ;
253
+ const EventTypeSpec* events = NULL ;
254
+ if (!process_io) {
255
+ num_types = GetEventTypeCount (kEventWakeUpSpec );
256
+ events = kEventWakeUpSpec ;
257
+ }
258
+
259
+ EventTargetRef target = GetEventDispatcherTarget ();
260
+ EventTimeout timeout =
261
+ (kForever == cms) ? kEventDurationForever : cms / 1000.0 ;
262
+ EventTimeout end_time = GetCurrentEventTime () + timeout;
263
+
264
+ bool done = false ;
265
+ while (!done) {
266
+ EventRef event;
267
+ OSStatus result = ReceiveNextEvent (num_types, events, timeout, true ,
268
+ &event);
269
+ if (noErr == result) {
270
+ if (wake_up_ != event) {
271
+ LOG_F (LS_VERBOSE) << " Dispatching event: " << DecodeEvent (event);
272
+ result = SendEventToEventTarget (event, target);
273
+ if ((noErr != result) && (eventNotHandledErr != result)) {
274
+ LOG_E (LS_ERROR, OS, result) << " SendEventToEventTarget" ;
275
+ }
276
+ } else {
277
+ done = true ;
278
+ }
279
+ ReleaseEvent (event);
280
+ } else if (eventLoopTimedOutErr == result) {
281
+ ASSERT (cms != kForever );
282
+ done = true ;
283
+ } else if (eventLoopQuitErr == result) {
284
+ // Ignore this... we get spurious quits for a variety of reasons.
285
+ LOG_E (LS_VERBOSE, OS, result) << " ReceiveNextEvent" ;
286
+ } else {
287
+ // Some strange error occurred. Log it.
288
+ LOG_E (LS_WARNING, OS, result) << " ReceiveNextEvent" ;
289
+ return false ;
290
+ }
291
+ if (kForever != cms) {
292
+ timeout = end_time - GetCurrentEventTime ();
293
+ }
294
+ }
295
+ return true ;
296
+ }
297
+
298
+ void MacCarbonSocketServer::WakeUp () {
299
+ if (!IsEventInQueue (event_queue_, wake_up_)) {
300
+ RetainEvent (wake_up_);
301
+ OSStatus result = PostEventToQueue (event_queue_, wake_up_,
302
+ kEventPriorityStandard );
303
+ if (noErr != result) {
304
+ LOG_E (LS_ERROR, OS, result) << " PostEventToQueue" ;
305
+ }
306
+ }
307
+ }
308
+
309
+ // /////////////////////////////////////////////////////////////////////////////
310
+ // MacCarbonAppSocketServer
311
+ // /////////////////////////////////////////////////////////////////////////////
312
+
313
+ MacCarbonAppSocketServer::MacCarbonAppSocketServer ()
314
+ : event_queue_(GetCurrentEventQueue()) {
315
+ // Install event handler
316
+ VERIFY (noErr == InstallApplicationEventHandler (
317
+ NewEventHandlerUPP (WakeUpEventHandler), 1 , kEventWakeUpSpec , this ,
318
+ &event_handler_));
319
+
320
+ // Install a timer and set it idle to begin with.
321
+ VERIFY (noErr == InstallEventLoopTimer (GetMainEventLoop (),
322
+ kEventDurationForever ,
323
+ kEventDurationForever ,
324
+ NewEventLoopTimerUPP (TimerHandler),
325
+ this ,
326
+ &timer_));
327
+ }
328
+
329
+ MacCarbonAppSocketServer::~MacCarbonAppSocketServer () {
330
+ RemoveEventLoopTimer (timer_);
331
+ RemoveEventHandler (event_handler_);
332
+ }
333
+
334
+ OSStatus MacCarbonAppSocketServer::WakeUpEventHandler (
335
+ EventHandlerCallRef next, EventRef event, void *data) {
336
+ QuitApplicationEventLoop ();
337
+ return noErr ;
338
+ }
339
+
340
+ void MacCarbonAppSocketServer::TimerHandler (
341
+ EventLoopTimerRef timer, void *data) {
342
+ QuitApplicationEventLoop ();
343
+ }
344
+
345
+ bool MacCarbonAppSocketServer::Wait (int cms, bool process_io) {
346
+ if (!process_io && cms == 0 ) {
347
+ // No op.
348
+ return true ;
349
+ }
350
+ if (kForever != cms) {
351
+ // Start a timer.
352
+ OSStatus error =
353
+ SetEventLoopTimerNextFireTime (timer_, cms / 1000.0 );
354
+ if (error != noErr ) {
355
+ LOG (LS_ERROR) << " Failed setting next fire time." ;
356
+ }
357
+ }
358
+ if (!process_io) {
359
+ // No way to listen to common modes and not get socket events, unless
360
+ // we disable each one's callbacks.
361
+ EnableSocketCallbacks (false );
362
+ }
363
+ RunApplicationEventLoop ();
364
+ if (!process_io) {
365
+ // Reenable them. Hopefully this won't cause spurious callbacks or
366
+ // missing ones while they were disabled.
367
+ EnableSocketCallbacks (true );
368
+ }
369
+ return true ;
370
+ }
371
+
372
+ void MacCarbonAppSocketServer::WakeUp () {
373
+ // TODO: No-op if there's already a WakeUp in flight.
374
+ EventRef wake_up;
375
+ VERIFY (noErr == CreateEvent (NULL , kEventClassSocketServer , kEventWakeUp , 0 ,
376
+ kEventAttributeUserEvent , &wake_up));
377
+ OSStatus result = PostEventToQueue (event_queue_, wake_up,
378
+ kEventPriorityStandard );
379
+ if (noErr != result) {
380
+ LOG_E (LS_ERROR, OS, result) << " PostEventToQueue" ;
381
+ }
382
+ ReleaseEvent (wake_up);
383
+ }
384
+
385
+ #endif
215
386
} // namespace rtc
0 commit comments