| Index: webrtc/base/macsocketserver.cc
|
| diff --git a/webrtc/base/macsocketserver.cc b/webrtc/base/macsocketserver.cc
|
| index b763e813b037d94909d8263d01049b4dcd5e0008..96b2091dd37b38dfd30745ecb7d9c67c768d0867 100644
|
| --- a/webrtc/base/macsocketserver.cc
|
| +++ b/webrtc/base/macsocketserver.cc
|
| @@ -212,4 +212,175 @@
|
| ASSERT(run_loop_ == CFRunLoopGetCurrent());
|
| CFRunLoopStop(run_loop_);
|
| }
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// MacCarbonSocketServer
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +#ifndef CARBON_DEPRECATED
|
| +
|
| +const UInt32 kEventClassSocketServer = 'MCSS';
|
| +const UInt32 kEventWakeUp = 'WAKE';
|
| +const EventTypeSpec kEventWakeUpSpec[] = {
|
| + { kEventClassSocketServer, kEventWakeUp }
|
| +};
|
| +
|
| +std::string DecodeEvent(EventRef event) {
|
| + std::string str;
|
| + DecodeFourChar(::GetEventClass(event), &str);
|
| + str.push_back(':');
|
| + DecodeFourChar(::GetEventKind(event), &str);
|
| + return str;
|
| +}
|
| +
|
| +MacCarbonSocketServer::MacCarbonSocketServer()
|
| + : event_queue_(GetCurrentEventQueue()), wake_up_(NULL) {
|
| + VERIFY(noErr == CreateEvent(NULL, kEventClassSocketServer, kEventWakeUp, 0,
|
| + kEventAttributeUserEvent, &wake_up_));
|
| +}
|
| +
|
| +MacCarbonSocketServer::~MacCarbonSocketServer() {
|
| + if (wake_up_) {
|
| + ReleaseEvent(wake_up_);
|
| + }
|
| +}
|
| +
|
| +bool MacCarbonSocketServer::Wait(int cms, bool process_io) {
|
| + ASSERT(GetCurrentEventQueue() == event_queue_);
|
| +
|
| + // Listen to all events if we're processing I/O.
|
| + // Only listen for our wakeup event if we're not.
|
| + UInt32 num_types = 0;
|
| + const EventTypeSpec* events = NULL;
|
| + if (!process_io) {
|
| + num_types = GetEventTypeCount(kEventWakeUpSpec);
|
| + events = kEventWakeUpSpec;
|
| + }
|
| +
|
| + EventTargetRef target = GetEventDispatcherTarget();
|
| + EventTimeout timeout =
|
| + (kForever == cms) ? kEventDurationForever : cms / 1000.0;
|
| + EventTimeout end_time = GetCurrentEventTime() + timeout;
|
| +
|
| + bool done = false;
|
| + while (!done) {
|
| + EventRef event;
|
| + OSStatus result = ReceiveNextEvent(num_types, events, timeout, true,
|
| + &event);
|
| + if (noErr == result) {
|
| + if (wake_up_ != event) {
|
| + LOG_F(LS_VERBOSE) << "Dispatching event: " << DecodeEvent(event);
|
| + result = SendEventToEventTarget(event, target);
|
| + if ((noErr != result) && (eventNotHandledErr != result)) {
|
| + LOG_E(LS_ERROR, OS, result) << "SendEventToEventTarget";
|
| + }
|
| + } else {
|
| + done = true;
|
| + }
|
| + ReleaseEvent(event);
|
| + } else if (eventLoopTimedOutErr == result) {
|
| + ASSERT(cms != kForever);
|
| + done = true;
|
| + } else if (eventLoopQuitErr == result) {
|
| + // Ignore this... we get spurious quits for a variety of reasons.
|
| + LOG_E(LS_VERBOSE, OS, result) << "ReceiveNextEvent";
|
| + } else {
|
| + // Some strange error occurred. Log it.
|
| + LOG_E(LS_WARNING, OS, result) << "ReceiveNextEvent";
|
| + return false;
|
| + }
|
| + if (kForever != cms) {
|
| + timeout = end_time - GetCurrentEventTime();
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void MacCarbonSocketServer::WakeUp() {
|
| + if (!IsEventInQueue(event_queue_, wake_up_)) {
|
| + RetainEvent(wake_up_);
|
| + OSStatus result = PostEventToQueue(event_queue_, wake_up_,
|
| + kEventPriorityStandard);
|
| + if (noErr != result) {
|
| + LOG_E(LS_ERROR, OS, result) << "PostEventToQueue";
|
| + }
|
| + }
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// MacCarbonAppSocketServer
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +
|
| +MacCarbonAppSocketServer::MacCarbonAppSocketServer()
|
| + : event_queue_(GetCurrentEventQueue()) {
|
| + // Install event handler
|
| + VERIFY(noErr == InstallApplicationEventHandler(
|
| + NewEventHandlerUPP(WakeUpEventHandler), 1, kEventWakeUpSpec, this,
|
| + &event_handler_));
|
| +
|
| + // Install a timer and set it idle to begin with.
|
| + VERIFY(noErr == InstallEventLoopTimer(GetMainEventLoop(),
|
| + kEventDurationForever,
|
| + kEventDurationForever,
|
| + NewEventLoopTimerUPP(TimerHandler),
|
| + this,
|
| + &timer_));
|
| +}
|
| +
|
| +MacCarbonAppSocketServer::~MacCarbonAppSocketServer() {
|
| + RemoveEventLoopTimer(timer_);
|
| + RemoveEventHandler(event_handler_);
|
| +}
|
| +
|
| +OSStatus MacCarbonAppSocketServer::WakeUpEventHandler(
|
| + EventHandlerCallRef next, EventRef event, void *data) {
|
| + QuitApplicationEventLoop();
|
| + return noErr;
|
| +}
|
| +
|
| +void MacCarbonAppSocketServer::TimerHandler(
|
| + EventLoopTimerRef timer, void *data) {
|
| + QuitApplicationEventLoop();
|
| +}
|
| +
|
| +bool MacCarbonAppSocketServer::Wait(int cms, bool process_io) {
|
| + if (!process_io && cms == 0) {
|
| + // No op.
|
| + return true;
|
| + }
|
| + if (kForever != cms) {
|
| + // Start a timer.
|
| + OSStatus error =
|
| + SetEventLoopTimerNextFireTime(timer_, cms / 1000.0);
|
| + if (error != noErr) {
|
| + LOG(LS_ERROR) << "Failed setting next fire time.";
|
| + }
|
| + }
|
| + if (!process_io) {
|
| + // No way to listen to common modes and not get socket events, unless
|
| + // we disable each one's callbacks.
|
| + EnableSocketCallbacks(false);
|
| + }
|
| + RunApplicationEventLoop();
|
| + if (!process_io) {
|
| + // Reenable them. Hopefully this won't cause spurious callbacks or
|
| + // missing ones while they were disabled.
|
| + EnableSocketCallbacks(true);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void MacCarbonAppSocketServer::WakeUp() {
|
| + // TODO: No-op if there's already a WakeUp in flight.
|
| + EventRef wake_up;
|
| + VERIFY(noErr == CreateEvent(NULL, kEventClassSocketServer, kEventWakeUp, 0,
|
| + kEventAttributeUserEvent, &wake_up));
|
| + OSStatus result = PostEventToQueue(event_queue_, wake_up,
|
| + kEventPriorityStandard);
|
| + if (noErr != result) {
|
| + LOG_E(LS_ERROR, OS, result) << "PostEventToQueue";
|
| + }
|
| + ReleaseEvent(wake_up);
|
| +}
|
| +
|
| +#endif
|
| } // namespace rtc
|
|
|