Author: sayer
Date: 2009-01-27 11:11:31 +0100 (Tue, 27 Jan 2009)
New Revision: 1245
Modified:
trunk/apps/dsm/DSM.cpp
trunk/apps/dsm/DSMChartReader.cpp
trunk/apps/dsm/DSMChartReader.h
trunk/apps/dsm/DSMStateDiagramCollection.cpp
trunk/apps/dsm/DSMStateDiagramCollection.h
trunk/apps/dsm/DSMStateEngine.cpp
trunk/apps/dsm/DSMStateEngine.h
trunk/apps/dsm/doc/dsm_syntax.txt
trunk/apps/dsm/doc/dsm_todo.txt
trunk/apps/dsm/etc/dsm.conf
Log:
o 'not' operator on conditions
o transitions from multiple origin states
o register scripts as application
Modified: trunk/apps/dsm/DSM.cpp
===================================================================
--- trunk/apps/dsm/DSM.cpp 2009-01-21 12:15:24 UTC (rev 1244)
+++ trunk/apps/dsm/DSM.cpp 2009-01-27 10:11:31 UTC (rev 1245)
@@ -172,6 +172,22 @@
return -1;
}
}
+
+ string RegisterDiags = cfg.getParameter("register_apps");
+ vector<string> register_names = explode(RegisterDiags, ",");
+ for (vector<string>::iterator it=
+ register_names.begin(); it != register_names.end(); it++) {
+ if (diags.hasDiagram(*it)) {
+ bool res = AmPlugIn::instance()->registerFactory4App(*it,this);
+ if(res)
+ INFO("DSM state machine registered: %s.\n",
+ it->c_str());
+ } else {
+ ERROR("trying to register application '%s' which is not loaded.\n",
+ it->c_str());
+ return -1;
+ }
+ }
InboundStartDiag = cfg.getParameter("inbound_start_diag");
if (InboundStartDiag.empty()) {
@@ -200,21 +216,35 @@
AmSession* DSMFactory::onInvite(const AmSipRequest& req)
{
- if (InboundStartDiag.empty()) {
- ERROR("no inbound calls allowed\n");
- throw AmSession::Exception(488, "Not Acceptable Here");
+ string start_diag;
+ if (req.cmd == MOD_NAME) {
+ if (InboundStartDiag.empty()) {
+ ERROR("no inbound calls allowed\n");
+ throw AmSession::Exception(488, "Not Acceptable Here");
+ }
+ start_diag = InboundStartDiag;
+ } else {
+ start_diag = req.cmd;
}
- DSMDialog* s = new DSMDialog(prompts, diags, InboundStartDiag, NULL);
+
+ DSMDialog* s = new DSMDialog(prompts, diags, start_diag, NULL);
prepareSession(s);
return s;
}
AmSession* DSMFactory::onInvite(const AmSipRequest& req,
- AmArg& session_params)
+ AmArg& session_params)
{
- if (OutboundStartDiag.empty()) {
- ERROR("no outbound calls allowed\n");
+
+ string start_diag;
+
+ if (req.cmd == MOD_NAME) {
+ if (OutboundStartDiag.empty()) {
+ ERROR("no outbound calls allowed\n");
throw AmSession::Exception(488, "Not Acceptable Here");
+ }
+ } else {
+ start_diag = req.cmd;
}
UACAuthCred* cred = NULL;
@@ -224,7 +254,7 @@
cred = dynamic_cast<UACAuthCred*>(cred_obj);
}
- DSMDialog* s = new DSMDialog(prompts, diags, OutboundStartDiag, cred);
+ DSMDialog* s = new DSMDialog(prompts, diags, start_diag, cred);
prepareSession(s);
if (NULL == cred) {
Modified: trunk/apps/dsm/DSMChartReader.cpp
===================================================================
--- trunk/apps/dsm/DSMChartReader.cpp 2009-01-21 12:15:24 UTC (rev 1244)
+++ trunk/apps/dsm/DSMChartReader.cpp 2009-01-27 10:11:31 UTC (rev 1245)
@@ -112,13 +112,21 @@
return core_mod.getAction(str);
}
-DSMCondition* DSMChartReader::conditionFromToken(const string& str) {
+DSMCondition* DSMChartReader::conditionFromToken(const string& str, bool
invert) {
for (vector<DSMModule*>::iterator it=
mods.begin(); it!= mods.end(); it++) {
DSMCondition* c=(*it)->getCondition(str);
- if (c) return c;
+ if (c) {
+ c->invert = invert;
+ return c;
+ }
}
- return core_mod.getCondition(str);
+
+ DSMCondition* c = core_mod.getCondition(str);
+ if (c)
+ c->invert = invert;
+
+ return c;
}
void splitCmd(const string& from_str,
@@ -332,8 +340,15 @@
}
continue;
}
+
+ if (token == "not") {
+ cl->invert_next = !cl->invert_next;
+ continue;
+ }
+
// DBG("new condition: '%s'\n", token.c_str());
- DSMCondition* c = conditionFromToken(token);
+ DSMCondition* c = conditionFromToken(token, cl->invert_next);
+ cl->invert_next = false;
if (!c)
return false;
Modified: trunk/apps/dsm/DSMChartReader.h
===================================================================
--- trunk/apps/dsm/DSMChartReader.h 2009-01-21 12:15:24 UTC (rev 1244)
+++ trunk/apps/dsm/DSMChartReader.h 2009-01-27 10:11:31 UTC (rev 1245)
@@ -69,8 +69,9 @@
};
struct DSMConditionList : public DSMElement {
- DSMConditionList() { }
+ DSMConditionList() : invert_next(false) { }
vector<DSMCondition*> conditions;
+ bool invert_next;
};
class DSMChartReader {
@@ -80,7 +81,7 @@
string getToken(string str, size_t& pos);
DSMAction* actionFromToken(const string& str);
- DSMCondition* conditionFromToken(const string& str);
+ DSMCondition* conditionFromToken(const string& str, bool invert);
bool importModule(const string& mod_cmd, const string& mod_path);
vector<DSMModule*> mods;
Modified: trunk/apps/dsm/DSMStateDiagramCollection.cpp
===================================================================
--- trunk/apps/dsm/DSMStateDiagramCollection.cpp 2009-01-21 12:15:24 UTC
(rev 1244)
+++ trunk/apps/dsm/DSMStateDiagramCollection.cpp 2009-01-27 10:11:31 UTC
(rev 1245)
@@ -69,6 +69,15 @@
return true;
}
+bool DSMStateDiagramCollection::hasDiagram(const string& name) {
+ for (vector<DSMStateDiagram>::iterator it=
+ diags.begin(); it != diags.end(); it++)
+ if (it->getName() == name)
+ return true;
+
+ return false;
+}
+
void DSMStateDiagramCollection::addToEngine(DSMStateEngine* e) {
DBG("adding %zd diags to engine\n", diags.size());
for (vector <DSMStateDiagram>::iterator it =
Modified: trunk/apps/dsm/DSMStateDiagramCollection.h
===================================================================
--- trunk/apps/dsm/DSMStateDiagramCollection.h 2009-01-21 12:15:24 UTC (rev
1244)
+++ trunk/apps/dsm/DSMStateDiagramCollection.h 2009-01-27 10:11:31 UTC (rev
1245)
@@ -45,6 +45,7 @@
bool loadFile(const string& filename, const string& name, const string&
mod_path);
void addToEngine(DSMStateEngine* e);
+ bool hasDiagram(const string& name);
};
#endif
Modified: trunk/apps/dsm/DSMStateEngine.cpp
===================================================================
--- trunk/apps/dsm/DSMStateEngine.cpp 2009-01-21 12:15:24 UTC (rev 1244)
+++ trunk/apps/dsm/DSMStateEngine.cpp 2009-01-27 10:11:31 UTC (rev 1245)
@@ -28,6 +28,7 @@
#include "DSMStateEngine.h"
#include "DSMModule.h"
+#include "AmUtils.h"
#include "AmSession.h"
#include "log.h"
@@ -63,25 +64,53 @@
}
bool DSMStateDiagram::addTransition(const DSMTransition& trans) {
- DBG("adding Transition '%s' %s -()-> %s\n",
+ DBG("adding Transition '%s' %s -(...)-> %s\n",
trans.name.c_str(), trans.from_state.c_str(), trans.to_state.c_str());
for (vector<DSMCondition*>::const_iterator it=
trans.precond.begin(); it != trans.precond.end(); it++) {
- DBG(" DSMCondition '%s'\n", (*it)->name.c_str());
+ DBG(" DSMCondition %s'%s'\n",
+ (*it)->invert?"not ":"", (*it)->name.c_str());
}
for (vector<DSMAction*>::const_iterator it=
trans.actions.begin(); it != trans.actions.end(); it++) {
DBG(" Action '%s'\n", (*it)->name.c_str());
}
- State* source_st = getState(trans.from_state);
- if (!source_st) {
- ERROR("state '%s' for transition '%s' not found\n",
- trans.from_state.c_str(), trans.name.c_str());
- return false;
+ vector<string> from_states;
+
+ if (trans.from_state.find_first_of("(") != string::npos) {
+
+ string states = trans.from_state;
+ if (states.length() && states[0] == '(')
+ states = states.substr(1);
+ if (states.length() && states[states.length()-1] == ')')
+ states = states.substr(0, states.length()-1);
+
+ from_states = explode(states, ",");
+ for (vector<string>::iterator it=from_states.begin();
+ it != from_states.end(); it++) {
+ if (it->length() && (*it)[0] == ' ')
+ *it = it->substr(1);
+ if (it->length() && (*it)[it->length()-1] == ' ')
+ *it = it->substr(0, it->length()-1);
+ }
+
+ } else {
+ from_states.push_back(trans.from_state);
}
-
- source_st->transitions.push_back(trans);
+
+ for (vector<string>::iterator it=
+ from_states.begin(); it != from_states.end(); it++) {
+ State* source_st = getState(*it);
+ if (!source_st) {
+ ERROR("state '%s' for transition '%s' not found\n",
+ it->c_str(), trans.name.c_str());
+ return false;
+ }
+
+ source_st->transitions.push_back(trans);
+ }
+
return true;
}
@@ -183,6 +212,13 @@
return true;
}
+bool DSMCondition::_match(AmSession* sess,
+ DSMCondition::EventType event,
+ map<string,string>* event_params) {
+ // or xor
+ return
invert?(!match(sess,event,event_params)):match(sess,event,event_params);
+}
+
bool DSMCondition::match(AmSession* sess,
DSMCondition::EventType event,
map<string,string>* event_params) {
@@ -220,7 +256,7 @@
vector<DSMCondition*>::iterator con=tr->precond.begin();
while (con!=tr->precond.end()) {
- if (!(*con)->match(sess, event, event_params))
+ if (!(*con)->_match(sess, event, event_params))
break;
con++;
}
Modified: trunk/apps/dsm/DSMStateEngine.h
===================================================================
--- trunk/apps/dsm/DSMStateEngine.h 2009-01-21 12:15:24 UTC (rev 1244)
+++ trunk/apps/dsm/DSMStateEngine.h 2009-01-27 10:11:31 UTC (rev 1245)
@@ -73,12 +73,17 @@
PlaylistSeparator
};
- DSMCondition() { }
+ bool invert;
+
+ DSMCondition() : invert(false) { }
virtual ~DSMCondition() { }
EventType type;
map<string, string> params;
+ bool _match(AmSession* sess, DSMCondition::EventType event,
+ map<string,string>* event_params);
+
virtual bool match(AmSession* sess, DSMCondition::EventType event,
map<string,string>* event_params);
};
Modified: trunk/apps/dsm/doc/dsm_syntax.txt
===================================================================
--- trunk/apps/dsm/doc/dsm_syntax.txt 2009-01-21 12:15:24 UTC (rev 1244)
+++ trunk/apps/dsm/doc/dsm_syntax.txt 2009-01-27 10:11:31 UTC (rev 1245)
@@ -15,7 +15,9 @@
} ]
;
-transition name s1 - [ { condition; condition; ... } ] [/ { action; action;
...} ] -> s2;
+transition name s1 - [ { [not] condition; [not] condition; ... } ] [/ {
action; action; ...} ] -> s2;
+ or
+transition name (s1a, s1b[, s1c, ...]) - [ { [not] condition; [not]
condition; ... } ] [/ { action; action; ...} ] -> s2;
=============================
#paramname uses the event parameter 'paramname' (from current event)
@@ -41,8 +43,8 @@
setPromptSet(name)
if more prompt sets are loaded
- set($var, value)
- e.g. set($var, "text"); set($var, $var2); set($var, #key)
+ set($var=value)
+ e.g. set($var="text"); set($var=$var2); set($var=#key)
append($var, value)
e.g. append($var, "text"); append($var, #key);
append($var, @select); append($var, $var2);
Modified: trunk/apps/dsm/doc/dsm_todo.txt
===================================================================
--- trunk/apps/dsm/doc/dsm_todo.txt 2009-01-21 12:15:24 UTC (rev 1244)
+++ trunk/apps/dsm/doc/dsm_todo.txt 2009-01-27 10:11:31 UTC (rev 1245)
@@ -2,10 +2,13 @@
o checking of FSM consitency (e.g. target state names)
o better error reporting in script compilation (e.g. line number)
o better error handling (exceptions)
- o 'not' operator on conditions
+ x 'not' operator on conditions
o 'or' operator
x provide session init function for modules
o embed python interpreter in module ?
-> py( ... python code ... ) condition and action
o correct en/decode DI args (e.g. arrays)
+ o replace DSMSession::map<string, string> var with map<string, AmArg>
+ x register scripts as app
o mod_mysql
+ o session creation from module
Modified: trunk/apps/dsm/etc/dsm.conf
===================================================================
--- trunk/apps/dsm/etc/dsm.conf 2009-01-21 12:15:24 UTC (rev 1244)
+++ trunk/apps/dsm/etc/dsm.conf 2009-01-27 10:11:31 UTC (rev 1245)
@@ -3,6 +3,10 @@
diag_path=/usr/local/lib/sems/dsm/
load_diags=inbound_call,outbound_call
+# register these diagrams as 'application' in SEMS
+# so it can be used in application= in sems.conf
+#register_apps=inbound_cann,outbound_call
+
# for import(mod_name)
mod_path=/usr/local/lib/sems/dsm/
_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev