DSM: State machine notation for VoIP applications

DSM Readme file

The DonkeySM - state machines as SEMS applications

DonkeySM is a state machine interpreter for SEMS. Application 
or service logic can comfortably and accurately be defined
as state machine, in a simple textual state machine definition 
language, and executed by the dsm module as application in SEMS.

A DSM consists of states and transitions between the states.
One state is the initial state with which the DSM is started. 
The transitions have conditions. If something happens, 
i.e. the session processes an event, the transitions are checked 
in order. If all conditions match, the transition is executed. 
Transitions can contain actions, which are run when the transition 
is executed. States can have actions that are executed on entering 
the state, and on leaving the state. If a transition is executed, 
first the leaving actions of the old state, then the transition 
actions, and finally the entering actions of the new state are 
executed.

DSMs can be defined in a hierarchical manner: Another DSM can be 
called as sub-DSM, or one can jump to another DSM, ignoring where
we came from.

A session (call) in the DonkeySM has a set of named (string) variables.
The variables may be used as parameter to most conditions and 
actions, by prepending the variable name with a dollar sign. The
parameters of an event (e.g. the key on key press) may be accessed
by prepending the name with a hash (e.g. #key). There are also 
'selects' with which a set of dialog properties can be accessed 
(e.g. @local_tag).

The DonkeySM can be extended by modules, which add new conditions
and actions to the language. This way, menuing system etc can be 
implemented as DSM, while complex logic or processing can efficitently 
be implemented in C++. Modules can act on new sessions, and have a 
initialization function that is called when the module is loaded.
DonkeySM also has built in actions to call 
DI methods from other modules. 

Actions (and conditions) can throw exceptions. Once an exception occurs,
execution of the current actions is interrupted. Exceptions are handled
this way that special "exception" transitions are executed. Exception
transitions are marked with "exception" in the conditions list. Once the
FSM is in exception handling, only exception transitions are followed.
DSMs may throw exceptions with the throw(<type>) action or the 
throwOnError() action.

DSM can cache a set of prompts, configured at start, in memory 
using PromptCollection.

A patch for fmsc 1.0.4 from the graphical FSM editor fsme 
(http://fsme.sf.net) is available, so DSMs can be defined in 
click-n-drag fashion and compiled to SEMS DSM diagrams.

DI commands
===========

DI commands allow interaction with DSM calls, and DSM script reload:

postDSMEvent(string call_id, [ [[param0,val0],[param1,val1],...] ]
 post a DSM event into a call. can be used to interact with running
 calls in DSM. See DSM + monitoring + DI example in 
 examples/dsm_di_monit. 

 Example: 
   s.postDSMEvent(call_id, [['action', 'take'],['roomname', 'realworld']])


reloadDSMs()
  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)

preloadModule(string mod_name, string mod_path)
  preload module from specific path 

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([string config])
  return list of loaded DSMs
  if config empty or not given, DSM of main config will be listed

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
=========
 o doc/dsm_syntax.txt has a quick reference for dsm syntax
 o doc/examples/ and lib/ some example DSMs
 o doc/examples/dsm_di_monit example on interfacing with DSM
 o mods/ (will) have modules

Internals
=========
The DSMStateEngine has a set of DSM diagrams which are loaded by 
the DSMStateDiagramCollection from text file and interpreted by
the DSMChartReader, a simple stack based tokenizing compiler.

DSMCall, which implement the DSMSession interface (additionally
to being an AmSession), run DSMStateEngine::runEvent for every event 
that occurs that should be processed by the engine (e.g. Audio event, 
onBye, ...). 

The DSMStateEngine checks every condition of the active state whether
it matches. If all match, the exit actions of the current state, the 
transition actions and then the enter actions of the next state are 
executed. The DSMCondition::match and DSMAction::execute functions
get the event parameters and the session as parameters, so that they
can operate on variables, implement selects etc. 

The DSMCall implementation is very simple, it uses a playlist and 
has PromptCollection to simply play prompts etc.

DSMCoreModule is a 'built in' module that implements the basic 
conditions (test(), hangup() etc) and actions (set(), playFile(), DI 
etc).

Roadmap
=======

On the roadmap is the possibility for modules to be the session factory
used for creating the new session. As the DSMSession is mostly an abstract 
interface, other session types can easily be implemented, and their 
functionality be exposed to the DSM interpreter by custom actions and 
conditions that interact with that specific session type.

A set of modules exposing more of the core functionality.

As the call state representation is nicely encapsulated here, this can 
also provide an abstraction layer on which active call replication can 
be implemented (rather than re-doing that for every application).

Q&A
===

Why "Donkey" SM? 
 Thanks Atle for the name: "I dont know why.. but my first thought
 when I read good name for FSM interpreter was Donkey. The reason for the
 name is that you put alot of things ontop of a donkey, and let it carry
 it arround.. and this is the same.. you put loads of stuf ontop.. and it
 carries it."

What is repost()? 
 If an event should be reevaluated, e.g. by the transitions of another 
 state or the initial state of another DSM which is called with callFSM/ 
 jumpFSM, repost() can be called, which signals the interpreter to
 evaluate the current event again.

Is the diagram interpreted or compiled? 
 DonkeySM reads the DSM script and creates an internal representation 
 (DSM classes in STL containers). This way it can be executed very
 efficiently.

map<string, string> var; - Are you crazy? E stands for Express!
 yes, right, there would be more efficient ways to implement
 that.  Anyway, in my experience one mostly has to manipulate and 
 check strings, and it is just very comfortable to do it this way.
 OTOH, if in a normal call there is a transition maybe on average 
 every 10 seconds, for which 5 conditions are checked, it is not 
 so much an impact on performance, considering that we are processing
 an audio packet every 20 ms.

You rely too heavily on polymorphism and RTTI - one dynamic_cast for 
each condition of each transition is way too heavy!
 Sure, but as noted above, there should not be heavy processing done
 in the DSM. If you need this, then consider writing your app entirely 
 in C++.

SEMS has a dynamically typed type (AmArg), why not use that one for 
variables? That would also make DI simpler. 
 a patch is very welcome, best to semsdev list: semsdev@iptel.org or 
 the tracker: http://tracker.iptel.org.
 There is also the avar array ("AmArg-Var"), which can hold AmArg 
 variables.

some performance numbers? 
 unfortunately not yet for running DSMs. DSM processing is actually fast: 
 a (quite simple) 3 state 5 transition DSM compiles in 0.2ms on P-M 2GHz.
 So the diagram could actually be read when the call is setup, or DSMs could
 load other DSMs (e.g. loadFSM() action)

DSM Syntax

=============================
-- comment
import(mod_name);

[initial] state name 
	  [ enter { 
	      action; 
	      action;
	      ...
	    } ] 
	  [ exit { 
	      action;
	      action;
	      ...
	    } ]
      ;

transition name s1 - [exception;] [ { [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)
$varname uses the variable varname (from session's variable map)
@selectname uses the "select" 'selectname' (from the session's dialog)
=============================
core actions:
 -- reprocess the current event after transition:
 repost()

 -- call/jump/return sub-FSM
 jumpFSM(name)
 callFSM(name)
 returnFSM()

 stop(<send bye>)
   e.g. stop(false), stop(true)

 playPrompt(param)
   from promptCollection, e.g. playPrompt("hello");
   if $prompts.default_fallback=yes, default prompt set is tried if
   prompt not found in current prompt set
   Throws "prompt" exeption with #name if prompt not found.

 playPromptLooped(param)

 setPromptSet(name)
   select active prompt set if more prompt sets are loaded
   Throws "prompt" exeption with #name if prompt set not found

 playFile(filename [, loop=true])
   e.g. playFile($myfile, true); will play the file looped.
   Throws "file" exeption with #path if file can not be opened

 playFileFront(filename [, loop=true])
   e.g. playFileFront($myfile, true); will play the file at first
   position in the playlist, and looped.
   Throws "file" exeption with #path if file can not be opened

 recordFile(filename)
   Throws "file" exeption with #path if file can not be opened for recording

 stopRecord()
 getRecordLength([dst_varname])   -- only while recording! default dst var: record_length
 getRecordDataSize([dst_varname]) -- only while recording! default dst var: record_data_size
 closePlaylist()
 addSeparator(id [, bool front])
   fires event when playlist hits it ; front=[true|false]
 connectMedia() 
   set playlist as input and output of session, and connect to mediaprocessor 
 disconnectMedia() 
   disconnect from mediaprocessor

 mute() 
   set RTP stream to muted (don't send and receive RTP packets)
 unmute() 
   set RTP stream to unmuted (send and receive RTP packets)

 postEvent(sess_id[, variable name])
   post dsm event to session sess_id; variable copied as event variable
   e.g. postEvent(@local_tag, PAI) : post event to ourselves
   * sets $errno (arg)

 postEvent(sess_id, var)
   all local variables copied as event variables
   * sets $errno (arg)

 enableDTMFDetection() 
 disableDTMFDetection()

 B2B.connectCallee(remote_party, remote_uri)
   connect second leg of B2B session (see AmB2BSession)

 B2B.terminateOtherLeg
   disconnect second leg of B2B session (see AmB2BSession)

 B2B.sendReinvite(generate_sdp [, string extra_headers])
   send a reinvite in caller leg (first leg), e.g. to 
   reconnect first leg after B2B.otherBye received. 
   generate_sdp can be 'true' or 'false'
   (B2B.sendReinvite(true) recommended)

 B2B.clearHeaders()
   clear the headers used for outgoing INVITE on B leg

 B2B.addHeader(string header)
  add a header for outgoing INVITE on B leg
 
 B2B.setHeaders(string headers [, replace_crlf=true|false])
  set headers for outgoing INVITE on B leg
  replace_crlf=true for replacing \r\n with CRLF
  e.g. 
  B2B.setHeaders("P-One: value\r\nP-Two: anothervalue", true)

 setPrompts(name) 
   if more than one prompt sets are loaded

 set($var=value)
  e.g.  set($var="text"); set($var=$var2); set($var=#key)
 var($dstvar=srcvarname)
  e.g.  var($dstvar=$var_counter)
 eval($var=value) 
  evaluate expression (only simple binary + and - supported)
  e.g.  set($var=1+5); set($var=$var2); set($var=#key)
 append($var, value)
 e.g. append($var, "text"); append($var, #key);
      append($var, @select); append($var, $var2);
 inc($var)
 clear($var)

 log(level, text)
   e.g. log(1, $var1)
 -- log all variables:
 logVars(level) 
 -- log all selects:
 logSelects(level) 
 -- log all Params (only in actions of a transition):
 logParams(level) 
 -- log everything:
 logAll(level) 

 setTimer(timer_id, timeout)
   e.g. setTimer(1, $timeout)
   * sets $errno (arg,config)
 removeTimer(timer_id)
   * sets $errno (arg,config)
 removeTimers()
   * sets $errno (config)

  DI(factory, function [, params...])
  e.g. DI(factory, function, $var_param, (int)int_param, "$str param", @select_par, ...)
       DI(user_timer, setTimer, (int)1, (int)5, @local_tag);
   * sets $errno (arg,config)

  DIgetResult(factory, function, param,...)
    saves result from DI call to DI_res or DI_res0, DI_res1, ...
   * sets $errno (arg,config)

  throw(<type>[,arg1=val1;arg2=val2;...])
   e.g. throw(bad_command),  throw(bad_command,cmd=help;reason=whynot)

  throwOnError()

============================= 
conditions:
 
 test(#key == 1)
 test(#key != 1)
 test(#key < 1)
 test(#key > 1)

 test($var == 1)
 test($var != 1)
 test($var < 1)
 test($var < 1)

 test(len($var) < len(#key))
 test(len($var) < len(@user))

 -- like test(expr), but only on key press
 keyTest(expr) 
 timerTest(expr)
 noAudioTest(expr)
 separatorTest(expr)
  e.g. separatorTest(#id == 5)

 eventTest(expr)

 keyPress(no) 
  -- bye received: 
 hangup  

  -- execution is invite (with run_invite_event):
 invite 
  -- execution is start of session (with run_invite_event, otherwise its always true):
 sessionStart

 B2B.otherReply 
   Reply on other leg received (see AmB2BSession)
    #code    - reply code
    #reason  - reply reason
    #hdrs    - headers
     
 B2B.otherBye
   BYE on other leg received
    #hdrs    - headers

=============================
@selects :
 local_tag
 user
 domain
 remote_tag
 callid
 local_uri
 remote_uri
=============================
imports:
 module imported with import(mod_name); loads mod_name.so in 
 module load path. modules provide conditions and actions.
 modules' actions/conditions-factory is checked first 
 (modules can override core conditions/actions)
=============================
special variables:
    connect_session     "0" -> after the start event (initial transition):
                                  do not connect session to 
                                  media processor on start

                            -> after the invite event:
                                  do not reply with 200 OK and do not 
                                  connect session to media processor on start
    
=============================
errors:
   actions set $errno
     #define DSM_ERRNO_OK          ""
     #define DSM_ERRNO_FILE        "1"
     #define DSM_ERRNO_UNKNOWN_ARG "2"
     #define DSM_ERRNO_GENERAL     "99"
     ...

Error handling in DSM

Error handling in DSM
---------------------

There are two mechanisms of error handling in DSM: 
Reporting an error as $errno, and throwing an exception.

Some actions throw an exception directly if a severe error occurs, 
for example the "playFile" action if the file could 
not be opened. These functions are marked with 
 "   Throws "<xyz>" exeption with <arguments>  if ..."
in the description/documentation.

Other actions just set the error variable $errno. After those
the DSM script may execute the throwOnError(); action, which
throws an exception if the error is set. These actions are
marked in the description as "Sets Errno."

All actions that may set the variable $errno to some value
need to reset $errno if no error occured, otherwise an exception
from an error of a previous action could be thrown.

Exceptions may be caught with exception transitions (see general DSM 
description). 

For Python (mod_py), exception handling is special - the the mod_py
documentation.


Example 1: Handling file exceptions
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-
state BEGIN 
enter {
  playFile(maybeexisting.wav);
};
transition "key pressed" BEGIN - keyPress(1) -> OTHER;

state OTHER
enter {
  playFile(mayalsobeexisting.wav);
};

transition "file error" (BEGIN, OTHER) - exception; test(#type=="file") /
 stop(true) -> end;
transition "hangs up" (BEGIN, OTHER) - hangup / stop(false) -> end;

state end;
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-


Example 2: Handling error with exception
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-
import(mod_mysql);
state BEGIN 
enter {
  mysql.connect();
  throwOnError();
  mysql.queryGetResult(select file from prompts where user=@user);
  throwOnError();
  playFile($file);
};
transition "mysql connection error occured" BEGIN - exception; test(#type=="connection") /
   log(1, MySQL connection error); playFile(sorry_error.wav) -> PLAYEND;

transition "mysql query error / no result" BEGIN - exception; test(#type=="noresult") /
   playFile(default_prompt.wav) -> PLAYEND;

transition "file opening error" BEGIN - exception; test(#type=="file") /
   playFile(default_prompt.wav) -> PLAYEND;

transition "other error occured" BEGIN - exception;  /
  log(1, error:); log(1, #text); playFile(sorry_error.wav) -> PLAYEND;

state PLAYEND;
transition "finished" PLAYEND - noAudioTest / stop(true) -> end;
state end;
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-

DSM Todo

 x run_invite_event per DSM script
 o explicit condition ordering (explicit priority)
 o checking of FSM consitency (e.g. target state names)
 o better error reporting in script compilation (e.g. line number)
 x better error handling (exceptions)
 x 'not' operator on conditions
 o 'or' operator
 x provide session init function for modules
 x embed python interpreter in module ?
   -> py( ... python code ... ) condition and action
 x correct en/decode DI args (e.g. arrays)
 o replace DSMSession::map<string, string> var with map<string, AmArg>
   var -> avar
 x register scripts as app  
 x mod_mysql 
 o session creation from module

DSM modules

mod_sys - System functions

Actions: 
 sys.mkdir(string dirname)
 sys.mkdirRecursive(string dirname)
 sys.rename(string from, string to)
 sys.unlink(string filename)
 sys.unlinkArray(string filename, string prefix)
    Array version of unlink (prefix/filename_0 .. prefix/filename_$filename_size) 
 sys.tmpnam(string varname)

Conditions: 
 sys.file_exists(string fname)
 sys.file_not_exists(string fname)

mod_dlg - Dialog related functionality

* mod_dlg saves the initial INVITE to DSMSession::last_req
* set connect_session to 0 with set(connect_session=0)
  if you want to reply with other than the standard 200 OK 
  to initial INVITE received.

dlg.reply(code,reason);
 reply to the request in DSMSession::last_req 
 (usually INVITE, if not yet replied) with code and reason
 * sets $errno (arg,general)

dlg.acceptInvite([code, reason]);
 e.g. dlg.acceptInvite(183, progress);
 * sets $errno (arg,general)
 
 accept audio stream from last_req (INVITE), and reply with 200 OK (default)
 or code, reason
 
dlg.bye([headers])
 send BYE. useful for example for continuing processing after call has ended.
 * sets $errno (general)

dlg.connectCalleeRelayed(string remote_party, string remote_uri)
 like B2B.connectCallee() but for relayed INVITEs, i.e. for executing in 
 invite run (run_invite_event=yes and transition "on INVITE" START - invite -> runinvite;)

mod_uri - URI parser and related functionality

uri.parse(<uri>, <prefix>)
  splits <uri> in 
    <prefix>display_name
    <prefix>user
    <prefix>host
    <prefix>param

   example: 
    uri.parse(@remote_uri, remote_);
    uri.parse($PAI, pai_);

  * Sets $errno (general).

uri.getHeader(<header>, <dst>)
    get header from initial INVITE into variable <dst>

    example:
    	uri.getHeader(P-Asserted-Identity, PAI);

 

mod_utils - Utility functions

Actions: 
 utils.getNewId(string varname)

 utils.playCountRight(int cnt [, string basedir])
    play count for laguages that have single digits after the 10s (like english)
    * Throws "file" exeption with #path if file can not be opened
    * sets $errno (arg)

 utils.playCountLeft(int cnt [, string basedir])
    play count for laguages that have single digits befire the 10s (like german)  
    * Throws "file" exeption with #path if file can not be opened
    * sets $errno (arg)

 utils.spell(string word[, string basedir])
  plays each character in the word (e.g. utils.spell(321,wav/digits/) plays
    wav/digits/3.wav, wav/digits/2.wav, wav/digits/1.wav 
  (like SayDigits from *)
  * Throws "file" exeption with #path if file can not be opened

 utils.rand(string varname [, int modulo])
  generates random number: $varname=rand()%modulo or $varname = rand()

 utils.srand() 
  seed the RNG with time().

mod_conference - Conferencing functions

Actions: 
 conference.join(string roomname [, string mode])
   mode = "" | speakonly | listenonly
   Throws "conference" Exception if conference can not be joined (currently never).

 conference.leave()
   destroy conference channel. Close playlist first!!!!!
   * Sets $errno (script).

 conference.rejoin(string roomname [, string mode])
   mode = "" | speakonly | listenonly
   Throws "conference" Exception if conference can not be joined (currently never).

 conference.postEvent(string roomname, int event_id)
   * Sets $errno (arg).

 conference.setPlayoutType(string type)
   where type is one of ["adaptive", "jb", "simple"]

mod_mysql - MySQL DB access

mod_py - Embedded Python functions

mod_py - DSM actions and conditions in Python
=============================================

mod_py adds one action and one condition to DSM: py(...)

py() action may execute arbitrary python code; py() condition 
python code needs to evaluate to an expression which returns
True or False (or and int value).

The 'type' and 'params' are accessible to determine the current
event's type and parameters.

py() actions and conditions can access session's variables using
session.var(name) and session.setvar(name, value). Locals stay 
across different py(...) actions/conditions.

They may even directly use some media functionality implemented 
in DSM sessions - see session module's help below. But, 
conceptionally, mod_py is above DSM, so while it would be 
possible it is not recommended to extend it with functions that
manipulate the AmSession directly.

Indentation is a little ugly with multi-line py() actions. 
But this is Python's fault (in 21st century, who creates a 
programming language with fixed indentation?).

mod_py MUST be preloaded, to initialize the python interpreter.
add preload=mod_py to dsm.conf. 


locals
======
type    - event type (dsm.Timer, dsm.Key, ...)
params  - dictionary with event parameters 
           (e.g. params['id'] for event==dsm.Timer)
dsm     - module to access dsm functions (see below)
session - module to access session functions (see below)

exceptions
==========
dsm.playPrompt, dsm.playFile, dsm.recordFile and dsm.setPromptSet
may throw an exception. This is a Python RuntimeError exception,
not the DSM exception handling (exceptions in interpreted code
can not be catched through outside of the interpreter). 
The application needs to catch the exceptions in the python code
itself, and can then handle them or signal the DSM code to throw
an exception. example:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
initial state begin 
 enter {
  py(dsm.INFO("hello dsm-world\n"))
  py(#
try:
	session.playFile('doesnotexist.wav')
except RuntimeError, e:
	dsm.ERROR('thats a runtime error: ' + e.message + '!\n')
	session.setvar('exception', e.message)
)
  log(2, huhu, still there);
  repost();
};
transition "catch py exception" begin - test($exception!="") / throw($exception) -> begin;
transition "normal exception handling" begin - exception; test(#type=="file") -> exception_state;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


example
=======
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import(mod_py);

initial state begin 
 enter {
  py(dsm.INFO("hello dsm-world"))
  py(#
session.setvar('some_variable','some val')
print session.var('some_variable')
print "dsm.Timer = ", dsm.Timer
)
  setTimer(1, 5);
  log(2, $some_variable)
  repost();
};

transition "timer" begin - py(type == dsm.Timer and params['id'] == '1')  / 
         py(session.playFile('wav/default_en.wav')); -> wait;

transition "key 1" begin - py(type == dsm.Key and params['key'] == '1')  / 
         py(session.playFile('wav/default_en.wav')); -> wait;

state wait;
transition "bye recvd" (begin, wait) - hangup / stop -> end;
state end;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

modules
=======
------------------------
help on module session:

NAME
    session

FILE
    (built-in)

FUNCTIONS
    B2BconnectCallee(string remote_party, string remote_uri [, bool relayed_invite])
        connect callee of B2B leg

    B2BterminateOtherLeg()
        terminate other leg of B2B call

    addSeparator(string name[, bool front])
        add a named separator to playlist

    closePlaylist(bool notify)
        close the playlist

    connectMedia()
        connect media (RTP processing)

    disconnectMedia()
        disconnect media (RTP processing)

    getRecordDataSize()
        get the data size of the current recording

    getRecordLength()
        get the length of the current recording

    mute()
        mute RTP)

    playFile(string name [, bool loop[, bool front]])
        play a file

    playPrompt(string name [, bool loop])
        play a prompt

    recordFile(string name)
        start recording to a file

    select(string name)
        get a session's select

    setError(int errno)
        set error (errno)

    setPromptSet(string name)
        set prompt set

    setvar(string name, string value)
        set a session's variable

    stopRecord()
        stop the running recording

    unmute()
        unmute RTP

    var(string name)
        get a session's variable
------------------------------------
Help on module dsm:

NAME
    dsm

FILE
    (built-in)

FUNCTIONS
    DBG(string msg)
        Log a message using SEMS' logging system, level debug

    ERROR(string msg)
        Log a message using SEMS' logging system, level error

    INFO(string msg)
        Log a message using SEMS' logging system, level info

    WARN(string msg)
        Log a message using SEMS' logging system, level warning

    log(int level, string msg)
        Log a message using SEMS' logging system

DATA
    Any = 0
    B2BOtherBye = 13
    B2BOtherReply = 12
    DSMEvent = 10
    Hangup = 6
    Hold = 7
    Invite = 1
    Key = 3
    NoAudio = 5
    PlaylistSeparator = 11
    SessionStart = 2
    Timer = 4
    UnHold = 8
    XmlrpcResponse = 9



how to debug memory leak:
-------------------------

Unfortunately, it seems to be not simple to get embedded 
python interpreter leak free. Here is how to run with python's 
mem debug:

compile python with --with-pydebug, e.g. 

./configure --with-pydebug --prefix=/path/to/mod_dsm/python
make && make install

set debug python in Makefile, e.g. replace PY_VER/PY_EXE:
 PY_VER = 2.5
 PY_EXE = ./python/bin/python

make mod_py with -D PYDSM_WITH_MEM_DEBUG

run sems with -E, make calls, end sems with ctrl-c
from python do scripts/combinerefs.py refs.txt.
generate calls with e.g. sipp:
sipp -sn uac -i 192.168.5.106 -s 35 -d 500 -r 400 192.168.5.106:5070
(sudo su; ulimit -n 100000  before starting sems)

mod_aws - Amazon Web Services functions

mod_aws - Copyright (C) 2009 TelTech Systems Inc.

This module brings Amazon Web Services to DSM. 

It uses and depends on libaws++, see http://aws.28msec.com/.

mod_aws must be preloaded. See aws.conf for configuration 
(aws credentials, connection pool size etc).

Actions
-------
S3: bucket name from $aws.s3.bucket is used if not specified as 
action parameter.

aws.s3.put(string filename [, string keyname]) 
  put file into bucket, if specified under key keyname, 
  else keyname=filename
  * throws Exception type="aws", with #cause
  * sets $errno (aws_put)


aws.s3.putArray(string filename_array [, string keyname_array])
  put files into bucket, if specified under key keyname, 
  else keyname=filename
  array is $filename_0, $filename_1, .. $filename_size
  * throws Exception type="aws", with #cause
  * sets $errno (aws_put,arg)

SQS: queue name from $aws.sqs.queue is used if not specified as 
action parameter.
 
aws.s3.createBucket([string bucket_name])
  create bucket. created bucket name in $aws.s3.bucket (should be same
  as bucket_name)
  * throws Exception type="aws", with #cause
  * sets $errno (aws_create,aws_conn,arg)

aws.sqs.createQueue(int visibilityTimeout [, string queue_name])
  create queue
  * sets $errno (aws_create,aws_conn,arg)

aws.sqs.deleteQueue([string queue_name])
  delete queue
  * sets $errno (aws_create,aws_conn,arg)

aws.sqs.sendMessage(string message [, string queue_name])
  send a message in queue. sets
    $aws.sqs.url
    $aws.sqs.md5
  * sets $errno (aws_create,aws_conn,arg)

Error handling
--------------
On error, errno is set, and aws.ereason has more detailed 
description.

Errno codes:
#define DSM_ERRNO_AWS_CONN    "50"
#define DSM_ERRNO_AWS_PUT     "51"
#define DSM_ERRNO_AWS_CREATE  "52"
#define DSM_ERRNO_AWS_DELETE  "53"
#define DSM_ERRNO_AWS_SEND    "54"

Links

Back to Application Modules Documentation, to Example Applications.


Generated on Wed Mar 17 14:34:30 2010 for SEMS by  doxygen 1.6.1
Home |  Recent changes |  Search |  Glossary |  Sitemap |  Login