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

Reply via email to