mirror of https://github.com/sipwise/sems.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
456 lines
12 KiB
456 lines
12 KiB
DSM quick reference
|
|
===================
|
|
|
|
Syntax
|
|
======
|
|
-- comment
|
|
#include "script.dsm"
|
|
#include "/path/to/anotherscript.dsm"
|
|
import(mod_name);
|
|
|
|
[initial] state name
|
|
[ enter {
|
|
<actions>
|
|
} ]
|
|
[ exit {
|
|
<actions>
|
|
} ]
|
|
;
|
|
|
|
transition name s1 - [ { [not] condition; [not] condition; ... } ] [/ { <actions>} ] -> s2;
|
|
or
|
|
transition name (s1a, s1b[, s1c, ...]) - [ { [not] condition; [not] condition; ... } ] [/ { <actions> } ] -> s2;
|
|
or (exception transition)
|
|
transition name s1 - exception [ { [not] condition; ... } ] [/ { <actions>} ] -> s2;
|
|
|
|
|
|
function func_name() {
|
|
<actions>
|
|
};
|
|
|
|
<actions> ::=
|
|
action;
|
|
action(param, param, ...);
|
|
|
|
if condition; condition; {
|
|
<actions>
|
|
} else {
|
|
<actions>
|
|
}
|
|
|
|
func_name();
|
|
...
|
|
|
|
|
|
Variables, event parameters, selects
|
|
====================================
|
|
|
|
#paramname uses the event parameter 'paramname' (from current event)
|
|
$varname uses the variable varname (from session's variable)
|
|
@selectname uses the "select" 'selectname' (from the session's dialog)
|
|
|
|
Variable arrays:
|
|
$myarray[0]
|
|
$myarray[1]
|
|
...
|
|
|
|
Variable structs:
|
|
$mystruct.member1
|
|
$mystruct.member2
|
|
|
|
Core actions
|
|
============
|
|
|
|
DSM flow
|
|
--------
|
|
|
|
|
|
-- call/jump/return sub-FSM
|
|
jumpFSM(name)
|
|
callFSM(name)
|
|
returnFSM()
|
|
|
|
stop(<send bye>)
|
|
e.g. stop(false), stop(true)
|
|
|
|
-- reprocess the current event after transition:
|
|
repost()
|
|
|
|
Variable manipulation
|
|
---------------------
|
|
|
|
set($var=value)
|
|
e.g. set($var="text"); set($var=$var2); set($var=#key)
|
|
sets($var=value)
|
|
e.g. set($var="text and some $variable and some #param");
|
|
var($dstvar=srcvarname)
|
|
e.g. var($dstvar=$var_counter)
|
|
param($dstvar=srcparamname)
|
|
e.g. param($dstvar=$myparam) (like: #($myparam) )
|
|
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);
|
|
substr($var, pos)
|
|
e.g. substr($myvar, 5);
|
|
|
|
size($arrayname, $dst);
|
|
set variable $dst to size of array
|
|
(e.g. $arrayname[0], $arrayname[1] set, $dst set to 2)
|
|
|
|
inc($var)
|
|
clear($var)
|
|
clearArray($var)
|
|
clears all var.* variables
|
|
|
|
Playing prompts and file I/O
|
|
----------------------------
|
|
|
|
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(notify=true)
|
|
if notify=true, send an event
|
|
setInOutPlaylist()
|
|
set playlist as input and output
|
|
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)
|
|
|
|
DTMF
|
|
----
|
|
|
|
enableDTMFDetection()
|
|
disableDTMFDetection()
|
|
|
|
sendDTMF(key [, duration_ms])
|
|
send a DTMF event (RFC4733 event)
|
|
duration_ms defaults to 500ms
|
|
|
|
sendDTMFSequence(sequence [, duration_ms])
|
|
send a sequence of DTMF events (RFC4733 event), e.g. 123#45*1
|
|
duration_ms defaults to 500ms
|
|
|
|
B2B call control
|
|
----------------
|
|
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)
|
|
|
|
Logging
|
|
-------
|
|
|
|
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)
|
|
|
|
Timers
|
|
------
|
|
|
|
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 functions
|
|
------------
|
|
DI(factory, function [, params...])
|
|
execute DI function
|
|
e.g. DI(factory, function, $var_param, (int)int_param, "str param", @select_par, (array)arrayname, (struct)structname, (json)json_object...)
|
|
DI(user_timer, setTimer, (int)1, (int)5, @local_tag);
|
|
|
|
set($sweets.candy="nice");
|
|
set($sweets.fruit="superb");
|
|
set($sweets.cake.tahini="great");
|
|
DI(myfactory, myfunc, (struct)sweets);
|
|
|
|
set($bi[0]="ba");
|
|
set($bi[1]="butzki");
|
|
DI(myfactory, myfunc, (array)bi);
|
|
|
|
set($js="{"x":"y", "a": 1}");
|
|
DI(myfactory, myfunc, (json)$js);
|
|
|
|
* 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)
|
|
|
|
Exception handling
|
|
------------------
|
|
throw(<type>[,arg1=val1;arg2=val2;...])
|
|
e.g. throw(bad_command), throw(bad_command,cmd=help;reason=whynot)
|
|
|
|
throwOnError()
|
|
|
|
Events
|
|
------
|
|
postEvent(sess_id[, variable_name;variable_name;...])
|
|
post dsm event to session sess_id; variables copied as event parameters
|
|
e.g. postEvent(@local_tag, PAI) : post event to ourselves
|
|
postEvent($some_call, var1;var2;var3) post event with var1, var2, var3
|
|
* sets $errno (arg)
|
|
|
|
postEvent(sess_id, var)
|
|
all local variables copied as event variables
|
|
* sets $errno (arg)
|
|
|
|
registerEventQueue(queue_name)
|
|
register session to receive events under the name queue_name
|
|
WARNING: make sure to unregister the event queue before ending the session!
|
|
|
|
unregisterEventQueue(queue_name)
|
|
unregister events queue queue_name
|
|
|
|
Conditions
|
|
==========
|
|
|
|
Conditions are combined as AND, i.e. a transition is executed if all conditions match.
|
|
|
|
Generic conditions (regardless of the type of the event):
|
|
test(#key == 1)
|
|
test(#key == prefix*)
|
|
test(#key != 1)
|
|
test(#key < 1)
|
|
test(#key > 1)
|
|
|
|
test($var == 1)
|
|
test($var == prefix*)
|
|
test($var != 1)
|
|
test($var < 1)
|
|
test($var < 1)
|
|
|
|
test(len($var) < len(#key))
|
|
test(len($var) < len(@user))
|
|
|
|
Other conditions only match on the type of event and when the expression expr in the
|
|
brackets match.
|
|
|
|
hangup
|
|
bye/cancel received
|
|
parameters:
|
|
#headers - headers of the BYE/CANCEL request
|
|
|
|
key(expr) or keyTest(expr)
|
|
parameters:
|
|
#key - Key pressed (0 - 11, * is 10, # is 11)
|
|
#duration - duration of key press
|
|
|
|
timer(expr) or timerTest(expr)
|
|
parameters:
|
|
#id - Timer ID
|
|
|
|
noAudio(expr) or noAudioTest(expr)
|
|
parameters:
|
|
#type - "cleared" (audio cleared) or "noAudio" (playlist empty)
|
|
|
|
separator(expr) or separatorTest(expr)
|
|
parameters:
|
|
#id - Separator ID
|
|
e.g. separatorTest(#id == 5)
|
|
|
|
event(expr) or eventTest(expr)
|
|
generic event, e.g. passed from DI or another call with postEvent
|
|
parameters depend on the DI call/the ones passed with postEvent
|
|
|
|
keyPress(key)
|
|
alias to key(#key==key)
|
|
|
|
invite
|
|
invite received/sent (only with run_invite_event):
|
|
parameters: none
|
|
|
|
ringing
|
|
ringing reply, 180 (only with run_invite_event):
|
|
parameters:
|
|
#code - SIP response code, e.g. 180
|
|
#reason - SIP reason string, e.g. "Ringing"
|
|
#has_body - "true" or "false"
|
|
|
|
early
|
|
early session, 183 (only with run_invite_event):
|
|
parameters: none
|
|
|
|
failed
|
|
outgoing call failed (only with run_invite_event):
|
|
parameters:
|
|
#code - SIP response code, e.g. 404
|
|
#reason - SIP reason string, e.g. "Not found"
|
|
|
|
sessionStart
|
|
start of session (with run_invite_event):
|
|
parameters: none
|
|
|
|
startup
|
|
startup of a system DSM
|
|
parameters: none
|
|
|
|
reload
|
|
reload (system DSM)
|
|
|
|
system
|
|
system event - shutdown or SIGNAL sent (kill <pid>)
|
|
parameters:
|
|
#type - system event type, e.g. ServerShutdown, User1, User2
|
|
|
|
B2B.otherReply
|
|
Reply on other B2B leg received
|
|
parameters:
|
|
#code - reply code
|
|
#reason - reply reason
|
|
#hdrs - headers
|
|
|
|
B2B.otherBye
|
|
BYE on other leg received
|
|
#hdrs - headers
|
|
|
|
sipRequest
|
|
SIP request received - only executed if enable_request_events=="true"
|
|
parameters:
|
|
#method - SIP method
|
|
#r_uri - request URI
|
|
#from - From
|
|
#to - To
|
|
#hdrs - Headers (apart from dialog-IDs)
|
|
#content_type - Content-Type
|
|
#body - body of message
|
|
#cseq - CSeq
|
|
|
|
sipReply
|
|
SIP reply received - only executed if enable_reply_events=="true"
|
|
parameters:
|
|
#code - response code
|
|
#reason - reason string
|
|
#hdrs - Headers (apart from dialog-IDs)
|
|
#content_type - Content-Type
|
|
#body - body of message
|
|
#cseq - CSeq
|
|
|
|
#dlg_status - SIP dialog status (Disconnected, Trying, ...)
|
|
#old_dlg_status - old SIP dialog status (before this reply)
|
|
|
|
|
|
jsonRpcRequest - json-rpc request received
|
|
parameters:
|
|
#ev_type - JsonRpcRequest
|
|
#method - RPC method
|
|
#is_notify - "true" or "false"
|
|
#id - request ID (if present)
|
|
|
|
#params.* - parameters array
|
|
|
|
jsonRpcResponse - json-rpc response received
|
|
#ev_type - JsonRpcResponse
|
|
#id - response ID
|
|
#is_error - "true" or "false"
|
|
#udata - user data that was saved when sending the request
|
|
|
|
#result.* or #error.* - response data array (or error data)
|
|
|
|
Selects
|
|
=======
|
|
selects :
|
|
@local_tag
|
|
@user
|
|
@domain
|
|
@remote_tag
|
|
@callid
|
|
@local_uri
|
|
@remote_uri
|
|
|
|
Importing modules
|
|
=================
|
|
|
|
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)
|
|
|
|
Variables controlling call flow
|
|
===============================
|
|
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
|
|
enable_request_events "true" - run events on receiving a request
|
|
"false" - don't run events on receiveing request
|
|
|
|
|
|
=============================
|
|
errors:
|
|
actions set $errno
|
|
#define DSM_ERRNO_OK ""
|
|
#define DSM_ERRNO_FILE "1"
|
|
#define DSM_ERRNO_UNKNOWN_ARG "2"
|
|
#define DSM_ERRNO_GENERAL "99"
|
|
...
|