diff --git a/apps/ivr/Ivr.cpp b/apps/ivr/Ivr.cpp index 5e0d3484..5215d4d8 100644 --- a/apps/ivr/Ivr.cpp +++ b/apps/ivr/Ivr.cpp @@ -30,7 +30,7 @@ #include "AmApi.h" #include "AmUtils.h" #include "AmSessionScheduler.h" -#include "AmSessionTimer.h" +//#include "AmSessionTimer.h" #include "AmPlugIn.h" #include @@ -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(event); - if(timeout_event && timeout_event->event_id > 0) { + AmPluginEvent* plugin_event = dynamic_cast(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); diff --git a/apps/ivr/Ivr.h b/apps/ivr/Ivr.h index 0d8d46f4..08c221f1 100644 --- a/apps/ivr/Ivr.h +++ b/apps/ivr/Ivr.h @@ -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 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. diff --git a/apps/ivr/IvrDialogBase.cpp b/apps/ivr/IvrDialogBase.cpp index 804260a3..41d391e7 100644 --- a/apps/ivr/IvrDialogBase.cpp +++ b/apps/ivr/IvrDialogBase.cpp @@ -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; diff --git a/apps/ivr/IvrSipDialog.cpp b/apps/ivr/IvrSipDialog.cpp index f5fb946a..eae2bfe2 100644 --- a/apps/ivr/IvrSipDialog.cpp +++ b/apps/ivr/IvrSipDialog.cpp @@ -1,6 +1,7 @@ #include "IvrSipDialog.h" -#include "AmSessionTimer.h" +//#include "AmSessionTimer.h" #include "AmSipDialog.h" +#include "log.h" // Data definition typedef struct { diff --git a/apps/ivr/IvrSipRequest.cpp b/apps/ivr/IvrSipRequest.cpp index 98d9ee04..100decc4 100644 --- a/apps/ivr/IvrSipRequest.cpp +++ b/apps/ivr/IvrSipRequest.cpp @@ -1,5 +1,5 @@ #include "IvrSipRequest.h" -#include "AmSessionTimer.h" +//#include "AmSessionTimer.h" #include "AmSipRequest.h" #if 0 diff --git a/core/AmApi.cpp b/core/AmApi.cpp index e12d52e8..909b4fef 100644 --- a/core/AmApi.cpp +++ b/core/AmApi.cpp @@ -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) { diff --git a/core/AmApi.h b/core/AmApi.h index 79bbbd64..265181dd 100644 --- a/core/AmApi.h +++ b/core/AmApi.h @@ -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 #include 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++ diff --git a/core/AmArg.h b/core/AmArg.h new file mode 100644 index 00000000..fb0157ce --- /dev/null +++ b/core/AmArg.h @@ -0,0 +1,88 @@ +#ifndef _AmArg_h_ +#define _AmArg_h_ + +#include + +#include +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 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 diff --git a/core/AmEvent.h b/core/AmEvent.h index 334afc34..70b6de27 100644 --- a/core/AmEvent.h +++ b/core/AmEvent.h @@ -1,6 +1,13 @@ #ifndef AmEvent_h #define AmEvent_h +#include "AmArg.h" + +#include +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: diff --git a/core/AmPlugIn.cpp b/core/AmPlugIn.cpp index 0205e56a..9b33970e 100644 --- a/core/AmPlugIn.cpp +++ b/core/AmPlugIn.cpp @@ -123,6 +123,13 @@ int AmPlugIn::load(const string& directory) if(err) break; } + + for(map::iterator it = name2di.begin(); + it != name2di.end(); it++){ + err = it->second->onLoad(); + if(err) + break; + } map apps(name2app); for(map::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::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(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; diff --git a/core/AmPlugIn.h b/core/AmPlugIn.h index 49175ead..c85b5e2f 100644 --- a/core/AmPlugIn.h +++ b/core/AmPlugIn.h @@ -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 name2app; map name2seh; + map 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); }; diff --git a/core/AmSession.cpp b/core/AmSession.cpp index 922a6370..057c7c7f 100644 --- a/core/AmSession.cpp +++ b/core/AmSession.cpp @@ -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) diff --git a/core/AmSession.h b/core/AmSession.h index ddb90768..10b297b5 100644 --- a/core/AmSession.h +++ b/core/AmSession.h @@ -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. diff --git a/core/AmSessionContainer.cpp b/core/AmSessionContainer.cpp index df433e35..18569f03 100644 --- a/core/AmSessionContainer.cpp +++ b/core/AmSessionContainer.cpp @@ -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); diff --git a/core/plug-in/echo/Echo.cpp b/core/plug-in/echo/Echo.cpp index b1b0ba33..72a3cf88 100644 --- a/core/plug-in/echo/Echo.cpp +++ b/core/plug-in/echo/Echo.cpp @@ -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)); diff --git a/core/plug-in/session_timer/SessionTimer.cpp b/core/plug-in/session_timer/SessionTimer.cpp index df0fffd1..4630656b 100644 --- a/core/plug-in/session_timer/SessionTimer.cpp +++ b/core/plug-in/session_timer/SessionTimer.cpp @@ -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(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(); diff --git a/core/plug-in/session_timer/SessionTimer.h b/core/plug-in/session_timer/SessionTimer.h index fcf9dd18..1421786c 100644 --- a/core/plug-in/session_timer/SessionTimer.h +++ b/core/plug-in/session_timer/SessionTimer.h @@ -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); diff --git a/core/AmSessionTimer.cpp b/core/plug-in/session_timer/UserTimer.cpp similarity index 60% rename from core/AmSessionTimer.cpp rename to core/plug-in/session_timer/UserTimer.cpp index d0bb30e3..b43954e7 100644 --- a/core/AmSessionTimer.cpp +++ b/core/plug-in/session_timer/UserTimer.cpp @@ -1,37 +1,64 @@ -#include "AmSessionTimer.h" +#include "UserTimer.h" #include #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::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::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::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); +} diff --git a/core/AmSessionTimer.h b/core/plug-in/session_timer/UserTimer.h similarity index 79% rename from core/AmSessionTimer.h rename to core/plug-in/session_timer/UserTimer.h index fb8036e1..4998de08 100644 --- a/core/AmSessionTimer.h +++ b/core/plug-in/session_timer/UserTimer.h @@ -1,4 +1,3 @@ - /* * Timer class with seconds granularity */ @@ -19,12 +18,24 @@ #include -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 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 diff --git a/core/sems.cpp b/core/sems.cpp index 3dd36d08..f1a2ee35 100644 --- a/core/sems.cpp +++ b/core/sems.cpp @@ -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();