1 /* 2 * (c) 2007 iptego GmbH 3 * 4 * This file is part of SEMS, a free SIP media server. 5 * 6 * SEMS is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. This program is released under 10 * the GPL with the additional exemption that compiling, linking, 11 * and/or using OpenSSL is allowed. 12 * 13 * For a license to use the SEMS software under conditions 14 * other than those described here, or to purchase support for this 15 * software, please contact iptel.org by e-mail at the following addresses: 16 * info@iptel.org 17 * 18 * SEMS is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 */ 27 /** @file AmCallWatcher.h */ 28 #ifndef _AM_CALL_WATCHER_H 29 #define _AM_CALL_WATCHER_H 30 31 // 32 // States are put into map on an Initialize event. 33 // States are held in a map identified by call_id 34 // (opaque identifier) and updated with Update events. 35 // Once an Obsolete event is received, the states are 36 // moved to soft-state map, where they are held until 37 // queried to a maximum of WATCHER_SOFT_EXPIRE_SECONDS 38 39 #define WATCHER_SOFT_EXPIRE_SECONDS 5 40 41 #include <string> 42 using std::string; 43 44 #include <map> 45 46 #include <utility> 47 using std::pair; 48 49 #include "AmEventQueue.h" 50 #include "AmEvent.h" 51 #include "AmThread.h" 52 53 class CallStatus; 54 55 /** 56 * \brief event that carries out call status update 57 */ 58 class CallStatusUpdateEvent : public AmEvent { 59 string call_id; 60 61 CallStatus* init_status; 62 63 public: 64 enum UpdateType { 65 Initialize = 0, 66 Update, 67 Obsolete 68 }; 69 CallStatusUpdateEvent(UpdateType t,const string & call_id)70 CallStatusUpdateEvent(UpdateType t, const string& call_id) 71 : AmEvent(t), call_id(call_id) { } 72 73 // implicit: initialize CallStatusUpdateEvent(const string & call_id,CallStatus * init_status)74 CallStatusUpdateEvent(const string& call_id, CallStatus* init_status) 75 : AmEvent(Initialize), call_id(call_id), init_status(init_status) { } 76 ~CallStatusUpdateEvent()77 ~CallStatusUpdateEvent() { } 78 get_call_id()79 string get_call_id() { return call_id; } get_init_status()80 CallStatus* get_init_status() { return init_status; } 81 }; 82 83 /** 84 * \brief interface for an update-able call status (AmCallWatcher) 85 */ 86 class CallStatus 87 { 88 public: CallStatus()89 CallStatus() { } ~CallStatus()90 virtual ~CallStatus() { } 91 92 /** update from an event */ 93 virtual void update(CallStatusUpdateEvent* e) = 0; 94 95 /** get a copy of self with relevant data */ 96 virtual CallStatus* copy() = 0; dump()97 virtual void dump() { } 98 }; 99 100 class AmCallWatcherGarbageCollector; 101 /** 102 * \brief manages call status to be queried by external processes 103 * call watcher is an entity for managing call status 104 * via events that change status. Events are executed in a 105 * separate thread serially by processing the event queue, 106 * so synchronous status queries do not block the thread 107 * reporting the status change. 108 */ 109 class AmCallWatcher 110 : public AmThread, 111 public AmEventQueue, 112 public AmEventHandler 113 { 114 public: 115 typedef std::map<string, CallStatus*> CallStatusMap; 116 typedef std::map<string, pair<CallStatus*, time_t> > CallStatusTimedMap; 117 118 private: 119 CallStatusMap states; 120 AmMutex states_mut; 121 122 123 CallStatusTimedMap soft_states; 124 AmMutex soft_states_mut; 125 AmCallWatcherGarbageCollector* garbage_collector; 126 127 public: 128 AmCallWatcher(); 129 ~AmCallWatcher(); 130 131 // thread 132 void run(); 133 void on_stop(); 134 135 // eventhandler 136 void process(AmEvent*); 137 138 CallStatus* getStatus(const string& call_id); 139 140 // dump all states 141 void dump(); 142 }; 143 144 /** 145 * \brief garbage collector for the AmCallWatcher 146 * 147 * checks garbage every two seconds. 148 * A bit inefficient with two threads, but AmCallWatcher 149 * shouldn't be blocked by event. 150 */ 151 class AmCallWatcherGarbageCollector 152 : public AmThread 153 { 154 AmMutex& mut; 155 AmCallWatcher::CallStatusTimedMap& garbage; 156 public: AmCallWatcherGarbageCollector(AmMutex & mut,AmCallWatcher::CallStatusTimedMap & garbage)157 AmCallWatcherGarbageCollector(AmMutex& mut, 158 AmCallWatcher::CallStatusTimedMap& garbage) 159 : mut(mut), garbage(garbage) {} 160 void run(); on_stop()161 void on_stop() { } 162 }; 163 164 #endif 165