From 0481ed77e074928563d6cacdd78fca88436cd0a4 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Wed, 28 Oct 2009 14:26:55 +0000 Subject: [PATCH] implements DSM app configurations from conf.d dir. this make it e.g. possible to install DSM applications from separate packages git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1582 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/dsm/DSM.cpp | 459 +++++++++++++++++++++++++++--------- apps/dsm/DSM.h | 27 ++- apps/dsm/DSMCall.cpp | 23 +- apps/dsm/DSMCall.h | 11 +- apps/dsm/DSMSession.h | 9 + apps/dsm/doc/Readme.dsm.txt | 19 +- apps/dsm/etc/dsm.conf | 14 ++ 7 files changed, 429 insertions(+), 133 deletions(-) diff --git a/apps/dsm/DSM.cpp b/apps/dsm/DSM.cpp index 7794448f..d58c386a 100644 --- a/apps/dsm/DSM.cpp +++ b/apps/dsm/DSM.cpp @@ -41,6 +41,9 @@ #include #include +#include +#include + #define MOD_NAME "dsm" extern "C" void* plugin_class_create() @@ -69,17 +72,13 @@ MonSelectType DSMFactory::MonSelectCaller; MonSelectType DSMFactory::MonSelectCallee; #endif // USE_MONITORING -map DSMFactory::config; -bool DSMFactory::RunInviteEvent; -bool DSMFactory::SetParamVariables; - DSMFactory::DSMFactory(const string& _app_name) : AmSessionFactory(_app_name),AmDynInvokeFactory(_app_name), loaded(false) { AmEventDispatcher::instance()->addEventQueue("dsm", this); - diags = new DSMStateDiagramCollection(); + MainScriptConfig.diags = new DSMStateDiagramCollection(); } void DSMFactory::postEvent(AmEvent* e) { @@ -100,9 +99,11 @@ DSMFactory::~DSMFactory() { prompt_sets.begin(); it != prompt_sets.end(); it++) delete it->second; - for (vector::iterator it= + for (std::set::iterator it= old_diags.begin(); it != old_diags.end(); it++) delete *it; + + delete MainScriptConfig.diags; } int DSMFactory::onLoad() @@ -117,7 +118,118 @@ int DSMFactory::onLoad() // get application specific global parameters configureModule(cfg); - + + DebugDSM = cfg.getParameter("debug_raw_dsm") == "yes"; + + if (!loadPrompts(cfg)) + return -1; + + if (!loadPromptSets(cfg)) + return -1; + + if (!loadDiags(cfg, MainScriptConfig.diags)) + return -1; + + vector registered_apps; + if (!registerApps(cfg, MainScriptConfig.diags, registered_apps)) + return -1; + + InboundStartDiag = cfg.getParameter("inbound_start_diag"); + if (InboundStartDiag.empty()) { + INFO("no 'inbound_start_diag' set in config. " + "inbound calls with application 'dsm' disabled.\n"); + } + + OutboundStartDiag = cfg.getParameter("outbound_start_diag"); + if (OutboundStartDiag.empty()) { + INFO("no 'outbound_start_diag' set in config. " + "outbound calls with application 'dsm' disabled.\n"); + } + + if (!InboundStartDiag.empty()) + AmPlugIn::instance()->registerFactory4App("dsm",this); + + MainScriptConfig.config_vars.insert(cfg.begin(), cfg.end()); + +// for (std::map::const_iterator it = +// cfg.begin(); it != cfg.end(); it++) +// MainScriptConfig.config_vars[it->first] = it->second; + + MainScriptConfig.RunInviteEvent = cfg.getParameter("run_invite_event")=="yes"; + + MainScriptConfig.SetParamVariables = cfg.getParameter("set_param_variables")=="yes"; + +#ifdef USE_MONITORING + string monitoring_full_callgraph = cfg.getParameter("monitoring_full_stategraph"); + MonitoringFullCallgraph = monitoring_full_callgraph == "yes"; + DBG("%sogging full call graph (states) to monitoring.\n", + MonitoringFullCallgraph?"L":"Not l"); + + string monitoring_full_transitions = cfg.getParameter("monitoring_full_transitions"); + MonitoringFullTransitions = monitoring_full_transitions == "yes"; + DBG("%sogging full call graph (transitions) to monitoring.\n", + MonitoringFullTransitions?"L":"Not l"); + + string cfg_usecaller = cfg.getParameter("monitor_select_use_caller"); + if (cfg_usecaller.empty() || cfg_usecaller=="from") + MonSelectCaller = MonSelect_FROM; + else if (cfg_usecaller=="no") + MonSelectCaller = MonSelect_NONE; + else if (cfg_usecaller=="pai") + MonSelectCaller = MonSelect_PAI; + else { + ERROR("monitor_select_use_caller value '%s' not understood\n", + cfg_usecaller.c_str()); + } + + string cfg_usecallee = cfg.getParameter("monitor_select_use_callee"); + if (cfg_usecallee.empty() || cfg_usecallee=="ruri") + MonSelectCallee = MonSelect_RURI; + else if (cfg_usecallee=="no") + MonSelectCallee = MonSelect_NONE; + else if (cfg_usecallee=="from") + MonSelectCallee = MonSelect_FROM; + else { + ERROR("monitor_select_use_callee value '%s' not understood\n", + cfg_usecallee.c_str()); + } +#endif + + string conf_d_dir = cfg.getParameter("conf_dir"); + if (!conf_d_dir.empty()) { + if (conf_d_dir[conf_d_dir.length()-1] != '/') + conf_d_dir += '/'; + + DBG("processing configurations in '%s'...\n", conf_d_dir.c_str()); + int err=0; + struct dirent* entry; + DIR* dir = opendir(conf_d_dir.c_str()); + + if(!dir){ + ERROR("config loader (%s): %s\n", + conf_d_dir.c_str(), strerror(errno)); + return -1; + } + while( ((entry = readdir(dir)) != NULL) && (err == 0) ){ + string conf_name = string(entry->d_name); + + if(conf_name.find(".conf",conf_name.length()-5) == string::npos ){ + continue; + } + + string conf_file_name = conf_d_dir + conf_name; + + DBG("loading %s ...\n",conf_file_name.c_str()); + if (!loadConfig(conf_file_name, conf_name, false, NULL)) + return -1; + + } + } + return 0; +} + +bool DSMFactory::loadPrompts(AmConfigReader& cfg) { + vector prompts_files = explode(cfg.getParameter("load_prompts"), ","); for (vector::iterator it= @@ -152,8 +264,12 @@ int DSMFactory::onLoad() } } if (!has_all_prompts) - return -1; + return false; + return true; +} + +bool DSMFactory::loadPromptSets(AmConfigReader& cfg) { string prompt_sets_path = cfg.getParameter("prompts_sets_path"); vector prompt_sets_names = @@ -183,9 +299,10 @@ int DSMFactory::onLoad() } prompt_sets[*it] = pc; } + return true; +} - DebugDSM = cfg.getParameter("debug_raw_dsm") == "yes"; - +bool DSMFactory::loadDiags(AmConfigReader& cfg, DSMStateDiagramCollection* m_diags) { string DiagPath = cfg.getParameter("diag_path"); if (DiagPath.length() && DiagPath[DiagPath.length()-1] != '/') DiagPath += '/'; @@ -196,7 +313,7 @@ int DSMFactory::onLoad() int res = preloadModules(cfg, err, ModPath); if (res<0) { ERROR("%s\n", err.c_str()); - return res; + return false; } // todo: pass preloaded mods to chart reader @@ -205,18 +322,23 @@ int DSMFactory::onLoad() vector diags_names = explode(LoadDiags, ","); for (vector::iterator it= diags_names.begin(); it != diags_names.end(); it++) { - if (!diags->loadFile(DiagPath+*it+".dsm", *it, ModPath, DebugDSM)) { + if (!m_diags->loadFile(DiagPath+*it+".dsm", *it, ModPath, DebugDSM)) { ERROR("loading %s from %s\n", it->c_str(), (DiagPath+*it+".dsm").c_str()); - return -1; + return false; } } - + + return true; +} + +bool DSMFactory::registerApps(AmConfigReader& cfg, DSMStateDiagramCollection* m_diags, + vector& register_names) { string RegisterDiags = cfg.getParameter("register_apps"); - vector register_names = explode(RegisterDiags, ","); + register_names = explode(RegisterDiags, ","); for (vector::iterator it= register_names.begin(); it != register_names.end(); it++) { - if (diags->hasDiagram(*it)) { + if (m_diags->hasDiagram(*it)) { bool res = AmPlugIn::instance()->registerFactory4App(*it,this); if(res) INFO("DSM state machine registered: %s.\n", @@ -224,69 +346,101 @@ int DSMFactory::onLoad() } else { ERROR("trying to register application '%s' which is not loaded.\n", it->c_str()); - return -1; + return false; } } + return true; +} - InboundStartDiag = cfg.getParameter("inbound_start_diag"); - if (InboundStartDiag.empty() && register_names.empty()) { - INFO("no 'inbound_start_diag' set in config. inbound calls with application 'dsm' disabled.\n"); - } - OutboundStartDiag = cfg.getParameter("outbound_start_diag"); - if (OutboundStartDiag.empty() && register_names.empty()) { - INFO("no 'outbound_start_diag' set in config. outbound calls with application 'dsm' disabled.\n"); +// DI interface function +void DSMFactory::loadConfig(const AmArg& args, AmArg& ret) { + string file_name = args.get(0).asCStr(); + string diag_name = args.get(1).asCStr(); + + if (loadConfig(file_name, diag_name, true, NULL)) { + ret.push(200); + ret.push("OK"); + } else { + ret.push(500); + ret.push("reload config failed"); } +} - if (!InboundStartDiag.empty() || OutboundStartDiag.empty()) - AmPlugIn::instance()->registerFactory4App("dsm",this); +bool DSMFactory::loadConfig(const string& conf_file_name, const string& conf_name, + bool live_reload, DSMStateDiagramCollection* m_diags) { - for (std::map::const_iterator it = - cfg.begin(); it != cfg.end(); it++) - config[it->first] = it->second; + string script_name = conf_name.substr(0, conf_name.length()-5); // - .conf + DBG("loading %s from %s ...\n", script_name.c_str(), conf_file_name.c_str()); + AmConfigReader cfg; + if(cfg.loadFile(conf_file_name)) + return false; - RunInviteEvent = cfg.getParameter("run_invite_event")=="yes"; + DSMScriptConfig script_config; + script_config.RunInviteEvent = + cfg.getParameter("run_invite_event")=="yes"; - SetParamVariables = cfg.getParameter("set_param_variables")=="yes"; + script_config.SetParamVariables = + cfg.getParameter("set_param_variables")=="yes"; -#ifdef USE_MONITORING - string monitoring_full_callgraph = cfg.getParameter("monitoring_full_stategraph"); - MonitoringFullCallgraph = monitoring_full_callgraph == "yes"; - DBG("%sogging full call graph (states) to monitoring.\n", - MonitoringFullCallgraph?"L":"Not l"); + script_config.config_vars.insert(cfg.begin(), cfg.end()); - string monitoring_full_transitions = cfg.getParameter("monitoring_full_transitions"); - MonitoringFullTransitions = monitoring_full_transitions == "yes"; - DBG("%sogging full call graph (transitions) to monitoring.\n", - MonitoringFullTransitions?"L":"Not l"); + if (live_reload) { + INFO("live DSM config reload does NOT reload prompts and prompt sets!\n"); + INFO("(see http://tracker.iptel.org/browse/SEMS-67)\n"); + } else { + if (!loadPrompts(cfg)) + return false; - string cfg_usecaller = cfg.getParameter("monitor_select_use_caller"); - if (cfg_usecaller.empty() || cfg_usecaller=="from") - MonSelectCaller = MonSelect_FROM; - else if (cfg_usecaller=="no") - MonSelectCaller = MonSelect_NONE; - else if (cfg_usecaller=="pai") - MonSelectCaller = MonSelect_PAI; - else { - ERROR("monitor_select_use_caller value '%s' not understood\n", - cfg_usecaller.c_str()); + if (!loadPromptSets(cfg)) + return false; } - string cfg_usecallee = cfg.getParameter("monitor_select_use_callee"); - if (cfg_usecallee.empty() || cfg_usecallee=="ruri") - MonSelectCallee = MonSelect_RURI; - else if (cfg_usecallee=="no") - MonSelectCallee = MonSelect_NONE; - else if (cfg_usecallee=="from") - MonSelectCallee = MonSelect_FROM; + DSMStateDiagramCollection* used_diags; + if (m_diags != NULL) + used_diags = m_diags; // got this from caller (main diags) else { - ERROR("monitor_select_use_callee value '%s' not understood\n", - cfg_usecallee.c_str()); + // create a new set of diags + used_diags = script_config.diags = new DSMStateDiagramCollection(); } -#endif - return 0; + if (!loadDiags(cfg, used_diags)) + return false; + + vector registered_apps; + if (!registerApps(cfg, used_diags, registered_apps)) + return false; + + ScriptConfigs_mut.lock(); + try { + // set ScriptConfig to this for all registered apps' names + for (vector::iterator reg_app_it= + registered_apps.begin(); reg_app_it != registered_apps.end(); reg_app_it++) { + string& app_name = *reg_app_it; + // dispose of the old one, if it exists + map::iterator it=ScriptConfigs.find(app_name); + if (it != ScriptConfigs.end()) { + // may be in use by active call - don't delete but save to + // old_diags for garbage collection (destructor) + if (it->second.diags != NULL) + old_diags.insert(it->second.diags); + } + + // overwrite with new config + ScriptConfigs[app_name] = script_config; + + DBG("-------------------------- inserting script config with diags [%p] for '%s'\n", + script_config.diags, app_name.c_str()); + } + } catch(...) { + ScriptConfigs_mut.unlock(); + throw; + } + ScriptConfigs_mut.unlock(); + + return true; } + void DSMFactory::prepareSession(DSMCall* s) { s->setPromptSets(prompt_sets); } @@ -436,7 +590,8 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req) vars["mon_session_record"] = session_id; #else - ERROR("using $(mon_select) for dsm application, but compiled without monitoring support!\n"); + ERROR("using $(mon_select) for dsm application, " + "but compiled without monitoring support!\n"); throw AmSession::Exception(488, "Not Acceptable Here"); #endif } else { @@ -445,17 +600,29 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req) } else { start_diag = req.cmd; } - diags_mut.lock(); - DSMCall* s = new DSMCall(&prompts, *diags, start_diag, NULL); - diags_mut.unlock(); + + // determine run configuration for script + DSMScriptConfig call_config; + ScriptConfigs_mut.lock(); + map::iterator sc=ScriptConfigs.find(start_diag); + if (sc == ScriptConfigs.end()) + call_config = MainScriptConfig; + else + call_config = sc->second; + + DBG("-------------------------- using script config with diags [%p] for '%s'\n", + call_config.diags, start_diag.c_str()); + + DSMCall* s = new DSMCall(call_config, &prompts, *call_config.diags, start_diag, NULL); + + ScriptConfigs_mut.unlock(); prepareSession(s); - addVariables(s, "config.", config); + addVariables(s, "config.", call_config.config_vars); - if (SetParamVariables) + if (call_config.SetParamVariables) addParams(s, req.hdrs); - if (!vars.empty()) addVariables(s, "", vars); @@ -503,14 +670,25 @@ AmSession* DSMFactory::onInvite(const AmSipRequest& req, AmArg2DSMStrMap(session_params, vars); } - DSMCall* s = new DSMCall(&prompts, *diags, start_diag, cred); + DSMScriptConfig call_config; + ScriptConfigs_mut.lock(); + map::iterator sc=ScriptConfigs.find(start_diag); + if (sc == ScriptConfigs.end()) + call_config = MainScriptConfig; + else + call_config = sc->second; + + DSMCall* s = new DSMCall(call_config, &prompts, *call_config.diags, start_diag, cred); + + ScriptConfigs_mut.unlock(); + prepareSession(s); - addVariables(s, "config.", config); + addVariables(s, "config.", call_config.config_vars); if (!vars.empty()) addVariables(s, "", vars); - if (SetParamVariables) + if (call_config.SetParamVariables) addParams(s, req.hdrs); if (NULL == cred) { @@ -560,10 +738,10 @@ void DSMFactory::reloadDSMs(const AmArg& args, AmArg& ret) { return; } } - diags_mut.lock(); - old_diags.push_back(diags); - diags = new_diags; - diags_mut.unlock(); + ScriptConfigs_mut.lock(); + old_diags.insert(MainScriptConfig.diags); + MainScriptConfig.diags = new_diags; + ScriptConfigs_mut.unlock(); ret.push(200); ret.push("DSMs reloaded"); @@ -638,19 +816,62 @@ void DSMFactory::preloadModule(const AmArg& args, AmArg& ret) { } void DSMFactory::listDSMs(const AmArg& args, AmArg& ret) { - diags_mut.lock(); - vector names = diags->getDiagramNames(); - diags_mut.unlock(); + vector names; + ScriptConfigs_mut.lock(); + + try { + if (isArgUndef(args) || !args.size()) + names = MainScriptConfig.diags->getDiagramNames(); + else { + if (isArgCStr(args.get(0))) { + map::iterator i= + ScriptConfigs.find(args.get(0).asCStr()); + if (i!= ScriptConfigs.end()) + names = i->second.diags->getDiagramNames(); + } + } + } catch (...) { + ScriptConfigs_mut.unlock(); + throw; + } + + ScriptConfigs_mut.unlock(); + for (vector::iterator it= names.begin(); it != names.end(); it++) { ret.push(*it); } } +bool DSMFactory::hasDSM(const string& dsm_name, const string& conf_name) { + bool res = false; + if (conf_name.empty()) + res = MainScriptConfig.diags->hasDiagram(dsm_name); + else { + map::iterator i= + ScriptConfigs.find(conf_name); + if (i!= ScriptConfigs.end()) + res = i->second.diags->hasDiagram(dsm_name); + } + return res; +} + void DSMFactory::hasDSM(const AmArg& args, AmArg& ret) { - diags_mut.lock(); - bool res = diags->hasDiagram(args.get(0).asCStr()); - diags_mut.unlock(); + string conf_name; + if (args.size()>1 && isArgCStr(args.get(1))) + conf_name = args.get(1).asCStr(); + + bool res; + + ScriptConfigs_mut.lock(); + try { + res = hasDSM(args.get(0).asCStr(), conf_name); + } catch(...) { + ScriptConfigs_mut.unlock(); + throw; + } + ScriptConfigs_mut.unlock(); + if (res) ret.push("1"); else @@ -659,9 +880,20 @@ void DSMFactory::hasDSM(const AmArg& args, AmArg& ret) { void DSMFactory::registerApplication(const AmArg& args, AmArg& ret) { string diag_name = args.get(0).asCStr(); - diags_mut.lock(); - bool has_diag = diags->hasDiagram(diag_name); - diags_mut.unlock(); + string conf_name; + if (args.size()>1 && isArgCStr(args.get(1))) + conf_name = args.get(1).asCStr(); + bool has_diag; + + ScriptConfigs_mut.lock(); + try { + has_diag = hasDSM(diag_name, conf_name); + } catch(...) { + ScriptConfigs_mut.unlock(); + throw; + } + ScriptConfigs_mut.unlock(); + if (!has_diag) { ret.push(400); ret.push("unknown application (DSM)"); @@ -697,20 +929,26 @@ void DSMFactory::loadDSM(const AmArg& args, AmArg& ret) { string dsm_file_name = DiagPath+dsm_name+".dsm"; string res = "OK"; - diags_mut.lock(); - if (diags->hasDiagram(dsm_name)) { - ret.push(400); - ret.push("DSM named '" + dsm_name + "' already loaded (use reloadDSMs to reload all)"); - } else { - if (!diags->loadFile(dsm_file_name, dsm_name, ModPath, DebugDSM)) { - ret.push(500); - ret.push("error loading "+dsm_name+" from "+ dsm_file_name); + + ScriptConfigs_mut.lock(); + try { + if (MainScriptConfig.diags->hasDiagram(dsm_name)) { + ret.push(400); + ret.push("DSM named '" + dsm_name + "' already loaded (use reloadDSMs to reload all)"); } else { - ret.push(200); - ret.push("loaded "+dsm_name+" from "+ dsm_file_name); + if (!MainScriptConfig.diags->loadFile(dsm_file_name, dsm_name, ModPath, DebugDSM)) { + ret.push(500); + ret.push("error loading "+dsm_name+" from "+ dsm_file_name); + } else { + ret.push(200); + ret.push("loaded "+dsm_name+" from "+ dsm_file_name); + } } + } catch(...) { + ScriptConfigs_mut.unlock(); + throw; } - diags_mut.unlock(); + ScriptConfigs_mut.unlock(); } void DSMFactory::loadDSMWithPaths(const AmArg& args, AmArg& ret) { @@ -719,20 +957,25 @@ void DSMFactory::loadDSMWithPaths(const AmArg& args, AmArg& ret) { string mod_path = args.get(2).asCStr(); string res = "OK"; - diags_mut.lock(); - if (diags->hasDiagram(dsm_name)) { - ret.push(400); - ret.push("DSM named '" + dsm_name + "' already loaded (use reloadDSMs to reload all)"); - } else { - if (!diags->loadFile(diag_path+dsm_name+".dsm", dsm_name, mod_path, DebugDSM)) { - ret.push(500); - ret.push("error loading "+dsm_name+" from "+ diag_path+dsm_name+".dsm"); + ScriptConfigs_mut.lock(); + try { + if (MainScriptConfig.diags->hasDiagram(dsm_name)) { + ret.push(400); + ret.push("DSM named '" + dsm_name + "' already loaded (use reloadDSMs to reload all)"); } else { - ret.push(200); - ret.push("loaded "+dsm_name+" from "+ diag_path+dsm_name+".dsm"); + if (!MainScriptConfig.diags->loadFile(diag_path+dsm_name+".dsm", dsm_name, mod_path, DebugDSM)) { + ret.push(500); + ret.push("error loading "+dsm_name+" from "+ diag_path+dsm_name+".dsm"); + } else { + ret.push(200); + ret.push("loaded "+dsm_name+" from "+ diag_path+dsm_name+".dsm"); + } } + } catch(...) { + ScriptConfigs_mut.unlock(); + throw; } - diags_mut.unlock(); + ScriptConfigs_mut.unlock(); } void DSMFactory::invoke(const string& method, const AmArg& args, @@ -773,6 +1016,9 @@ void DSMFactory::invoke(const string& method, const AmArg& args, } else if (method == "registerApplication"){ args.assertArrayFmt("s"); registerApplication(args,ret); + } else if (method == "loadConfig"){ + args.assertArrayFmt("ss"); + loadConfig(args,ret); } else if(method == "_list"){ ret.push(AmArg("postDSMEvent")); ret.push(AmArg("reloadDSMs")); @@ -780,6 +1026,7 @@ void DSMFactory::invoke(const string& method, const AmArg& args, ret.push(AmArg("loadDSMWithPaths")); ret.push(AmArg("preloadModules")); ret.push(AmArg("preloadModule")); + ret.push(AmArg("loadConfig")); ret.push(AmArg("hasDSM")); ret.push(AmArg("listDSMs")); ret.push(AmArg("registerApplication")); diff --git a/apps/dsm/DSM.h b/apps/dsm/DSM.h index b431f810..a1188069 100644 --- a/apps/dsm/DSM.h +++ b/apps/dsm/DSM.h @@ -42,6 +42,8 @@ using std::string; #include +#include + enum MonSelectType { MonSelect_NONE, MonSelect_RURI, @@ -60,16 +62,18 @@ class DSMFactory public AmEventQueueInterface { AmPromptCollection prompts; - DSMStateDiagramCollection* diags; - AmMutex diags_mut; + AmMutex main_diags_mut; - vector old_diags; + std::set old_diags; static bool DebugDSM; static string InboundStartDiag; static string OutboundStartDiag; + DSMScriptConfig MainScriptConfig; + map ScriptConfigs; + AmMutex ScriptConfigs_mut; #ifdef USE_MONITORING static MonSelectType MonSelectCaller; @@ -81,6 +85,16 @@ class DSMFactory ~DSMFactory(); bool loaded; + int preloadModules(AmConfigReader& cfg, string& res, const string& ModPath); + bool loadConfig(const string& conf_file_name, const string& conf_name, + bool live_reload, DSMStateDiagramCollection* m_diags); + bool loadDiags(AmConfigReader& cfg, DSMStateDiagramCollection* m_diags); + bool registerApps(AmConfigReader& cfg, DSMStateDiagramCollection* m_diags, + vector& register_names /* out */); + bool loadPromptSets(AmConfigReader& cfg); + bool loadPrompts(AmConfigReader& cfg); + bool hasDSM(const string& dsm_name, const string& conf_name); + map prompt_sets; void prepareSession(DSMCall* s); void addVariables(DSMCall* s, const string& prefix, @@ -97,16 +111,11 @@ class DSMFactory void loadDSM(const AmArg& args, AmArg& ret); void loadDSMWithPaths(const AmArg& args, AmArg& ret); void registerApplication(const AmArg& args, AmArg& ret); - - int preloadModules(AmConfigReader& cfg, string& res, const string& ModPath); + void loadConfig(const AmArg& args, AmArg& ret); public: static DSMFactory* instance(); - static map config; - static bool RunInviteEvent; - static bool SetParamVariables; - #ifdef USE_MONITORING static bool MonitoringFullCallgraph; static bool MonitoringFullTransitions; diff --git a/apps/dsm/DSMCall.cpp b/apps/dsm/DSMCall.cpp index 9b8ee628..623e459a 100644 --- a/apps/dsm/DSMCall.cpp +++ b/apps/dsm/DSMCall.cpp @@ -30,14 +30,17 @@ #include "AmMediaProcessor.h" #include "DSM.h" -DSMCall::DSMCall(AmPromptCollection* prompts, - DSMStateDiagramCollection& diags, - const string& startDiagName, - UACAuthCred* credentials) - : prompts(prompts), default_prompts(prompts), startDiagName(startDiagName), - playlist(this), cred(credentials), - rec_file(NULL), - process_invite(true), process_sessionstart(true) +DSMCall::DSMCall(const DSMScriptConfig& config, + AmPromptCollection* prompts, + DSMStateDiagramCollection& diags, + const string& startDiagName, + UACAuthCred* credentials) + : + run_invite_event(config.RunInviteEvent), + prompts(prompts), default_prompts(prompts), startDiagName(startDiagName), + playlist(this), cred(credentials), + rec_file(NULL), + process_invite(true), process_sessionstart(true) { diags.addToEngine(&engine); set_sip_relay_only(false); @@ -81,7 +84,7 @@ void DSMCall::onInvite(const AmSipRequest& req) { bool run_session_invite = engine.onInvite(req, this); - if (DSMFactory::RunInviteEvent) { + if (run_invite_event) { if (!engine.init(this, startDiagName, DSMCondition::Invite)) run_session_invite =false; @@ -107,7 +110,7 @@ void DSMCall::onOutgoingInvite(const string& headers) { req.hdrs = headers; bool run_session_invite = engine.onInvite(req, this); - if (DSMFactory::RunInviteEvent) { + if (run_invite_event) { if (!engine.init(this, startDiagName, DSMCondition::Invite)) run_session_invite =false; diff --git a/apps/dsm/DSMCall.h b/apps/dsm/DSMCall.h index a604fc06..6363b559 100644 --- a/apps/dsm/DSMCall.h +++ b/apps/dsm/DSMCall.h @@ -49,6 +49,8 @@ class DSMCall : public AmB2BCallerSession, string startDiagName; AmPlaylist playlist; + bool run_invite_event; + bool process_invite; bool process_sessionstart; @@ -62,10 +64,11 @@ class DSMCall : public AmB2BCallerSession, bool checkVar(const string& var_name, const string& var_val); public: - DSMCall(AmPromptCollection* prompts, - DSMStateDiagramCollection& diags, - const string& startDiagName, - UACAuthCred* credentials = NULL); + DSMCall(const DSMScriptConfig& config, + AmPromptCollection* prompts, + DSMStateDiagramCollection& diags, + const string& startDiagName, + UACAuthCred* credentials = NULL); ~DSMCall(); void onInvite(const AmSipRequest& req); diff --git a/apps/dsm/DSMSession.h b/apps/dsm/DSMSession.h index ce8583d3..38a1b09c 100644 --- a/apps/dsm/DSMSession.h +++ b/apps/dsm/DSMSession.h @@ -117,6 +117,15 @@ class DSMSession { std::auto_ptr last_req; }; +class DSMStateDiagramCollection; + +struct DSMScriptConfig { + DSMStateDiagramCollection* diags; + map config_vars; + + bool RunInviteEvent; + bool SetParamVariables; +}; class DSMDisposable { public: diff --git a/apps/dsm/doc/Readme.dsm.txt b/apps/dsm/doc/Readme.dsm.txt index 32a644cf..49d1302d 100644 --- a/apps/dsm/doc/Readme.dsm.txt +++ b/apps/dsm/doc/Readme.dsm.txt @@ -68,13 +68,16 @@ postDSMEvent(string call_id, [ [[param0,val0],[param1,val1],...] ] reloadDSMs() - reload all DSMs from config file (load_diags) + reload all DSMs from config file (load_diags) from main config + - DSM is loaded with main config loadDSM(string diag_name) load DSM with name diag_name, paths are taken from config file + - DSM is loaded with main config loadDSMWithPaths(string diag_name, string diag_path, string mod_path) load DSM with specified paths + - DSM is loaded with main config preloadModules() preload all modules specified in config file (preload_mods) @@ -82,16 +85,24 @@ preloadModules() preloadModule(string mod_name, string mod_path) preload module from specific path -hasDSM(string diag_name) +hasDSM(string diag_name, [string config]) returns 1 if DSM with diag_name is loaded, 0 if not + if config empty or not given, DSM of main config will be listed -listDSMs() +listDSMs([string config]) return list of loaded DSMs + if config empty or not given, DSM of main config will be listed -registerApplication(string diag_name) +registerApplication(string diag_name, [string config]) register DSM with name diag_name as application in SEMS (e.g. to be used with application=$(apphdr), $(ruri.param) or $(ruri.user) + if config empty or not given, DSM is assumed to be in main config + +loadConfig(string conf_file_name, string conf_name) + (re)load application configuration and script + like a file in conf_dir + More info ========= diff --git a/apps/dsm/etc/dsm.conf b/apps/dsm/etc/dsm.conf index 861d7545..c6a01066 100644 --- a/apps/dsm/etc/dsm.conf +++ b/apps/dsm/etc/dsm.conf @@ -95,3 +95,17 @@ load_prompts=/usr/local/etc/sems/etc/dsm_in_prompts.conf,/usr/local/etc/sems/etc # #monitor_select_use_callee=no +# conf_dir= +# +# is scanned for *.conf files. Every .conf +# file is loaded, and in the .conf file, the following +# DSM config parameters are processed: +# diag_path= +# load_diags= +# register_apps= +# mod_path= +# preload_mods= +# run_invite_event= +# +# +#