1 // Copyright 2007, Google Inc. 2 3 #ifndef TALK_BASE_MACSOCKETSERVER_H__ 4 #define TALK_BASE_MACSOCKETSERVER_H__ 5 6 #include <set> 7 #ifdef OSX // Invalid on IOS 8 #include <Carbon/Carbon.h> 9 #endif 10 #include "talk/base/physicalsocketserver.h" 11 12 namespace talk_base { 13 14 /////////////////////////////////////////////////////////////////////////////// 15 // MacBaseSocketServer 16 /////////////////////////////////////////////////////////////////////////////// 17 class MacAsyncSocket; 18 19 class MacBaseSocketServer : public PhysicalSocketServer { 20 public: 21 MacBaseSocketServer(); 22 virtual ~MacBaseSocketServer(); 23 24 // SocketServer Interface CreateSocket(int type)25 virtual Socket* CreateSocket(int type) { return NULL; } CreateSocket(int family,int type)26 virtual Socket* CreateSocket(int family, int type) { return NULL; } 27 28 virtual AsyncSocket* CreateAsyncSocket(int type); 29 virtual AsyncSocket* CreateAsyncSocket(int family, int type); 30 31 virtual bool Wait(int cms, bool process_io) = 0; 32 virtual void WakeUp() = 0; 33 34 void RegisterSocket(MacAsyncSocket* socket); 35 void UnregisterSocket(MacAsyncSocket* socket); 36 37 // PhysicalSocketServer Overrides 38 virtual bool SetPosixSignalHandler(int signum, void (*handler)(int)); 39 40 protected: 41 void EnableSocketCallbacks(bool enable); sockets()42 const std::set<MacAsyncSocket*>& sockets() { 43 return sockets_; 44 } 45 46 private: 47 static void FileDescriptorCallback(CFFileDescriptorRef ref, 48 CFOptionFlags flags, 49 void* context); 50 51 std::set<MacAsyncSocket*> sockets_; 52 }; 53 54 // Core Foundation implementation of the socket server. While idle it 55 // will run the current CF run loop. When the socket server has work 56 // to do the run loop will be paused. Does not support Carbon or Cocoa 57 // UI interaction. 58 class MacCFSocketServer : public MacBaseSocketServer { 59 public: 60 MacCFSocketServer(); 61 virtual ~MacCFSocketServer(); 62 63 // SocketServer Interface 64 virtual bool Wait(int cms, bool process_io); 65 virtual void WakeUp(); 66 void OnWakeUpCallback(); 67 68 private: 69 CFRunLoopRef run_loop_; 70 CFRunLoopSourceRef wake_up_; 71 }; 72 73 #ifdef OSX 74 75 /////////////////////////////////////////////////////////////////////////////// 76 // MacCarbonSocketServer 77 /////////////////////////////////////////////////////////////////////////////// 78 79 // Interacts with the Carbon event queue. While idle it will block, 80 // waiting for events. When the socket server has work to do, it will 81 // post a 'wake up' event to the queue, causing the thread to exit the 82 // event loop until the next call to Wait. Other events are dispatched 83 // to their target. Supports Carbon and Cocoa UI interaction. 84 class MacCarbonSocketServer : public MacBaseSocketServer { 85 public: 86 MacCarbonSocketServer(); 87 virtual ~MacCarbonSocketServer(); 88 89 // SocketServer Interface 90 virtual bool Wait(int cms, bool process_io); 91 virtual void WakeUp(); 92 93 private: 94 EventQueueRef event_queue_; 95 EventRef wake_up_; 96 }; 97 98 /////////////////////////////////////////////////////////////////////////////// 99 // MacCarbonAppSocketServer 100 /////////////////////////////////////////////////////////////////////////////// 101 102 // Runs the Carbon application event loop on the current thread while 103 // idle. When the socket server has work to do, it will post an event 104 // to the queue, causing the thread to exit the event loop until the 105 // next call to Wait. Other events are automatically dispatched to 106 // their target. 107 class MacCarbonAppSocketServer : public MacBaseSocketServer { 108 public: 109 MacCarbonAppSocketServer(); 110 virtual ~MacCarbonAppSocketServer(); 111 112 // SocketServer Interface 113 virtual bool Wait(int cms, bool process_io); 114 virtual void WakeUp(); 115 116 private: 117 static OSStatus WakeUpEventHandler(EventHandlerCallRef next, EventRef event, 118 void *data); 119 static void TimerHandler(EventLoopTimerRef timer, void *data); 120 121 EventQueueRef event_queue_; 122 EventHandlerRef event_handler_; 123 EventLoopTimerRef timer_; 124 }; 125 126 #endif 127 128 /////////////////////////////////////////////////////////////////////////////// 129 // MacNotificationsSocketServer 130 /////////////////////////////////////////////////////////////////////////////// 131 132 // The name "SocketServer" is misleading for this class. This class inherits 133 // from SocketServer, some variants of which create/use physical sockets 134 // (specifically, PhysicalSocketServer). But generally, this class is a way for 135 // a thread to schedule tasks (see task.h, thread.h and taskrunner.h). 136 // 137 // Since we don't want to write a custom Cocoa event loop, we will use this 138 // in a non-standard way. The "Wait" method will never actually wait - it will 139 // return false if cms > 0. Whenever a task needs to be woken up, the WakeUp 140 // method here will get called, and will cause the thread to cycle through all 141 // messages currently available. 142 143 class MacNotificationsSocketServer : public SocketServer { 144 public: 145 MacNotificationsSocketServer(); 146 virtual ~MacNotificationsSocketServer(); 147 148 // SocketServer Interface CreateSocket(int type)149 virtual Socket* CreateSocket(int type) { return NULL; } CreateAsyncSocket(int type)150 virtual AsyncSocket* CreateAsyncSocket(int type) { return NULL; } 151 // process_io argument is ignored. 152 virtual bool Wait(int cms, bool process_io); 153 virtual void WakeUp(); 154 155 private: 156 static void NotificationCallBack(CFNotificationCenterRef center, 157 void* observer, 158 CFStringRef name, 159 const void* object, 160 CFDictionaryRef userInfo); 161 162 bool sent_notification_; 163 }; 164 165 /////////////////////////////////////////////////////////////////////////////// 166 167 } // namespace talk_base 168 169 #endif // TALK_BASE_MACSOCKETSERVER_H__ 170