moved the user timer (used to be known as AmSessionTimer) to the session_timer plugin.

added a multi-purpose plugin type. see also AmApi.h for details.


git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@8 8eb893ce-cfd4-0310-b710-fb5ebe64c474
sayer/1.4-spce2.6
Raphael Coeffic 21 years ago
parent 68f51feee4
commit 14c69b1672

@ -30,7 +30,7 @@
#include "AmApi.h"
#include "AmUtils.h"
#include "AmSessionScheduler.h"
#include "AmSessionTimer.h"
//#include "AmSessionTimer.h"
#include "AmPlugIn.h"
#include <unistd.h>
@ -118,7 +118,8 @@ extern "C" {
}
IvrFactory::IvrFactory(const string& _app_name)
: AmSessionFactory(_app_name)
: AmSessionFactory(_app_name),
user_timer_fact(NULL)
{
}
@ -205,12 +206,18 @@ IvrDialog* IvrFactory::newDlg(const string& name)
if(mod_it == mod_reg.end()){
ERROR("Unknown script name\n");
throw AmSession::Exception(500,"Unknown Application");
return NULL;
}
IvrScriptDesc& mod_desc = mod_it->second;
IvrDialog* dlg = new IvrDialog();
AmDynInvoke* user_timer = user_timer_fact->getInstance();
if(!user_timer){
ERROR("could not get a user timer reference\n");
throw AmSession::Exception(500,"could not get a user timer reference");
}
IvrDialog* dlg = new IvrDialog(user_timer);
PyObject* c_dlg = PyCObject_FromVoidPtr(dlg,NULL);
PyObject* dlg_inst = PyObject_CallMethod(mod_desc.dlg_class,"__new__","OO",
@ -318,6 +325,14 @@ bool IvrFactory::loadScript(const string& path)
*/
int IvrFactory::onLoad()
{
user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
if(!user_timer_fact){
ERROR("could not load user_timer from session_timer plug-in\n");
return -1;
}
AmConfigReader cfg;
if(cfg.loadFile(add2path(AmConfig::ModConfigPath,1,MOD_NAME ".conf")))
@ -403,10 +418,11 @@ AmSession* IvrFactory::onInvite(const AmSipRequest& req)
return newDlg(req.user);
}
IvrDialog::IvrDialog()
IvrDialog::IvrDialog(AmDynInvoke* user_timer)
: py_mod(NULL),
py_dlg(NULL),
playlist(this)
playlist(this),
user_timer(user_timer)
{
sip_relay_only = false;
}
@ -501,12 +517,13 @@ void IvrDialog::process(AmEvent* event)
event->processed = true;
}
AmTimeoutEvent* timeout_event = dynamic_cast<AmTimeoutEvent*>(event);
if(timeout_event && timeout_event->event_id > 0) {
AmPluginEvent* plugin_event = dynamic_cast<AmPluginEvent*>(event);
if(plugin_event && plugin_event->name == "timer_timeout") {
PYLOCK;
callPyEventHandler("onTimer", timeout_event->event_id);
callPyEventHandler("onTimer", plugin_event->data.get(0).asInt());
event->processed = true;
}
if (!event->processed)
AmB2BCallerSession::process(event);

@ -44,27 +44,21 @@ struct IvrScriptDesc
{
PyObject* mod;
PyObject* dlg_class;
// PyObject* config;
IvrScriptDesc()
: mod(0),
dlg_class(0)// ,
// config(0)
dlg_class(0)
{}
IvrScriptDesc(const IvrScriptDesc& d)
: mod(d.mod),
dlg_class(d.dlg_class)// ,
// config(d.config)
dlg_class(d.dlg_class)
{}
IvrScriptDesc(PyObject* mod,
PyObject* dlg_class// ,
// PyObject* config
)
PyObject* dlg_class)
: mod(mod),
dlg_class(dlg_class)// ,
// config(config)
dlg_class(dlg_class)
{}
};
@ -77,6 +71,8 @@ class IvrFactory: public AmSessionFactory
map<string,IvrScriptDesc> mod_reg;
AmDynInvokeFactory* user_timer_fact;
void init_python_interpreter();
void import_ivr_builtins();
@ -112,9 +108,10 @@ class IvrDialog : public AmB2BCallerSession
void process(AmEvent* event);
public:
AmDynInvoke* user_timer;
AmPlaylist playlist;
IvrDialog();
IvrDialog(AmDynInvoke* user_timer);
~IvrDialog();
// must be called before everything else.

@ -4,7 +4,7 @@
#include "IvrSipDialog.h"
#include "AmSessionTimer.h"
//#include "AmSessionTimer.h"
// Data definition
typedef struct {
@ -290,8 +290,13 @@ static PyObject* IvrDialogBase_setTimer(IvrDialogBase* self, PyObject* args)
return NULL;
}
AmSessionTimer::instance()->
setTimer(id, interval, self->p_dlg->getLocalTag());
AmArgArray di_args,ret;
di_args.push(id);
di_args.push(interval);
di_args.push(self->p_dlg->getLocalTag().c_str());
self->p_dlg->user_timer->
invoke("setTimer", di_args, ret);
Py_INCREF(Py_None);
return Py_None;
@ -310,8 +315,12 @@ static PyObject* IvrDialogBase_removeTimer(IvrDialogBase* self, PyObject* args)
return NULL;
}
AmSessionTimer::instance()->
removeTimer(id, self->p_dlg->getLocalTag());
AmArgArray di_args,ret;
di_args.push(id);
di_args.push(self->p_dlg->getLocalTag().c_str());
self->p_dlg->user_timer->
invoke("removeTimer",di_args,ret);
Py_INCREF(Py_None);
return Py_None;
@ -322,8 +331,11 @@ static PyObject* IvrDialogBase_removeTimers(IvrDialogBase* self, PyObject* args)
{
assert(self->p_dlg);
AmSessionTimer::instance()->
removeUserTimers(self->p_dlg->getLocalTag());
AmArgArray di_args,ret;
di_args.push(self->p_dlg->getLocalTag().c_str());
self->p_dlg->user_timer->
invoke("removeUserTimers",di_args,ret);
Py_INCREF(Py_None);
return Py_None;

@ -1,6 +1,7 @@
#include "IvrSipDialog.h"
#include "AmSessionTimer.h"
//#include "AmSessionTimer.h"
#include "AmSipDialog.h"
#include "log.h"
// Data definition
typedef struct {

@ -1,5 +1,5 @@
#include "IvrSipRequest.h"
#include "AmSessionTimer.h"
//#include "AmSessionTimer.h"
#include "AmSipRequest.h"
#if 0

@ -29,6 +29,19 @@
#include "log.h"
#include "AmSession.h"
AmDynInvoke::AmDynInvoke() {}
AmDynInvoke::~AmDynInvoke() {}
void AmDynInvoke::invoke(const string& method, const AmArgArray& args, AmArgArray& ret)
{
throw NotImplemented(method);
}
AmDynInvokeFactory::AmDynInvokeFactory(const string& name)
: AmPluginFactory(name)
{
}
AmSessionFactory::AmSessionFactory(const string& name)
: AmPluginFactory(name), mod_conf(AmConfig::defaultSessionTimerConfig)
{

@ -27,19 +27,36 @@
#ifndef _AmApi_h_
#define _AmApi_h_
//#include "AmRequest.h"
#include "AmThread.h"
#include "AmSipRequest.h"
#include "AmConfig.h"
#include "AmArg.h"
#include <string>
#include <map>
using std::map;
using std::string;
class AmSession;
class AmSessionEventHandler;
/**
* Multi-purpose plugin class
*/
class AmDynInvoke
{
public:
struct NotImplemented {
string what;
NotImplemented(const string& w)
: what(w) {}
};
AmDynInvoke();
virtual ~AmDynInvoke();
virtual void invoke(const string& method, const AmArgArray& args, AmArgArray& ret);
};
/**
* Base class for plugin factories
*/
class AmPluginFactory
{
string plugin_name;
@ -61,6 +78,33 @@ public:
virtual int onLoad()=0;
};
/**
* Factory for multi-purpose plugin classes
*/
class AmDynInvokeFactory: public AmPluginFactory
{
public:
AmDynInvokeFactory(const string& name);
virtual AmDynInvoke* getInstance()=0;
};
class AmSession;
class AmSessionEventHandler;
class AmSessionEventHandlerFactory: public AmPluginFactory
{
public:
AmSessionEventHandlerFactory(const string& name);
virtual AmSessionEventHandler* getHandler(AmSession*)=0;
/**
* @return true if session creation should be stopped
*/
virtual bool onInvite(const AmSipRequest& req)=0;
};
class AmSessionFactory: public AmPluginFactory
{
@ -68,11 +112,11 @@ class AmSessionFactory: public AmPluginFactory
AmSessionTimerConfig mod_conf;
protected:
/**
* This reads the module configuration from
* cfg into the modules mod_conf.
*/
int configureModule(AmConfigReader& cfg);
/**
* This reads the module configuration from
* cfg into the modules mod_conf.
*/
int configureModule(AmConfigReader& cfg);
public:
/**
@ -93,18 +137,6 @@ public:
virtual AmSession* onInvite(const AmSipRequest& req)=0;
};
class AmSessionEventHandlerFactory: public AmPluginFactory
{
public:
AmSessionEventHandlerFactory(const string& name);
virtual AmSessionEventHandler* getHandler(AmSession*)=0;
/**
* @return true if session creation should be stopped
*/
virtual bool onInvite(const AmSipRequest& req)=0;
};
#define EXPORT_FACTORY(fctname,class_name,...) \
extern "C" void* fctname()\
@ -129,6 +161,12 @@ typedef void* (*FactoryCreate)();
#define EXPORT_SESSION_EVENT_HANDLER_FACTORY(class_name,app_name) \
EXPORT_FACTORY(FACTORY_SESSION_EVENT_HANDLER_EXPORT,class_name,app_name)
#define FACTORY_PLUGIN_CLASS_EXPORT plugin_class_create
#define FACTORY_PLUGIN_CLASS_EXPORT_STR XSTR(FACTORY_PLUGIN_CLASS_EXPORT)
#define EXPORT_PLUGIN_CLASS_FACTORY(class_name,app_name) \
EXPORT_FACTORY(FACTORY_PLUGIN_CLASS_EXPORT,class_name,app_name)
#endif
// Local Variables:
// mode:C++

@ -0,0 +1,88 @@
#ifndef _AmArg_h_
#define _AmArg_h_
#include <assert.h>
#include <vector>
using std::vector;
class AmArg
{
public:
// type enum
enum {
Undef=0,
Int,
Double,
CStr
};
private:
// type
short type;
// value
union {
int v_int;
double v_double;
const char* v_cstr;
};
public:
AmArg(const AmArg& v)
: type(v.type){
switch(type){
case Int: v_int = v.v_int; break;
case Double: v_double = v.v_double; break;
case CStr: v_cstr = v.v_cstr; break;
default: assert(0);
}
}
AmArg(const int& v)
: type(Int),
v_int(v)
{}
AmArg(const double& v)
: type(Double),
v_double(v)
{}
AmArg(const char* v)
: type(CStr),
v_cstr(v)
{}
short getType() const { return type; }
int asInt() const { return v_int; }
double asDouble() const { return v_double; }
const char* asCStr() const { return v_cstr; }
};
class AmArgArray
{
vector<AmArg> v;
public:
AmArgArray() : v() {}
AmArgArray(const AmArgArray& a) : v(a.v) {}
void push(const AmArg& a){
v.push_back(a);
}
const AmArg& get(size_t idx) const {
assert(idx < v.size());
return v[idx];
}
size_t size() { return v.size(); }
};
#endif

@ -1,6 +1,13 @@
#ifndef AmEvent_h
#define AmEvent_h
#include "AmArg.h"
#include <string>
using std::string;
#define E_PLUGIN 100
struct AmEvent
{
int event_id;
@ -10,6 +17,20 @@ struct AmEvent
virtual ~AmEvent();
};
struct AmPluginEvent: public AmEvent
{
string name;
AmArgArray data;
AmPluginEvent(const string& n)
: AmEvent(E_PLUGIN), name(n), data() {}
AmPluginEvent(const string& n, const AmArgArray& d)
: AmEvent(E_PLUGIN), name(n), data(d) {}
};
class AmEventHandler
{
public:

@ -123,6 +123,13 @@ int AmPlugIn::load(const string& directory)
if(err)
break;
}
for(map<string,AmDynInvokeFactory*>::iterator it = name2di.begin();
it != name2di.end(); it++){
err = it->second->onLoad();
if(err)
break;
}
map<string,AmSessionFactory*> apps(name2app);
for(map<string,AmSessionFactory*>::iterator it = apps.begin();
@ -149,6 +156,7 @@ int AmPlugIn::loadPlugIn(const string& file)
FactoryCreate fc = NULL;
amci_exports_t* exports = (amci_exports_t*)dlsym(h_dl,"amci_exports");
bool has_sym=false;
if(exports){
if(loadAudioPlugIn(exports))
goto error;
@ -158,12 +166,20 @@ int AmPlugIn::loadPlugIn(const string& file)
if((fc = (FactoryCreate)dlsym(h_dl,FACTORY_SESSION_EXPORT_STR)) != NULL){
if(loadAppPlugIn((AmPluginFactory*)fc()))
goto error;
has_sym=true;
}
else if((fc = (FactoryCreate)dlsym(h_dl,FACTORY_SESSION_EVENT_HANDLER_EXPORT_STR)) != NULL){
if((fc = (FactoryCreate)dlsym(h_dl,FACTORY_SESSION_EVENT_HANDLER_EXPORT_STR)) != NULL){
if(loadSehPlugIn((AmPluginFactory*)fc()))
goto error;
has_sym=true;
}
else {
if((fc = (FactoryCreate)dlsym(h_dl,FACTORY_PLUGIN_CLASS_EXPORT_STR)) != NULL){
if(loadDiPlugIn((AmPluginFactory*)fc()))
goto error;
has_sym=true;
}
if(!has_sym){
ERROR("Plugin type could not be detected (%s)(%s)\n",file.c_str(),dlerror());
goto error;
}
@ -251,6 +267,14 @@ AmSessionEventHandlerFactory* AmPlugIn::getFactory4Seh(const string& name)
return 0;
}
AmDynInvokeFactory* AmPlugIn::getFactory4Di(const string& name)
{
map<string,AmDynInvokeFactory*>::iterator it = name2di.find(name);
if(it != name2di.end())
return it->second;
return 0;
}
int AmPlugIn::loadAudioPlugIn(amci_exports_t* exports)
{
if(!exports){
@ -299,13 +323,8 @@ int AmPlugIn::loadAppPlugIn(AmPluginFactory* f)
goto error;
}
//if(!sf->onLoad()){
name2app.insert(std::make_pair(sf->getName(),sf));
DBG("application '%s' loaded.\n",sf->getName().c_str());
// }
// else {
// goto error;
// }
name2app.insert(std::make_pair(sf->getName(),sf));
DBG("application '%s' loaded.\n",sf->getName().c_str());
return 0;
@ -326,13 +345,30 @@ int AmPlugIn::loadSehPlugIn(AmPluginFactory* f)
goto error;
}
// if(!sf->onLoad()){
name2seh.insert(std::make_pair(sf->getName(),sf));
DBG("session component '%s' loaded.\n",sf->getName().c_str());
// }
// else {
// goto error;
// }
name2seh.insert(std::make_pair(sf->getName(),sf));
DBG("session component '%s' loaded.\n",sf->getName().c_str());
return 0;
error:
return -1;
}
int AmPlugIn::loadDiPlugIn(AmPluginFactory* f)
{
AmDynInvokeFactory* sf = dynamic_cast<AmDynInvokeFactory*>(f);
if(!sf){
ERROR("invalid component plug-in!\n");
goto error;
}
if(name2di.find(sf->getName()) != name2di.end()){
ERROR("component '%s' already loaded !\n",sf->getName().c_str());
goto error;
}
name2di.insert(std::make_pair(sf->getName(),sf));
DBG("component '%s' loaded.\n",sf->getName().c_str());
return 0;

@ -38,6 +38,7 @@ using std::vector;
class AmPluginFactory;
class AmSessionFactory;
class AmSessionEventHandlerFactory;
class AmDynInvokeFactory;
struct amci_exports_t;
struct amci_codec_t;
@ -67,6 +68,7 @@ private:
map<string,AmSessionFactory*> name2app;
map<string,AmSessionEventHandlerFactory*> name2seh;
map<string,AmDynInvokeFactory*> name2di;
int dynamic_pl; // range: 96->127, see RFC 1890
@ -78,6 +80,7 @@ private:
int loadAudioPlugIn(amci_exports_t* exports);
int loadAppPlugIn(AmPluginFactory* cb);
int loadSehPlugIn(AmPluginFactory* cb);
int loadDiPlugIn(AmPluginFactory* cb);
int addCodec(amci_codec_t* c);
int addPayload(amci_payload_t* p);
@ -136,6 +139,11 @@ private:
*/
AmSessionEventHandlerFactory* getFactory4Seh(const string& name);
/**
* Dynamic invokation component
*/
AmDynInvokeFactory* getFactory4Di(const string& name);
/** @return true if this record has been inserted. */
bool registerFactory4App(const string& app_name, AmSessionFactory* f);
};

@ -38,7 +38,7 @@
#include "AmSessionScheduler.h"
#include "AmDtmfDetector.h"
/* Session Timer: -ssa */
#include "AmSessionTimer.h"
//#include "AmSessionTimer.h"
#include "log.h"
@ -315,7 +315,7 @@ void AmSession::run()
}
}
// remove pending timers
AmSessionTimer::instance()->removeTimers(getLocalTag());
//AmSessionTimer::instance()->removeTimers(getLocalTag());
}
catch(const AmSession::Exception& e){ throw e; }
catch(const string& str){
@ -555,10 +555,10 @@ int AmSession::acceptAudio(const AmSipRequest& req)
return -1;
}
string AmSession::SessionTimerException::getErrorHeaders() const {
return "Min-SE:" + int2str(minSE) + "\n"
+ "Supported: timer\n";
}
// string AmSession::SessionTimerException::getErrorHeaders() const {
// return "Min-SE:" + int2str(minSE) + "\n"
// + "Supported: timer\n";
// }
void AmSession::onSendRequest(const string& method, const string& content_type,
const string& body, string& hdrs)

@ -53,13 +53,6 @@ class AmSessionFactory;
//class AmDialogState;
class AmDtmfEvent;
/* Session Timer: -ssa */
class AmTimeoutEvent;
// these are the timer IDs for session timer
// Caution: do not use these for other purposes
#define ID_SESSION_INTERVAL_TIMER -1
#define ID_SESSION_REFRESH_TIMER -2
/**
* Signaling plugins must inherite from this class.
@ -153,15 +146,15 @@ public:
Exception(int c, string r) : code(c), reason(r) {}
};
struct SessionTimerException : Exception {
unsigned int minSE;
// struct SessionTimerException : Exception {
// unsigned int minSE;
SessionTimerException(unsigned int min_SE)
: Exception(422, "Session Interval Too Small"),
minSE(min_SE) { }
// SessionTimerException(unsigned int min_SE)
// : Exception(422, "Session Interval Too Small"),
// minSE(min_SE) { }
string getErrorHeaders() const;
};
// string getErrorHeaders() const;
// };
/**
* Session constructor.

@ -185,10 +185,10 @@ void AmSessionContainer::startSessionUAS(AmSipRequest& req)
//throw AmSession::Exception(500,"internal error");
}
}
catch(const AmSession::SessionTimerException& e){
ERROR("%i %s\n",e.code,e.reason.c_str());
AmSipDialog::reply_error(req,e.code,e.reason,e.getErrorHeaders());
}
// catch(const AmSession::SessionTimerException& e){
// ERROR("%i %s\n",e.code,e.reason.c_str());
// AmSipDialog::reply_error(req,e.code,e.reason,e.getErrorHeaders());
// }
catch(const AmSession::Exception& e){
ERROR("%i %s\n",e.code,e.reason.c_str());
AmSipDialog::reply_error(req,e.code,e.reason);

@ -56,8 +56,6 @@ int EchoFactory::onLoad()
AmSession* EchoFactory::onInvite(const AmSipRequest& req)
{
// if()
AmSession* s = new EchoDialog();
s->addHandler(session_timer_f->getHandler(s));

@ -1,6 +1,6 @@
#include "SessionTimer.h"
#include "AmUtils.h"
#include "AmSessionTimer.h"
#include "UserTimer.h"
EXPORT_SESSION_EVENT_HANDLER_FACTORY(SessionTimerFactory, MOD_NAME);
@ -34,7 +34,7 @@ bool SessionTimer::process(AmEvent* ev)
/* Session Timer: -ssa */
AmTimeoutEvent* timeout_ev = dynamic_cast<AmTimeoutEvent*>(ev);
if (timeout_ev) {
DBG("received timeout Event with ID %d\n", ev->event_id);
DBG("received timeout Event with ID %d\n", timeout_ev->data.get(0).asInt());
onTimeoutEvent(timeout_ev);
return true;
}
@ -264,23 +264,23 @@ void SessionTimer::setTimers(AmSession* s)
DBG("Setting session interval timer: %ds, tag '%s'\n", session_interval,
s->getLocalTag().c_str());
AmSessionTimer::instance()->
UserTimer::instance()->
setTimer(ID_SESSION_INTERVAL_TIMER, session_interval, s->getLocalTag());
// set session refresh action timer, after half the expiration
if (session_refresher == refresh_local) {
DBG("Setting session refresh timer: %ds, tag '%s'\n", session_interval/2,
s->getLocalTag().c_str());
AmSessionTimer::instance()->
setTimer(ID_SESSION_REFRESH_TIMER, session_interval/2, s->getLocalTag());
DBG("Setting session refresh timer: %ds, tag '%s'\n", session_interval/2,
s->getLocalTag().c_str());
UserTimer::instance()->
setTimer(ID_SESSION_REFRESH_TIMER, session_interval/2, s->getLocalTag());
}
}
void SessionTimer::removeTimers(AmSession* s)
{
AmSessionTimer::instance()->
UserTimer::instance()->
removeTimer(ID_SESSION_REFRESH_TIMER, s->getLocalTag());
AmSessionTimer::instance()->
UserTimer::instance()->
removeTimer(ID_SESSION_INTERVAL_TIMER, s->getLocalTag());
}
@ -288,13 +288,14 @@ void SessionTimer::onTimeoutEvent(AmTimeoutEvent* timeout_ev)
{
// if (!session_timer_conf.getEnableSessionTimer())
// return;
if (timeout_ev->event_id == ID_SESSION_REFRESH_TIMER) {
int timer_id = timeout_ev->data.get(0).asInt();
if (timer_id == ID_SESSION_REFRESH_TIMER) {
if (session_refresher == refresh_local)
s->sendReinvite();
else
WARN("need session refresh but remote session is refresher\n");
} else if (timeout_ev->event_id == ID_SESSION_INTERVAL_TIMER) {
} else if (timer_id == ID_SESSION_INTERVAL_TIMER) {
// // let the session know it got timeout
// onTimeout();

@ -6,6 +6,14 @@
#define MOD_NAME "session_timer"
/* Session Timer: -ssa */
class AmTimeoutEvent;
// these are the timer IDs for session timer
// Caution: do not use these for other purposes
#define ID_SESSION_INTERVAL_TIMER -1
#define ID_SESSION_REFRESH_TIMER -2
class SessionTimerFactory: public AmSessionEventHandlerFactory
{
bool checkSessionExpires(const AmSipRequest& req);

@ -1,37 +1,64 @@
#include "AmSessionTimer.h"
#include "UserTimer.h"
#include <sys/time.h>
#define SESSION_TIMER_GRANULARITY 100 // check every 100 millisec
class UserTimerFactory: public AmDynInvokeFactory
{
public:
UserTimerFactory(const string& name)
: AmDynInvokeFactory(name) {}
AmDynInvoke* getInstance(){
return UserTimer::instance();
}
int onLoad(){
#ifdef SESSION_TIMER_THREAD
UserTimer::instance()->start();
#endif
return 0;
}
};
EXPORT_PLUGIN_CLASS_FACTORY(UserTimerFactory,"user_timer");
AmTimeoutEvent::AmTimeoutEvent(int timer_id)
: AmPluginEvent(TIMEOUTEVENT_NAME)
{
data.push(AmArg(timer_id));
}
AmSessionTimer::AmSessionTimer()
UserTimer::UserTimer()
{
}
AmSessionTimer::~AmSessionTimer()
UserTimer::~UserTimer()
{
}
AmSessionTimer* AmSessionTimer::_instance=0;
UserTimer* UserTimer::_instance=0;
AmSessionTimer* AmSessionTimer::instance()
UserTimer* UserTimer::instance()
{
if(!_instance)
_instance = new AmSessionTimer();
_instance = new UserTimer();
return _instance;
}
#ifdef SESSION_TIMER_THREAD
void AmSessionTimer::run() {
void UserTimer::run() {
while(1){
usleep(SESSION_TIMER_GRANULARITY * 1000);
checkTimers();
}
}
void AmSessionTimer::on_stop() {
void UserTimer::on_stop() {
}
#endif // SESSION_TIMER_THREAD
@ -45,7 +72,7 @@ bool operator == (const AmTimer& l, const AmTimer& r)
return l.id == r.id;
}
void AmSessionTimer::checkTimers() {
void UserTimer::checkTimers() {
timers_mut.lock();
if(timers.empty()){
timers_mut.unlock();
@ -68,7 +95,9 @@ void AmSessionTimer::checkTimers() {
new AmTimeoutEvent(id))) {
DBG("Timeout Event could not be posted, session does not exist any more.\n");
}
else {
DBG("Timeout Event could be posted.\n");
}
if(timers.empty()) break;
it = timers.begin();
@ -76,7 +105,7 @@ void AmSessionTimer::checkTimers() {
timers_mut.unlock();
}
void AmSessionTimer::setTimer(int id, int seconds, const string& session_id) {
void UserTimer::setTimer(int id, int seconds, const string& session_id) {
struct timeval tval;
gettimeofday(&tval,NULL);
@ -84,7 +113,7 @@ void AmSessionTimer::setTimer(int id, int seconds, const string& session_id) {
setTimer(id, &tval, session_id);
}
void AmSessionTimer::setTimer(int id, struct timeval* t,
void UserTimer::setTimer(int id, struct timeval* t,
const string& session_id)
{
timers_mut.lock();
@ -99,13 +128,13 @@ void AmSessionTimer::setTimer(int id, struct timeval* t,
}
void AmSessionTimer::removeTimer(int id, const string& session_id) {
void UserTimer::removeTimer(int id, const string& session_id) {
timers_mut.lock();
unsafe_removeTimer(id, session_id);
timers_mut.unlock();
}
void AmSessionTimer::unsafe_removeTimer(int id, const string& session_id)
void UserTimer::unsafe_removeTimer(int id, const string& session_id)
{
// erase old timer if exists
set<AmTimer>::iterator it = timers.begin();
@ -118,7 +147,7 @@ void AmSessionTimer::unsafe_removeTimer(int id, const string& session_id)
}
}
void AmSessionTimer::removeTimers(const string& session_id) {
void UserTimer::removeTimers(const string& session_id) {
// DBG("removing timers for <%s>\n", session_id.c_str());
timers_mut.lock();
for (set<AmTimer>::iterator it = timers.begin();
@ -131,7 +160,7 @@ void AmSessionTimer::removeTimers(const string& session_id) {
timers_mut.unlock();
}
void AmSessionTimer::removeUserTimers(const string& session_id) {
void UserTimer::removeUserTimers(const string& session_id) {
// DBG("removing User timers for <%s>\n", session_id.c_str());
timers_mut.lock();
for (set<AmTimer>::iterator it = timers.begin();
@ -143,3 +172,21 @@ void AmSessionTimer::removeUserTimers(const string& session_id) {
}
timers_mut.unlock();
}
void UserTimer::invoke(const string& method, const AmArgArray& args, AmArgArray& ret)
{
if(method == "setTimer"){
setTimer(args.get(0).asInt(),
args.get(1).asInt(),
args.get(2).asCStr());
}
else if(method == "removeTimer"){
removeTimer(args.get(0).asInt(),
args.get(1).asCStr());
}
else if(method == "removeUserTimers"){
removeUserTimers(args.get(0).asCStr());
}
else
throw AmDynInvoke::NotImplemented(method);
}

@ -1,4 +1,3 @@
/*
* Timer class with seconds granularity
*/
@ -19,12 +18,24 @@
#include <set>
class AmTimeoutEvent : public AmEvent {
/**
* Timer Event: Name
*/
#define TIMEOUTEVENT_NAME "timer_timeout"
/**
* Timer Event: class
* data[0]: int timer_id
*/
class AmTimeoutEvent : public AmPluginEvent
{
public:
AmTimeoutEvent(int timer_id)
: AmEvent(timer_id) { }
AmTimeoutEvent(int timer_id);
};
/**
* Timer struct containing the alarm time.
*/
struct AmTimer
{
int id;
@ -46,22 +57,22 @@ bool operator == (const AmTimer& l, const AmTimer& r);
* Implements a timer with session granularity.
* On timeout an AmTimeoutEvent with the ID is posted.
*/
class AmSessionTimer
class UserTimer: public AmDynInvoke
#ifdef SESSION_TIMER_THREAD
: public AmThread
,public AmThread
#endif
{
static AmSessionTimer* _instance;
static UserTimer* _instance;
std::set<AmTimer> timers;
AmMutex timers_mut;
void unsafe_removeTimer(int id, const string& session_id);
public:
AmSessionTimer();
~AmSessionTimer();
UserTimer();
~UserTimer();
static AmSessionTimer* instance();
static UserTimer* instance();
/** set timer with ID id, fire after s seconds event in
session session_id */
@ -84,6 +95,8 @@ class AmSessionTimer
void run();
void on_stop();
#endif
void invoke(const string& method, const AmArgArray& args, AmArgArray& ret);
};
#endif //AM_SESSION_TIMER_H

@ -38,7 +38,7 @@
#include "AmSessionScheduler.h"
#include "AmIcmpWatcher.h"
#include "AmRtpReceiver.h"
#include "AmSessionTimer.h"
//#include "AmSessionTimer.h"
#include "log.h"
@ -412,8 +412,8 @@ int main(int argc, char* argv[])
DBG("Starting RTP receiver\n");
AmRtpReceiver::instance()->start();
DBG("Starting Session Timer\n");
AmSessionTimer::instance()->start();
//DBG("Starting Session Timer\n");
//AmSessionTimer::instance()->start();
//DBG("Starting ICMP watcher\n");
//AmIcmpWatcher::instance()->start();

Loading…
Cancel
Save