StarTrinity.com

VoIP software

CallXML documentation

Logic of processing SIP calls in StarTrinity VoIP software is defined by scripts written in high-level scripting programming language "CallXML". Incoming and outgoing SIP calls are processed by an engine which reads and executes CallXML elements in sequence. The CallXML elements define basic operations with the SIP call.

CallXML elements: description, attributes, examples of usage

accept Sends "200 OK" or "1xx" provisional response to incoming SIP call. Is not applicable for outgoing calls.
Sends a "488 Not Acceptable Here" response if codec negotiation failed. May contain inner "additionalMultipartContent" XML element and attribute "multipartBoundary" to send "multipart/mixed" content body (see example for "call") Attributes:
value (optional, default = "200") - SIP status code for the response. Note: "100 Trying" response is always sent, regardless of CallXML script
headers (optional) - list of custom SIP headers to be included into the response.
Example: Header1Name=Header1Value|Header2Name=Header2Value|Header3Name=Header3Value
sdpAttributes (optional) - list of custom SDP attributes to be included into the response.
Example: Attr1Name:Attr1Value|Attr2Name:Attr2Value|Attr3Name:Attr3Value
localRtpPort (optional) - explicitly set local RTP UDP port number. If empty or zero, a socket from RTP transport pool is used (see settings "MediaTransportPoolMinPort", "MediaTransportPoolMaxSocketsCountPerInterface")
localRtpAddress (optional) - explicitly set local RTP IP address, is used to select network interface. If empty, the network interface is selected by remote IP address using system routing table (WinAPI function GetBestInterface())
codec (optional) - when sending 200 OK, selects audio codec
disableRtp (optional, "true" or "false", default is "false") - disables RTP stream for the SIP call. Is used to save CPU resources by enabling RTP only for some part of generated SIP calls
<accept value="200" /> <!-- answer to SIP call -->
<accept value="183" /> <!-- send "183 Session Progress" response -->
<accept headers="WG67-Version=radio.01" sdpAttributes="R2S-KeepAlivePeriod:200|R2S-KeepAliveMultiplier:10|sigtime:1" />
<accept value="200" headers="History-Info: <SIP URL>;index=1|History-Info: <SIP URL>; index=1.1|Diversion=<sip:1111@1.1.1.1>;abc|Diversion=<sip:2222@2.2.2.2>;def" />

assign Sets new value to a variable. Variables are used to store intermediate data and to build complex logic in CallXML scripts. Variables can be accessed later in script using substitutions.
Valiables in CallXML are not typed, more specifically all have type "string" and are parsed dynamically if needed Attributes:
var (optional) - name of the variable. Variables are separated for different SIP calls
globalvar (optional) - name of the global variable. Global variables are shared between different SIP calls
value (optional) - new value for the variable. If it equals to "$rand_from_options;", the value is randomly selected from one of child XML elements (see example)
values (optional) - list of sequential values, separated by ";" (see example)
mathvalue (optional) - mathematical expression (see example). Supported operators are: ( ) * + - / ^ %. Functions: sin(x), cos(x), tg(x), ctg(x), sh(x), ch(x), th(x), sqrt(x), exp(x), (a)log(b), ln(x), abs(x)
<assign var="fileName" value="$rand_from_options;">
 <option value="wav\01.wav" />
 <option value="wav\02.wav" />
 <option value="wav\03.wav" />
</assign>
<playaudio value="$fileName;"/>
<assign var="phone" values="101;102;103" /> <!-- call numbers 101, 102, or 103 sequentially in loop -->
<call value="sip:$phone;@server.com" />
<assign var="y" value="4" />
<assign var="x" mathvalue="-(5+5*5)/$y;+sqrt(4000000)" />
<log value="x=$x;" />

block Groups CallXML elements into single block. Is used for many purposes: "if" statements, matching strings with regular expressions, loops, simulation of random behaviour.
Attributes:
test (optional) - boolean expression, specifies condition of executing internal CallXML elements repeat (optional, default is "1") - number of times to execute nested CallXML elements. If equals to "infinite", it will run until SIP call is destroyed.
var (optional) - name of variable to receive iteration counter value
probability (optional, default is "1") - propability of executing nested CallXML elements
minInterval (optional) - minimal interval between consecutive executions of the block. If time since last execution of the block is smaller than the "minInterval", the block is not executed. The "minInterval" is useful when you want to do something not for every call, but for single call every minute
<block test="$callerId;=100"> <!-- check if caller ID equals to "100" -->
 <reject value="486"> <!-- reject call with "486 Busy Here" if caller ID is "100" -->
</block>
<block probability="0.5">
 <log value="this is executed with probability 0.5" />
</block>
<log value="this is executed with probability 1" />
<block test="abc = abc">
  <log value="abc = abc - it is true" />
</block>
<block test="abc = def">
  <log value="abc = def - it is not true" />
</block>
<log value="making call to the server. it should be configured to answer to 'test' number with no delay" />
<call value="sip:test@localhost:5060" maxtime="5s" />
<on event="answer">
 <log value="call answered. aborting call" />
 <exit />
</on>
<on event="maxringtime;callfailure">
 <log value="call failed (5-sec timeout or error response). restarting server if did not restart already 3 minutes ago" />
 <block minInterval="3m">
  <sendemail value="mailto:email@gmail.com?subject=call to server failed. restarting the server" />
  <log value="restarting SIP server" />
   <!-- here you should set path to your SIP server -->
  <restartprocess value="C:\Users\User\AppData\Roaming\StarTrinity SipTester\StarTrinity.SIPTester.exe" />
 </block>
 <exit />
</on>
<log value="reporting global variables: total: $global.totalcounter;, block1 (probability 0.5): $global.block1counter;, block2 (probability 0.5*(1-0.5) = 0.25): $global.block2counter;" />
<assign globalvar="totalcounter" mathvalue="$global.totalcounter;+1" />
<block probability="0.5">
<assign globalvar="block1counter" mathvalue="$global.block1counter;+1" />
<exit />
</block>
<block probability="0.5">
<assign globalvar="block2counter" mathvalue="$global.block2counter;+1" />
<exit/>
</block>

call Initiates new outgoing call (SIP UAC session) to specified destination; optionally aborts call on time out
Raises "answer", "maxringtime", "pr", "audioSignal", "reinvite", "transferred" and "callfailure" events. On call failure sets variable "lastError" to SIP status code. Executes next CallXML element if call was aborted. Handles "3xx (Moved Temporarily)" responses and makes another call to new destination. Saves remote SIP headers into CallXML variables with prefix "sipHeader"; saves remote SDP attributes into CallXML variables with prefix "sdpAttribute". May contain inner "additionalMultipartContent" XML element and attribute "multipartBoundary" to send "multipart/mixed" content body (see example). Attributes:
value (required) - specifies SIP URI of destination. Destination host can be specified as IP address (e.g. 192.168.10.1), DNS A-record name (e.g. sip-anycast-1.voice.google.com), DNS SRV-record name (e.g. _sip._udp.sip.voice.google.com). The SIP URI may contain following query parameters:
  • "transport" - "udp" or "tcp", "udp" is default
  • "user", "password" - credentials for authentication
  • "proxyAddress", "proxyPort" - address of proxy server
  • "localSipPort" - local SIP UDP port to use for the call
  • "callerId" - user ID in 'From' header
  • "route" - if equals to "localregistrar", the SIP call is routed to an extension registered at local UAS registrar (URI is replaced by 'Contact' header of received REGISTER request)
If value equals to "$rand_from_options;" - call is made to one of randomly selected destinations in "option" children XML elements (see example). It is possible to limit number of concurrent calls per each "option" in list ("destination resource") and to build different call scenarios for different "destination resource".
If value equals to "$seq_sip_uri_from_csv(CSV_file_name[, optional csvLineStartIndex])" - destination is read from CSV file, starting from specified zero-based line index (zero line index by default).
If value equals to "$random_least_busy_uac_registration()" - call is made using UAC registrations (used when simulating calls via extensions of tested IP PBX).
to (optional) - "To" header for SIP INVITE message. If "to" is not set, it is taken from "value" SIP URI
callerId (optional, default is "unknown") -"From" header or "SIP ID" for "From" header in INVITE message. Example: "123456", "sip:123456@domain.com"
sipCallId (optional) - SIP "Call-ID" header in INVITE message. Example: "StarTrinity$id;@yourdomain.com"
sendSdpInInitialInvite (optional, "true" or "false", default is "true") - specifies whether to send SDP in SIP INVITE message. If no SDP is sent in request, and if destination also does not send SDP in response, the SIP call will be established without RTP media. If the destination sends late SDP offer in 200 OK, the caller will respond with SDP answer in ACK.
disableRtp (optional, "true" or "false", default is "false") - disables RTP stream for the SIP call. Is used to save CPU resources by enabling RTP only for some part of generated SIP calls
direction (optional, "SendOnly"/"ReceiveOnly"/"None"/"Both", default is "Both") - RTP media direction to be declared in SDP
maxringtime (optional, default is "no timeout") - timeout of waiting for call answer in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix). If "maxringtime" expires, call is aborted with CANCEL SIP message. It is max time to wait for answer, not max call duration
maxansweredtime (optional, default is "no timeout") - max call duration after answering in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix). If "maxansweredtime" expires, "maxansweredtime" event is raised. If no event handler for "maxansweredtime" exists, the call is aborted with BYE SIP message
headers (optional) - list of custom SIP headers to be included into the INVITE message.
Example: Header1Name=Header1Value|Header2Name=Header2Value|Header3Name=Header3Value
sdpAttributes (optional) - list of custom SDP attributes to be included into the INVITE message.
Example: Attr1Name:Attr1Value|Attr2Name:Attr2Value|Attr3Name:Attr3Value
codec (optional, "G711A"/"G711U"/"G723"/"G729", default is "any of supported") - RTP media codec (SDP media stream payload type) to be used for the SIP call
localRtpPort (optional) - explicitly set local RTP UDP port number. If empty or zero, a socket from RTP transport pool is used (see settings "MediaTransportPoolMinPort", "MediaTransportPoolMaxSocketsCountPerInterface")
localRtpAddress (optional) - explicitly set local RTP IP address, is used to select network interface. If empty, the network interface is selected by remote IP address using system routing table (WinAPI function GetBestInterface())
var (optional) - name of variable where to save SIP status code of the call
testId (optional) - Test ID to be passed into "Test ID" CDR column
terminatorId (optional) - ID of terminator to associate with the new call
<call maxringtime="10s" callerId="101" value="sip:100@localhost:5070" headers="Diversion=TestD|Header2=HeaderValue2" />
<call maxringtime="10000ms" callerId="$Id;" value="sip:100@localhost:5070"
  headers="Diversion=&lt;sip:+1234567890@BC05.MSCTG01;user=phone&gt;;reason=unknown" />
<call value="sip:111@192.168.1.1" callerId="222"
  headers="Subject=radio|Priority=normal|WG67-Version=radio.01"
  sdpAttributes="R2S-KeepAlivePeriod:200|R2S-KeepAliveMultiplier:10|sigtime:1" />
<call value="sip:test@localhost" multipartBoundary="-----border----">
<additionalMultipartContent>
<![CDATA[
Content-ID: $id;@ng123.com
Content-Type: application/pidf+xml
Content-Transfer-Encoding: 8bit

<?xml version="1.0" encoding="ISO-8859-1"?>
<presence xmlns="urn:ietf:params:xml:ns:pidf"
xmlns:gp="urn:ietf:params:xml:ns:pidf:geopriv10"
xmlns:cl=" urn:ietf:params:xml:ns:pidf:geopriv10:civicLoc"
xmlns:gml="urn:opengis:specification:gml:schema-xsd:feature:v3.0"
entity="sip:caller1@ngsos.com">
<tuple id="id56345">
<status>
<gp:geopriv>
<gp:location-info>
<gml:location>
<gml:Point>
<gml:pos>$rand(30,40);.$rand(1,99999); -$rand(67,78);.$rand(1,99999);</gml:pos>
</gml:Point>
</gml:location>
</gp:location-info>
<gp:method>Manual</gp:method>
</gp:geopriv>
</status>
<contact priority="0.8">sip:abcd@4.5.6.7:5060</contact>
<timestamp>$time();</timestamp>
</tuple>
</presence>
]]>
</additionalMultipartContent>
</call>
<on event="answer">
 <playaudio value="music.wav" maxtime="10s" />
 <exit />
</on>
<call value="$rand_from_options;" callerId="sipTester" maxringtime="$rand(5000);ms" sendSdpInInitialInvite="true">
  <option value="sip:test@10.10.10.1:5060?transport=tcp" maxCallsPerDestinationResource="100"
    destinationResourceId="server1" />
  <option value="sip:test@10.10.10.2:5060?transport=tcp" maxCallsPerDestinationResource="200"
    destinationResourceId="server2" />
</call>
<on event="answer">
 <log value="call answered. resource ID = $destinationResourceId;" />
 <wait value="5s" />
 <exit />
</on>
<call maxringtime="30s" callerId="sip:test@192.168.1.10" value="sip:100@192.168.1.9:5060" />
<call callerId="&quot;AAA&quot; &lt;sip:TEST@192.168.1.10&gt;" value="sip:444@192.168.1.10:5060" />
<call maxringtime="10000ms" callerId="" value="sip:100@localhost:5070" sendSdpInInitialInvite="true"
headers="History-Info: <SIP URL>;index=1|History-Info: <SIP URL>; index=1.1|H1=<sip:1111@1.1.1.1>;abc|H1=<sip:2222@2.2.2.2>;def" />
<!-- make a SIP call with custom Conact header -->
<call value="sip:test@ims.mnc222.mcc302.abc.org" headers="Contact=sip:4087890001@ims.mnc222.mcc302.abc.org;q=0.5;+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.largemsg"|P-Asserted-Service=urn:urn-7:3gpp-service.ims.icsi.abc.cpm.largemsg|Accept-Contact=+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.abc.cpm.largemsg"" />

callgroup Initiates call to group of SIP phones. "parallel", "sequential", "queue" modes of calling phones are available.
Attributes:
value (required) - name of call group
ringbacktone (optional) - audio file name which is played to caller until call is answered
<callgroup value="worktime" ringbacktone="C:\wav\please_wait_for_answer.wav" />
<exit/>
<callgroups>
 <callgroup name="worktime" userName="" mode="parallel" >
  <callgroupitem value="sip:100@10.10.10.1" maxringtime="30s" />
  <callgroupitem value="sip:101@10.10.10.1" maxringtime="30s" />
  <callgroupitem value="sip:102@10.10.10.1" maxringtime="30s" />
 </callgroup>
</callgroups>

case Is used within "switch". Defines an option which can be executed
See also: "switch", "default" Attributes:
equals (optional) - specifies a value to check equality
startsWith (optional) - specifies prefix
from (optional) - specifies lower inclusive bound for the value
to (optional) - specifies upper inclusive bound for the value
probability (optional) - specifies probability for the case. Sum of "probabily" values for all "case" elements in "switch" is normalized

checktime Checks current time, raises event if it matches to some schedule, or puts a value to a variable
Parameters of schedule are set by "span" XML elements (see example). "daystart" and "daystop" of the spans can be within same day or over midnight. Attributes:
var (optional) - name of variable where to save "value" attribute of selected time span (see example). if not set, the "checktime" raises "time_matches" event
<checktime>
 <span weekdays="mon,tue,wed,thu,fri" daystart="09:00" daystop="13:00" /> <!-- work days, 9AM ... 1PM -->
 <span weekdays="mon,tue,wed,thu,fri" daystart="14:00" daystop="18:00" > <!-- work days, 2PM ... 6PM -->
  <span daystart="15:10" daystop="15:20" value="false" /> <!-- except 3:10PM ... 3:20PM -->
 </span>
 <span date="2015.01.01" value="false" priority="1" /> <!-- except January 1, 2015 -->
</checktime>
<on event="time_matches" >
<!-- accept the call if the schedule worked -->
 <playaudio value="wav\welcome.wav" />
 <transfer value="techSupport" />
 <exit />
</on>
<playaudio value="wav\out_of_schedule.wav" />
<exit />
<assign var="ncalls" value="100" />
<checktime var="ncalls">
 <span weekdays="mon,tue,wed,thu,fri" daystart="09:00" daystop="13:00" value="150" />
 <span weekdays="mon,tue,wed,thu,fri" daystart="14:00" daystop="18:00" value="200" />
 <span date="2015.11.01" value="300" />
 <span date="2015.11.07" value="355" />
</checktime>
<log value="setting max concurrent calls = $ncalls;" />
<setcallgeneratorparams maxconcurrentcalls="$ncalls;" />

conference Connects a call with other calls in conference room
Raises "callsJoinedInConference", "maxTimeToWaitForOtherCallsInConference", "callsLeftConference" events. See also "ifconferenceexists" Attributes:
value (required) - ID of conference
direction (optional, "SendOnly"/"ReceiveOnly"/"None"/"Both", default is "Both") - audio direction between SIP call and conference room.
syncDestroy (optional, "true"/"false", default is "false") - specifies whether to destroy all other calls in conference when current call is destroyed
syncDestroyDelay (optional, default is "0ms") - specifies delay before destroying other calls in conference if "syncDestroy" is "true"
maxTimeToWaitForOtherCalls (optional, default is "infinite") - specifies a timeout of waiting for other calls to join the conference. If calls are joined, a "callsJoinedInConference" event is raised. If the timeout expires, "maxTimeToWaitForOtherCallsInConference" event is raised. The attribute and events are used to build a logic of billing calls only when there are 2 or more calls in conference (see example script).
<conference value="01" />
<assign var="ParentSessionID" value="$id;"/>
<assign var="NumToCall" value="sip:152@192.168.0.56" />
<run var="secondarySessionId" >
  <call value="$NumToCall;" to="$NumToCall;" callerId="123" maxringtime="100s" />
  <on event="answer" >
    <sendevent value="answer" session="$parentSessionId;" />
    <conference value="$Id;" />
  </on>
  <on event="callfailure">
   <log value="call failed with status $lastError;" />
   <sendevent value="callfailure" session="$parentSessionId;" />
  </on>
</run>
<playaudio value="ringbacktone.wav" />
<on event="externalevent:answer" >
 <accept />
 <conference value="$eventsenderId;" />
</on>
<on event="externalevent:callfailure" >
 <exit />
</on>
<accept value="183"/>
<log value="sent 183 session progress for incoming call. playing ringback tone" />
<playaudio value="music.wav" dontwait="true" />
<log value="adding to conference, setting a timer of 10 seconds to wait for other calls to join the conference" />
<conference value="conference01" maxTimeToWaitForOtherCalls="10s" />
<on event="maxTimeToWaitForOtherCallsInConference">
 <log value="wait timer expired. rejecting with 503" />
 <reject value="503" />
</on>
<on event="callsJoinedInConference">
 <log value="2 or more calls joined in conference. sending 200 OK to start billing" />
 <stopaudio />
 <accept value="200" />
</on>
<conference value="01"/>
<on event="dtmf:1">
 <playaudio value="you_pressed_1.wav" />
</on>
<on event="dtmf:2">
 <disconnect /> <!-- this aborts the call -->
</on>

default Is used within "switch". Defines an option which is executed when no matching "case" element is found
See also: "switch", "case" Attributes:
[None]

dequeue Gets an element from a global queue and saves it to variables. If no element is found, empty values are saved
An "element" in the global queue is a raw array of values, 0..N. Attributes:
queueId (optional) - idenfier of the global queue
var0, var1, ... (multiple) - variables where to save dequeued element's values
exceptValue0, exceptValue1, ... (multiple) - filter for dequeued element's values
onlyValue0, onlyValue1, ... (multiple) - filter for dequeued element's values
<accept value="200" />
<enqueue value0="$sipCallId;" value1="$id;" />

<dequeue label="dequeue" var0="peerCallId" var1="peerSessionId" exceptValue0="$sipCallId;" />
<if test="'$peerCallId;' = ''">
  <wait value="3s" />
  <if test="$movedConferenceByPeerCall; = 1"> <log value="don't dequeue: already moved to conference" /> <wait /> </if>
  <goto value="dequeue" />
</if>

<dequeue onlyValue0="$sipCallId;" />
<assign var="conferenceId" value="$sipCallId;" />
<log value="connecting 2 calls: this call $sipCallId; peer call $peerCallId; session $peerSessionId;. conference ID = $conferenceId;" />

<sendevent session="$peerSessionId;" value="conference" />
<conference value="$sipCallId;" />
<on event="externalevent:conference">
  <assign var="movedConferenceByPeerCall" value="1" />
  <log value="joining to conference $conferenceId;" />
  <conference value="$conferenceId;" />
</on>

disableuacregistration Disables UAC registration for a specified period of time, so it will not be used for calls
Attributes:
value - SIP user ID of the UAC registration
maxtime - period to disable the item
<call value="$random_least_busy_uac_registration();" >
 <on event="callfailure" >
  <log value="call failed with status = $eventSubType;. temporarily disabling extension $callerId;" />
  <disableuacregistration value="$callerId;" maxtime="30m" />
 </on>
</call>

disconnect Terminates SIP call if it is created and not terminated yet. Sends BYE or CANCEL SIP message.
Does not terminate execution of CallXML script.
Attributes:
[none]
<disconnect />

dynamicblacklist Adds the specified number into RAM-based blacklist, checks if number of attempts exceed some specified threshold. Executes internal CallXML elements if the number gets blocked
Attributes:
id (required) - idenfier of the blacklist. The system may have multiple blacklists
maxtime (required) - max time to store the numbers in the list. Example: 60s, 60m, 24h
maxcount (required) - max number of occurences of the specified number in the list to block the call
value (required) - the number
var (optional) - name of variable where to save number of occurences in the list, if the number gets blocked
<dynamicblacklist id="01" maxtime="60s" maxcount="1" value="$calledId;" var="numAttempts">
<log value="$calledId; is blocked, number of attempts = $numAttempts;" />
<reject />
<exit />
</dynamicblacklist>
<log value="$calledId; is passed" />

else Is used after "if"; is executed if the test condition is false
Attributes:
[none]

enqueue Adds an element to a global queue
Attributes:
queueId (optional) - idenfier of the global queue
value0, value1, ... (multiple) - element's values to add into the queue. An element in the queue is an array of values: "value0" .. "valueN"
<accept value="200" />
<enqueue value0="$sipCallId;" value1="$id;" />

<dequeue label="dequeue" var0="peerCallId" var1="peerSessionId" exceptValue0="$sipCallId;" />
<if test="'$peerCallId;' = ''">
  <wait value="3s" />
  <if test="$movedConferenceByPeerCall; = 1"> <log value="don't dequeue: already moved to conference" /> <wait /> </if>
  <goto value="dequeue" />
</if>

<dequeue onlyValue0="$sipCallId;" />
<assign var="conferenceId" value="$sipCallId;" />
<log value="connecting 2 calls: this call $sipCallId; peer call $peerCallId; session $peerSessionId;. conference ID = $conferenceId;" />

<sendevent session="$peerSessionId;" value="conference" />
<conference value="$sipCallId;" />
<on event="externalevent:conference">
  <assign var="movedConferenceByPeerCall" value="1" />
  <log value="joining to conference $conferenceId;" />
  <conference value="$conferenceId;" />
</on>

exec Parses string as CallXML script and executes it. Is similar to "eval" in JavaScript
Attributes:
value (required) - the CallXML script as string. It can be dynamically computed
<assign var="xml" value="&lt;log value=&quot;test" /&gt;" />
<exec value="$xml;" />

exit Terminates SIP call if it is created and not terminated yet. Sends BYE or CANCEL SIP message.
Terminates execution of CallXML script.
Attributes:
[none]
<exit />

exitcli Terminates current command-line-mode SIP Tester. Is used to pass result of testing to .bat script
See also: "setexitcode" Attributes:
value (optional) - process exit code
graceful (optional, "true"/"false", default "false") - "true" to stop call generator and to wait for all current calls to complete
<exitcli value="777" />

function Defines a function or subroutine. Is executed with "runfunction".
Session variables, global variables and parameters are shared between caller code and the function's code, there is no "function scope". There is only a "flat context" of variables. Functions enable to have all of repetitive code, like initiating environment, in one place. Attributes:
name (required) - unique name of function
[parameters] (optional, "in[;defaultValue]" or "out") - names and types of parameters. There are "in" (input) and "out" (output) types of function parameters. Input parameters may have default values (separated by semicolon); otherwise input parameters are required when running the function. Output parameters contain name of variable
<function name="func1" param1="in" param2="in" resultvar="out" >
 <log value="func1: param1 = $param1;, param2 = $param2;" />
 <assign var="resultvar" value="$param1;: OK" />
</function>

<runfunction name="func1" param1="TestValue1" param2="TestValue2" resultvar="result" />
<log value="result=$result;" />

getaudiofilelength Reads WAV or MP3 audio file, calculates its duration, saves result to variable
Attributes:
value (required) - absolute or relative path to audio file(s), separated by semicolon. If multiple files are specified, minimal duration is saved as result
var (required) - name of CallXML variable where to save audio length in milliseconds.
<getaudiofilelength value="music.wav" var="length" />
<log value="length = $length;ms" />

getcallgeneratorparams Saves call generator parameters into CallXML variables.
Attributes:
maxcpsvar (optional) - name of CallXML variable to save max calls per second
maxconcurrentcallsvar (optional) - name of CallXML variable to save max concurrent calls
<getcallgeneratorparams maxcpsvar="maxcps" maxconcurrentcallsvar="nchannels" />
<log value="current params of call generation: max cps = $maxcps;, num of channels = $nchannels;" />

getcallinfo Saves call information into CallXML variables.
Attributes:
codecvar (optional) - name of CallXML variable to save name of current codec
<accept value="183"/>
<getcallinfo codecvar="codec" />
<log value="received call with codec = $codec;" />

getcdrcallscount Queries CDR with specified query expression and saves number of returned records into a variable
Attributes:
expression - boolean expression to query CDR
period (optional) - identifies CDR search period. Example: 24h - query calls in recent 24 hours
var - name of CallXML variable to save the number of queried calls
<getcdrcallscount expression="CalledId = 123456" var="c" period="24h"/>
<log value="there are $c; calls in CDR with specified criteria in recent 24 hours" />
<getcdrcallscount expression="MyCustomCdrHeader = SomeValue" var="c" period="24h"/>
<log value="there are $c; calls in CDR with specified criteria in recent 24 hours" />
<writecdr header="MyCustomCdrHeader" value="SomeValue"/>

getfilenamefrompath Parses full file path, extracts file name
Attributes:
value (required) - input file name with path
var (required) - name of CallXML variable to save file name without path
<getfilenamefrompath var="fn" value="c:\path\file.txt" />
<log value="file name = $fn;" />

getstatistics Gets statistics about processed SIP calls
Saves statistics into CallXML variables:
incomingCps1s, incomingCps10s, incomingCps100s - incoming calls rate per second, averaged by 1, 10 and 100-second filters
outgoingCps1s, outgoingCps10s, outgoingCps100s - outgoing calls rate per second, averaged by 1, 10 and 100-second filters
answeredCallsCount - total number of answered calls
answeredCallsAverageDuration - average answered duration (in seconds)
currentAnsweredCallsCount - number of answered calls at current time
currentCallsCount - number of concurrent calls at current time
See also: resetstatistics
Attributes:
[none]
<getstatistics />
<log value="incomingCps1s = $incomingCps1s;; incomingCps10s = $incomingCps10s;; incomingCps100s = $incomingCps100s;" />
<log value="outgoingCps1s = $outgoingCps1s;; outgoingCps10s = $outgoingCps10s;; outgoingCps100s = $outgoingCps100s;" />
<log value="answeredCallsCount = $answeredCallsCount; answeredCallsAverageDuration = $answeredCallsAverageDuration; currentAnsweredCallsCount = $currentAnsweredCallsCount; currentCallsCount = $currentCallsCount;" />

getstringlength Calculates length of a string/number in characters/digits
Saves result into CallXML variable Attributes:
value (required) - input string
var (required) - name of variable where to save result
<getstringlength value="$calledId;" var="callerIdLength" />
<log value="Called ID length = $callerIdLength;" />

getwg67info Saves WG-67 RTP header extension data into CallXML variables. Measures round-trip delay time if peer SIP-UA has PTT-SQU loopback connection
Attributes:
ptt2squdelayvar (optional) - name of CallXML variable to save measured round-trip delay time [in milliseconds]
ptttypevar (optional) - name of CallXML variable to save WG-67 PTT-type field from RX stream
pttidvar (optional) - name of CallXML variable to save WG-67 PTT-ID field from RX stream
squvar (optional) - name of CallXML variable to save WG-67 SQU field from RX stream
pmvar (optional) - name of CallXML variable to save WG-67 PM field from RX stream
pttsvar (optional) - name of CallXML variable to save WG-67 PTTS field from RX stream
sctvar (optional) - name of CallXML variable to save WG-67 SCT field from RX stream
<!-- script for UAC side: make a call, play RTP extension sequence, measure delay and save data to CDR -->
<call value="sip:111@devpc:5070" callerId="1111" />
<on event="answer">
 <setrtpextension wg67_pttType="1" wg67_pttId="16" />
 <playaudio value="music.wav" maxtime="3s" />
 <setrtpextension wg67_pttType="0" wg67_pttId="16" />
 <playaudio value="music.wav" maxtime="3s" />
 <getwg67info ptt2squdelayvar="ptt2squdelay" ptttypevar="ptttype" pttidvar="pttid" squvar="squ" pmvar="pm" pttsvar="ptts" sctvar="sct" />
 <log value="WG67 measurements: ptt2squdelay=$ptt2squdelay;ms, ptttype=$ptttype;, pttid=$pttid;, squ=$squ;, pm=$pm;, ptts=$ptts;, sct=$sct;" />
 <writecdr field="RX_WG67_PTT_ID" value="$pttid;" />
 <writecdr field="RX_WG67_PTT2SQU_DELAY" value="$ptt2squdelay;" numeric="true" qualityIsAscending="false" />
<!-- save measured delay to CSV CDR file, GUI report and history charts on "reports/statistics" tab -->
 <exit />
</on>

<!-- script for UAS side: accept the call and set up PTT->SQU loopback connection -->
<accept />
<setrtpextension wg67_pttType="1" wg67_pttId="33" wg67_squ="rxptt" wg67_pm="0" wg67_ptts="0" wg67_sct="0" />
<playaudio value="music2.wav" repeat="infinite" maxtime="60s" />
<exit />

goto Performs one-way transfer of control to another CallXML element with specified "label".
Attributes:
value (required) - destination CallXML element "label" attribute
test (optional) - boolean expression, specifies condition of transfer
<goto value="play_music1" test="$callerId; = 100" />
<goto value="play_music2" test="$callerId; = 101" />
<reject />
<block label="play_music1" >
  <playaudio value="music1.wav" />
  <exit />
</block>
<block label="play_music2" >
 <playaudio value="music2.wav" />
 <exit />
</block>

if Executes internal CallXML elements if specified conditions are satisfied
Optionally executes internal elements of "else", which should be placed after "if" Attributes:
test (required) - boolean expression, specifies condition of executing internal CallXML elements. Syntax of condition is following:
<if test="abc = abc">
 <log value="abc = abc - it is true" />
</if>
<else>
 <log value="abc != abc - it is not true" />
</else>

<if test="abc = def">
 <log value="abc = def - it is not true" />
</if>
<else>
 <log value="abc != def - it is true" />
</else>

<if test="abc = abc and def = def">
 <log value="abc = abc AND def = def - it is true" />
</if>
<accept />
<if test="$callerId; startswith 44 or $callerId; startswith +44">
 <log value="Caller ID starts with 44 or +44" />
 <playaudio value="IVR1.wav" />
 <exit />
</if>
<if test="$callerId; startswith 1 or $callerId; startswith +1" >
 <log value="Caller ID starts with 1 or +1" />
 <playaudio value="IVR2.wav" />
 <exit />
</if>
<log value="some unknown Caller ID: $callerId;" />
<playaudio value="IVR3.wav" />
<exit />

ifcallexists Executes internal CallXML elements if a SIP sall with specified criteria exists in current calls or in call history
You can check if call exists at another (remote) instance of SIP Tester by sending a HTTP API request, see in "sendhttprequest" examples Attributes:
sipCallId (optional) - SIP Call-ID
callerId (optional) - SIP User ID in "From" header
calledId (optional) - SIP User ID in "To" header
expression (optional) - CDR filter boolean expression, when querying call history. It must be constant, for callerId and calledId filters use corresponding attributes
considerThisCall (optional, "true" or "false", default "true") - specifies whether to consider current call when searching for the matching call
<assign label="generate_new" var="from" value="$rand(1000,1005);" />
<ifcallexists callerId="$from;" >
 <goto value="generate_new" />
</ifcallexists>
<call value="sip:test@10.10.10.10" callerId="$from;" />
<ifcallexists query="CalledId = $calledId;" >
 <log value="this number has already been called" />
</ifcallexists>

ifconferenceexists Executes internal CallXML elements if conference with specified ID currently exists
Attributes:
value (required) - ID of conference
<ifconferenceexists value="$confId;">
 <accept />
 <conference value="$confId;" />
</ifconferenceexists>
<reject value="503"/>

include Reads and executes another CallXML file. Returns control to current file after the execution. Imports functions from included file.
The included file is read from disk or obtained from memory cache only when CallXML flow reaches the "include" element. Included file name could be dynamically calculated. File must have ASCII encoding Attributes:
value (optional) - absolute or relative path to included CallXML file. It can be dynamically calculated
httpUrl (optional) - HTTP URL of included CallXML file. It can be dynamically calculated
cache (optional, "true" or "false", default "true") - specifies whether to use previously cached included file from memory or not. By default the "include" uses cached copy of callXML file and asynchronously starts to update the cache from disk, so the CallXML flow is not delayed with file access operation
<include value="CustomScripts\script1.xml" />
<switch value="$callerId">
 <case startsWith="198" > <include value="params198.xml" /> </case>
 <case startsWith="199" > <include value="params199.xml" /> </case>
</switch>

<playaudio value="$param.greeting;" />

inputdigits Collects digits and saves them into variable
Attributes:
value (optional) - absolute or relative audio file name to be played
repeat (optional, default is "1") - number of times to repeat audio file
var (required) - name of variable to save entered digits
maxdigits (optional) - max number of entered digits
finalkey (optional) - terminating key which ends the entry of digits
maxsilence (optional, default is "infinite") - time interval of waiting for DTMF digits after end of playing audio file. Is set in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix).
<inputdigits value="C:\wav\enter_phone_and_press_pound_key.wav" finalkey="#" var="enteredNumber" maxsilence="20s" maxdigits="10" />
<transfer value="sip:$enteredNumber;@192.168.1.4" />
<accept />
<inputdigits var="d" maxsilence="20s" />
<writecdr header="digits" value="$d;" />

inputspeech Recognizes voice (speech) to text and saves the text into variable
Uses Google Speech API v2 for IVR speech recognition. Please set settings "GoogleSpeechAPIv2Key" and "GoogleSpeechAPIv2Language" to make the API work. Note: you should use a "beep" sound to indicate start of recording to avoid clipping of input speech Attributes:
maxtime (required) - time of initial recording before sending the recorded audio to API. Example: "5s"
var (required) - name of variable to save recognized text
recognizingAudio (optional) - audio file to play while recognition is in progress (after initial recording)
<playaudio value="say_name.wav" />
<playaudio value="beep.wav" dontwait="true" />
<inputspeech var="t" maxtime="5s" />
<switch value="$t;">
  <case equals="Sales"> <transfer value="sip:101@10.10.10.10" /> </case>
  <case equals="Support"> <transfer value="sip:102@10.10.10.10" /> </case>
</switch>

log Writes a message to GUI or CLI and to file log. Is used for debugging and reporting.
Attributes:
value (required) - text message to be written into log
level (optional, "debug"/"error", default "debug") - if "error", writes output to "stderr" stream instead of "stdout"
<log value="processing call from '$callerId;'" />

loopbackaudio Plays received (RX stream) RTP audio back to SIP call (TX stream). Is used to verify audio path.
Attributes:
maxtime (optional, default is "infinite") - time of playing. Is set in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix).
<accept value="200" /> <loopbackaudio />

measuresignal Measures min and max audio level of RX RTP stream. Saves result to variables.
Attributes:
maxtime (required) - time of measurement. Is set in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix)
maxlevelvar (optional) - name of variable to save maximal (peak) signal level in decibels
<accept />
<measuresignal maxlevelvar="max" maxtime="1s" />
<log value="measured audio level for incoming call: max=$max;dB" />
<!-- display measured level in reports and CDR -->
<writecdr header="maxLevelDb" value="$max;" numeric="true" qualityIsAscending="true" />

movingAverageGet Gets output of a "moving average", saves it to variable
Attributes:
id (required) - identifies the "moving average"
var (required) - name of variable where to save the output
See example here

movingAveragePut Puts a value into a "moving average", configures number of samples to store for the calculation
Attributes:
id (required) - identifies the "moving average"
size (required) - specifies number of samples to store in the "moving average"
value (required) - input value
See example here

movingAverageReset Resets a "moving average", i.e. removes all previously stored values from memory
Attributes:
id (required) - identifies the "moving average"
See example here

on Handles CallXML events. Sets variable "eventType" and "eventSubType"
The "on" event handler is searched in child XML elements of current element and also in all sibling and parent XML elements Attributes:
event (required) - type and optionally subtype of the handled event. Types of events are following:
  • answer - answering of outgoing call
  • callfailure - receiving error response for outgoing call
  • dtmf - receiving DTMF signal. Warning: the call flow must not exit an element which is being used to wait for the DTMF event, otherwise it will generate a duplicate CallXML flow in the script
  • error - system error
  • hangup - termination of current SIP call by remote side
  • maxringtime - ringing timeout
  • pr - receiving provisional response (1xx) to INVITE
  • reinvite - receiving a RE-INVITE from remote side
  • sipinfo - receiving SIP INFO
  • sr - recognizing voice command
  • transferred - answering of outgoing call, which was initiated by receiving REFER
The "event" may contain multiple event types separated by ";". Example: "maxringtime;callfailure"
<call callerId="123456" value="sip:7890123@192.168.1.57:5060" > <!-- send INVITE to destination SIP server and check its availability -->
 <on event="answer"> <!-- handle 'answer' event which means receiving 200 OK from destination -->
   <block test="$global.available; != true"> <!-- don't send same email twice -->
    <assign globalvar="available" value="true" />
    <sendemail value="mailto:username@gmail.com?subject=sip testing - OK&amp;body=received 200 OK response from server" />
   </block>
   <exit />
 </on>
 <on event="callfailure"> <!-- handle 'callfailure' event which means receiving error response from server or not receiving response on timeout -->
  <block test="$global.available; != false"> <!-- don't send same email twice -->
   <assign globalvar="available" value="false" />
   <sendemail value="mailto:username@gmail.com?subject=sip testing - call failed with status $eventSubType;&amp;body=call failed with status $eventSubType;"/>
  </block>
  <exit/>
 </on>
</call>
<log value="making call to the server. it should be configured to answer to 'test' number with no delay" />
<call value="sip:test@localhost:5060" maxringtime="5s" />
<on event="answer">
 <log value="call answered. aborting call" />
 <exit />
</on>
<on event="maxringtime;callfailure">
 <log value="call failed (5-sec timeout or error response). restarting server if did not restart already 3 minutes ago" />
 <block minInterval="3m">
  <sendemail value="mailto:email@gmail.com?subject=call to server failed. restarting the server" />
  <log value="restarting SIP server" />
   <!-- here you should set path to your SIP server -->
  <restartprocess value="C:\Users\User\AppData\Roaming\StarTrinity SipTester\StarTrinity.SIPTester.exe" />
 </block>
 <exit />
</on>

params Declares parameters for the script
Parameters are read-only, their purpose is to have user-editable configurations for script in a separated place. There can be multiple declarations of params in script. The params can be declared in an included callxml file, or in parent callxml file. Params aren't like variables. They are the one (or few) section(s) of the code, where the adjustable params are. Attributes:
[none]
<params>
 <param name="param1" value="value1" />
 <param name="param2" value="value2" />
</params>

<log value="param1 = $param.param1;. param2 = $param.param2;" />

param Is used within "params"; defines a parameter which can be used later in script
Attributes:
name (required) - name of the parameter
value (required) - value of the parameter

performAAA Performs authentication, authorization and accounting for an incoming SIP call
Uses integrated billing engine, 'Originator' entities
Attributes:
var (optional) - variable where to save authenticated originator ID
<!-- simplest softswitch script for GSM termination and wholesale -->
<performAAA />
<accept value="183" />
<transfer terminators="routed" />

playaudio Plays audio file from specified WAV or MP3 file. Exits on end of file or end of silence (if "maxsilence" is specified), unless "dontwait" is set to "true"
The files are pre-cached into memory before playback, at startup time. If file name is dynamic and the audio file does not exist in the cache, it is cached at runtime. The caching includes reading audio file from disk and encoding it into RTP payload using appropriate codec. When transferring (in Softswitch), the audio is played to both call legs: A and B (if available).
Attributes:
value (required) - absolute or relative audio file name. If relative file name is specified, in multitenant mode first it tries to locate a tenant-specific audio file in \[tenantId]\ subfolder, and if it is not found, it uses file from program root folder
maxtime (optional, default is "unlimited") - max time of playing. Is set in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix).
repeat (optional, default is "1") - number of times to repeat audio file
conference (optional) - ID of conference where to play audio file. If not set, audio file is played only to current SIP call
dontwait (optional, "true"/"false", default is "false") - if set to "true", control is returned immediately, before ending of audio file. In this case audio is still played during execution of next CallXML elements. It can be stopped using "stopaudio"
<playaudio value="C:\music\01.mp3" maxtime="10m" repeat="infinite" >
<log value="making call to server" />
<call callerId="test" value="sip:9999@server.com:5060" codec="G711A" />
<on event="pr:183">
 <log value="received 183 Session Progress, playing early media to the server" />
 <playaudio value="C:\early_media_tx.wav" dontwait="true" />
</on>
<on event="answer">
 <log value="call answered" />
 <exit />
</on>
<accept value="183" /> <playaudio value="ringbacktone.wav" dontwait="true" /> <!-- do something here: request database, read from file, etc --> <stopaudio /> <accept value="200" />

playdtmf Sends one or many DTMF digits to current SIP call. Returns control immediately. If "UseRFC2833ToSendDTMF" setting is set to "1", sends DTMF within RTP stream (according to RFC2833), otherwise uses SIP INFO method
Attributes:
value (required) - DTMF digits to send. If more than one digits are specified, time between digits is set by "DtmfSendingIntervalMs" setting (default is 200ms). The value may contain 'p' character which means 1-second pause between DTMF digits
signaldelayvar (optional) - name of variable where to save audio response delay value in milliseconds. If set, the "playdtmf" waits for audio response with signal level "DefaultSignalDetectorThresholdDb" (set in settings).
<playdtmf value="1">
<wait value="500ms">
<playdtmf value="2">
<wait value="1000ms">
<playdtmf value="34p5">
<wait value="$rand(10,5000);ms"> <playdtmf value="#">
<playdtmf value="1">
<playaudio value="played_1.wav"> <!-- play audio file to hear it in recording, for debugging purposes -->
<wait value="5000ms">
<playdtmf value="2">
<playaudio value="played_2.wav">
<wait value="10000ms">
<playdtmf value="1" />
<log value="sent DTMF digit 1" />
<waitforsignal signaldelayvar="ivrDelay"/>
<log value="IVR response in RTP audio is $ivrDelay;ms" />
<playdtmf value="1" signaldelayvar="ivrDelay" />
<log value="IVR response in RTP audio is $ivrDelay;ms" />

readcsv Reads a row from CSV file, stores fields into variables
Progress of reading the CSV file is displayed in SIP Tester's GUI on "reports/statistics" tab. If the entire CallXML script is executed, but “readcsv" element is not executed, the CSV reader is left in current position. CSV readers are shared between sessions, file data is cached into memory. CSV file must have ASCII encoding. CSV fields delimiter is taken from "CsvDelimiter" global setting. See also: "readdb" Attributes:
value (required) - absolute or relative CSV file name
var[columnIndex] (required) - names of variables to store fields from row. Zero-based [columnIndex] identifies column.
mode (optional, "sequential"/"random", default is "sequential") - mode of reading rows in CSV file
countsColumnIndex (optional) - zero-based index of column which contains count of reads for each row. Is used to read some rows more than one time.
skipHeaders (optional, "true"/"false", default is "false") - indicates whether to skip first row with headers
repeat (optional, default is "1") - number of times to repeat the whole CSV file. "infinite" to repeat file infinitely
eofMode (optional, "error" or "emptyValues", default "error") - specifies what to do when there are no more rows to read in file (EOF) and when "repeat" counter is finished, also when "rowIndex" is out of bounds. "error" - raises 'error' event; "emptyValues" - return empty field values
rowIndex (optional) - zero-based row index. If not set, global pointer is used. The global counter is incremented with every read.
<readcsv value="c:\list.csv" var0="resultField0" var1="resultField1" var2="resultField2" repeat="3" />
<on event="error">
 <log value="CSV EOF, 3 times repeated all rows" />
</on>
<readcsv value="list.csv" var0="callerIdFromCsv" var1="calledIdFromCsv" countsColumnIndex="2" mode="random" />
<call value="sip:$calledIdFromCsv;@10.10.10.1" callerId="$callerIdFromCsv" />
<readcsv value="c:\01.csv" mode="random" var0="dialNumber" var1="cli" var2="pin" skipHeaders="true" repeat="infinite" />
<call value="sip:$dialNumber;@10.10.10.10:5060" callerId="$cli;" />
<on event="answer">
 <wait value="500ms" />
 <playdtmf value="$pin;#" />
 <playaudio value="$randswitch(c:\01.wav,c:\02.wav,c:\03.wav);" maxtime="$rand(10,20);s" />
 <exit />
</on>
<switch>
 <case probability="50" >
  <call maxringtime="7000ms" value="$seq_sip_uri_from_csv(C:\Users\Administrator\Desktop\Data\XXXXXXXXXXX.csv, 1);" />
 </case>
 <case probability="50" >
  <call maxringtime="7000ms" value="$seq_sip_uri_from_csv(C:\Users\Administrator\Desktop\Data\YYYYYYYYYYY.csv, 1);" />
 </case>
</switch>
<on event="answer">
 <playaudio value="music.wav" maxtime="10s" />
 <exit />
</on>
<!-- the script is used to generate test VoIP traffic to multiple countries via multiple servers (your softswitches), reading A and B numbers from
separate CSV files (one CSV file per country). CSV files contain 2 columns: B number (called ID) in 1st column and A number (caller ID) in 2nd column.
The scripts limits number of concurrent calls (channels) per country. When call is answered, a random audio is played from directory with wav files -->

<readcsv value="C:\StarTrinity\CSV\Morocco160125.csv" var0="f0_1" var1="f1_1" repeat="infinite"/>
<readcsv value="C:\StarTrinity\CSV\Lybia160125.csv" var0="f0_2" var1="f1_2" repeat="infinite"/>
<call maxringtime="35000ms" value="$rand_from_options;" codec="G729" >
 <option value="sip:$f0_1;@[ip1]?callerId=$f1_1;" maxCallsPerDestinationResource="100" destinationResourceId="server1" />
 <option value="sip:$f0_2;@[ip2]?callerId=$f1_2;" maxCallsPerDestinationResource="200" destinationResourceId="server2" />
</call>
<on event="answer">
 <playaudio value="$randfile(C:\StarTrinity\Wav Files\*.wav);" repeat="infinite" maxtime="$rand(670000);ms" />
 <exit />
</on>

readdb Executes a database query, returns rows one by one, stores fields into variables
The database request is done via ODBC drivers to MSSQL, MySQL, PostgreSQL, other databases. Database readers are shared between sessions, queried records are cached into memory. See also: "readcsv" Attributes:
value (required) - SQL query to execute
odbcConnection (required) - ODBC connection string
var[columnIndex] (required) - names of variables to store data fields. Zero-based [columnIndex] identifies column.
repeat (optional, default is "1") - number of times to repeat the queried records. "infinite" to repeat file infinitely
reloadOnRepeat (optional, "true" or "false", default is "false") - need to reload data from database when queried records are repeated
<readdb value="select Number from NumbersToDial" odbcConnection="Driver={SQL Server};Server=server.com\SQLEXPRESS;Database=Test;Uid=sa;Pwd=abcxyz;" var0="number" repeat="infinite" reloadOnRepeat="false" />
<log value="read number from database: $number;" />
<call value="sip:$number@12.34.56.67">
 <on event="answer" >
  <playaudio value="music.wav" />
  <exit />
 </on>
</call>
<readdb value="select Number, ServerIP from NumbersToDial" odbcConnection="Driver={SQL Server};Server=server.com\SQLEXPRESS;Database=Test;Uid=sa;Pwd=abcxyz;" var0="number" var1="serverIp" repeat="infinite" reloadOnRepeat="false" />
<log value="read number from database: $number;@$serverIp;" />
<call value="sip:$number@$serverIp;">
 <on event="answer" >
  <playaudio value="music.wav" />
  <exit />
 </on>
</call>

receivefax Initiates RE-INVITE with T.38 fax SDP offer, receives T.38 fax to file.
Does not return control untile fax operation is complete. If the fax operation fails, raises an "error" event, it could be handled in CallXML script Attributes:
value (optional) - file name where to save received fax. If not set, unique file name will be generated
<receivefax />
<receivefax value="C:\receivedfax.tiff" />

recordcall Switches on/off recording for current SIP call or conference.
Returns control immediately. Recording is started only when RTP media session is established. Audio is recorded from mix of RX and TX audio streams of current SIP call, and from mix of RX streams of all calls in conference. Recorded wav file name pattern is configured with settings. Attributes:
value (required) - percentage of SIP calls to be recorded. If "100", always starts recording; if "0" always stops recording
conference (optional) - ID of conference for recording. If not set, only current SIP call is recorded
uri (optional) - specifies destination for recorded file, i.e recorded file name
basepath (optional) - base folder for recorded files
mode (optional, "rx", "tx", default "mix") - source of audio data for recording. "rx" - audio received from remote side, "tx" - audio transmitted to remote side, "mix" - mix of "rx" and "tx"
<recordcall value="100" basepath="F:\recordings" />
<recordcall value="100" uri="c:\recorded_files\$time();_$callerId;.wav" />
<recordcall value="100" conference="01" />
<recordcall value="0" /> <!-- stop recording -->

recordmessage Records audio message e.g. for voicemail
Returns control after message is recorded. Recording is ended by pressing any DTMF key Attributes:
value (required) - path to new recorded file
<recordmessage value="d:\recordings\$time(yyyyMMdd_HH_mm_ss_fff);.wav" />

redirect Redirects incoming SIP call to new destination. Sends "302 Moved Temporarily" response with new contact.
Attributes:
value (required) - SIP URI with new contact
<redirect value="sip:1000@10.10.10.1" />

regexsearch Searches for patterns in strings using regular expressions
Uses System.Text.RegularExpressions.Regex.Match method from Microsoft .NET library Attributes:
value (required) - input string
regex (required) - regular expression. Nnote that it should be XML-escaped, i.e. '<' and '>' should be replaced with '&lt;' and '&gt;'
var (required) - list of variables' names to store results
<regexsearch value="ABCD 123 456 789"
  regex="ABCD\W*(?&lt;digits1&gt;\d+)\W*(?&lt;digits2&gt;\d+)\W*(?&lt;digits3&gt;\d+)" var="digits1;digits2;digits3" />
<log value="digits1='$digits1;', digits2='$digits2;', digits3='$digits3;'" />
<regexsearch value="$sipheadercontact;" regex="@(?&lt;sip_contact_address&gt;[^;]*)" var="sip_contact_address" />
<regexsearch value="asdasg s dfghdfghdfgh 777 asdf asd asf" regex="[0-9]+" var="digits" />
<log value="found digits: $digits;" />

register Sends REGISTER, waits for response, saves status to a variable. Measures delay between sending "REGISTER" request and receiving "200 OK" response
Attributes:
value (required) - SIP URI of destination. SIP URI can contain user and password for authentication, and "transport" query parameter ("udp" or "tcp", "udp" is default)
var (optional) - name of variable to store response status code
delayvar (optional) - name of variable to store response delay in milliseconds
expires (optional) - value of "Expires" SIP header. Default is 3600 (seconds). If set to 0, the REGISTER request means un-registration
headers (optional) - list of custom SIP headers to be included into the REGISTER request.
Example: Header1Name=Header1Value|Header2Name=Header2Value|Header3Name=Header3Value
contactHeaderFormat (optional) - custom Contact header format. Example: "Eran%20Younger" <sip:[userId]@[localIp]:[localPort];transport=TLS;ob>;reg-id=1;+sip.instance="<urn:uuid:2c72cde9-c1d4-321d-8727-9bb0e165519f>"
<log value="sending REGISTER..." />
<register value="sip:100@192.168.0.17?user=100&amp;password=123456" expires="180" var="status" delayvar="delay" />
<log value="received response code = $status;, delay = $delay;ms" />
<register value="sips:$rand(100,200);@192.168.10.4:5061?transport=tls" var="status" />
<register value="sip:555@startrinity.com" contactHeaderFormat="sip:666@23.45.56.78:7895" />
<log value="sending un-REGISTER (expires = 0)..." />
<register value="sip:100@192.168.0.17?user=100&amp;password=123456" expires="0" var="status" delayvar="delay" />
<log value="received response code = $status;, delay = $delay;ms" />

reinvite Sends RE-INVITE. Is used to put SIP call on hold (call parking feature)
Attributes:
direction (optional, "SendOnly"/"ReceiveOnly"/"None"/"Both") - RTP media stream direction. The meaning of the direction in SDP is a little bit confusing. It is explained in RFC3264. If one side (A) sends "recvonly" in its SDP offer, the other side (B) should say "sendonly" (opposite) in its SDP answer. After that (when SIP call is put on hold), A "receives only, not sends" from B, and B "sends only, not receives" to A, in other words RTP stream flows in one direction: from B to A, microphone at A is muted
sendSdp (optional, "true"/"false", default "true") - send SDP in the RE-INVITE packet. "false" is used to test case of SDP offer in "200 OK" and SDP answer in "ACK"
localRtpAddress (optional) - a custom IP address to put into SDP. Is used for test purposes
codec (optional, "G711A"/"G711U"/"G723"/"G729", default is "current") - new RTP media codec (SDP media stream payload type) to be sent in the RE-INVITE SDP
<reinvite direction="ReceiveOnly" />
<call value="sip:test@10.10.10.10" /> <!-- make call with all available codecs declared in SDP -->
<on event="answer">
 <playaudio value="music.wav" maxtime="5s" />
 <reinvite codec="G729" /> <!-- change codec to G729 -->
 <playaudio value="music.wav" maxtime="5s" />
 <reinvite codec="G711A" /> <!-- change codec to G711A -->
 <playaudio value="music.wav" maxtime="5s" />
 <exit />
</on>

reject Rejects incoming SIP call before answering. Sends response with custom SIP status code.
Attributes:
value (optional, default is "603") - SIP status code for the response
headers (optional) - list of custom SIP headers to be included into the INVITE message.
Example: Header1Name=Header1Value|Header2Name=Header2Value|Header3Name=Header3Value
<reject value="486" />
<reject value="486" headers="Reason=Q.850;cause=17" />
<reject value="302" headers="Contact=sip:152@192.168.0.56" />

replacestring Performs text replacement
Attributes:
value (required) - input text
var (required) - name of variable where to save result
old (required) - old text to be found and replaced
new (required) - new text
<replacestring value="this is original text" old="initial" new="new" var="result" />
<log value="result of replacement is: $result;" />

report Saves custom performance indicator to SIP Tester's GUI and HTML report
See also: "writecdr" Attributes:
name (required) - name of the performance indicator which will be displayed in report
value (required) - numeric value of the performance indicator
qualityIsAscending (optional, "true"/"false") - indicates whether call quality increases or decreases with increasing of the indicator. Is used to calculate percentiles and list of worst quality calls.
<playdtmf value="1" />
<waitforsignal signaldelayvar="ivrDelay"/>
<report name="IVR_delay_1" qualityIsAscending="false" value="$ivrDelay;" />

requestdb Executes MSSQL command (select, insert, delete statements, stored procedures). Stores fields from the first requested row into variables. If no rows returned, saves empty values
The "requestdb" is executed even if current SIP call is disposed, independently from SIP thread. If no connection string is set by parameters, CDR connection string from settings is used Attributes:
connection (optional) - connection string to MSSQL server, contains name of server, name of database, authentication parameters. Example: Data Source=(local)\SQLEXPRESS;User ID=sa;Password=123;Initial Catalog=db1;Asynchronous Processing=true
odbcConnection (optional) - ODBC connection string to database server. Examples: Driver={SQL Server};Server=localhost\SQLEXPRESS;Database=testCDR;Uid=sa;Pwd=pass;,
command (required) - SQL command text. If not set by XML attribute, the command text is taken from inner XML text (see example)
var[columnIndex] (required) - names of variables to store results returned by MSSQL server
<requestdb command="exec SaveCallerId '$callerId;', 'Test', 'Test'"
    connection="Data Source=(local);User ID=sa;Password=123456;Initial Catalog=DtmfTest;Asynchronous Processing=true"
    var0="resultField0" var1="resultField1" var2="resultField2" />
<inputdigits var="enteredNumber" maxsilence="20s" maxdigits="10" />
<requestdb command="select InfoMessage from Table1 where PinCode = '$enteredNumber;'"
 connection="Data Source=(local)\SQLEXPRESS;User ID=sa;Password=123;Initial Catalog=db1;Asynchronous Processing=true"
 var0="infoMessage" /> <!-- Request table from MSSQL database and store a column in variable "enteredNumber" -->
<say voice="Microsoft Anna" value="$infoMessage;" /> <!-- Speak message from database -->
<requestdb odbcConnection="Driver={SQL Server};Server=startrinity.com\SQLEXPRESS;Database=TestCDR;Uid=sa;Pwd=asv2015HJLK;" var0="f0" var1="f1" var2="f2">
 select top 1 callerId, calledId, created from StartrinitySipTesterCdrs order by created desc
</requestdb>
<log value="result from database: callerId = $f0;, calledId = $f1;, created = $f2;" />
<requestdb odbcConnection="Driver={MySQL ODBC 5.3 ANSI Driver}; Server=91.121.146.1;Database=mor; User=usr1; Password=pass1; Option=3;" var0="f0">
 SELECT `src` FROM `calls` WHERE `calldate` > DATE_SUB(NOW(), INTERVAL 48 HOUR) AND `localized_dst` LIKE '%09299802' LIMIT 1
</requestdb>
<log value="result from MySQL MOR CDR database: callerId = $f0; (empty if not found)" />

resetstatistics Resets statistics about processed SIP calls; resets all moving averages
Attributes:
[none]
<resetstatistics />

restartprocess Restarts a windows process
Is used to monitor availability of SIP server and restart it if test calls fail Attributes:
value (required) - full path to executable file
<log value="making call to the server. it should be configured to answer to 'test' number with no delay" />
<call value="sip:test@localhost:5060" maxringtime="5s" />
<on event="answer">
 <log value="call answered. aborting call" />
 <exit />
</on>
<on event="maxringtime;callfailure">
 <log value="call failed (5-sec timeout or error response). restarting server if did not restart already 3 minutes ago" />
 <block minInterval="3m">
  <sendemail value="mailto:email@gmail.com?subject=call to server failed. restarting the server" />
  <log value="restarting SIP server" />
   <!-- here you should set path to your SIP server -->
  <restartprocess value="C:\Users\User\AppData\Roaming\StarTrinity SipTester\StarTrinity.SIPTester.exe" />
 </block>
 <exit />
</on>

run Generates a new CallXML session. Copies all variables from current session to the new session. The "run" XML element should contain child XML elements to be executed by new session.
Attributes:
var (optional) - name of variable to store ID of new session
<block repeat="5">
   <run var="newSessionId">
     <call value="sip:$Id;@192.168.0.1" />
     <on event="answer">
       <playaudio value="music" />
     </on>
   </run>
   <log value="generated new session, ID = $newSessionId;" />
</block>
<assign var="ParentSessionID" value="$id;"/>
<assign var="NumToCall" value="sip:152@192.168.0.56"/>
<run var="secondarySessionId" >
  <call value="$NumToCall;" to="$NumToCall;" callerId="123" maxringtime="100s" />
  <on event="answer" >
    <sendevent value="answer" session="$parentSessionId;" />
    <conference value="$Id;" />
  </on>
  <on event="callfailure">
   <log value="call failed with status $lastError;" />
   <sendevent value="callfailure" session="$parentSessionId;" />
  </on>
</run>
<playaudio value="ringbacktone.wav" />
<on event="externalevent:answer" >
 <accept />
 <conference value="$eventsenderId;" />
</on>
<on event="externalevent:callfailure" >
 <exit />
</on>

runfunction Executes a function
Attributes:
name (requierd) - unique name of function
[parameters] (optional) - values of input parameters, names of variables to store output parameters
<function name="func1" param1="in" param2="in" resultvar="out" >
 <log value="func1: param1 = $param1;, param2 = $param2;" />
 <assign var="resultvar" value="$param1;: OK" />
</function>

<runfunction name="func1" param1="TestValue1" param2="TestValue2" resultvar="result" />
<log value="result=$result;" />

runprocess Runs an .exe or .bat file with custom command line arguments. Saves console output and process exit code into variables. Is used for integration with third party tools
Attributes:
value (required) - path to executable file
args (optional) - command line arguments
exitcode (optional) - name of variable to store exit code. Normal exit code is "0"
user (optional) - name of Windows user in case if you need to run .exe as different user
password (optional) - password of Windows user in case if you need to run .exe as different user
workingdirectory (optional) - working directory for .exe file
<runprocess value="C:\folder\something.exe" args="plink -ssh connectremote -l testuser" stdoutput="stdoutput" exitcode="exitcode" user="xxx" password="yyy" />
<log value="executed something.exe. stdoutput = '$stdoutput;', exitcode = '$exitcode;'" />

runtenantscript For multitenant softswitch or PBX: runs custom tenant's script
Attributes:
none
<runtenantscript />

say Speaks text using a Microsoft Speech API 5 engine. Waits until the engine speaks all the text. Text is set by "value" attribute or by child XML elements
You may need to install SAPI5 SDK Attributes:
value (optional) - text to be spought
voice (optional) - identifies TTS speaker
conference (optional) - ID of conference where to speak the text. If not set, test is spought only to current SIP call
nowait (optional, "true"/"false", default is "false") - if set to "true", control is returned immediately, before end of speaking text. In this case text is still spought during execution of next CallXML elements
<say voice="Microsoft Anna" value="Welcome to the startrinity.com SIP server with text to speech functionality" />
<say>
  <voice required="NAME=Microsoft Mike">you are calling from $callerId;</voice>
</say>
<say voice="Microsoft Mike" >
  you are calling from $callerId; to $calledId;
</say>

searchfile Search for random file in a directory
Attributes:
directory (required) - absolute or relative path to directory
var (required) - name of variable where to save file name
<searchfile directory="d:\recordings" var="fn" />
<playaudio value="$fn;" />

sendemail Sends email using SMTP server, returns control immediately. Connection to SMTP server is configured on settings screen Note that subject and body text have to be escaped
Attributes:
value (required) - "mailto" URI of destination
<sendemail value="mailto:user@server.com?subject=call from $callerId;&amp;body=test body" />
<playdtmf value="1" />
<waitforsignal signaldelayvar="ivrDelay" maxringtime="3000"/>
<if test="$ivrDelay; >= 3000">
 <sendemail value="mailto:user@server.com?subject=IVR timeout: $time();&body=Timeout in IVR1" />
</if>

sendevent Sends external event to another (destination) session. Sets "eventsenderId" variable to the destination session. Copies all variables from current session to the destination session. The external event should be handled with <on event="externalevent:[subType]"> handler.
Attributes:
value (required) - subtype of the external event
session (required) - ID of the destination session
<assign var="conferenceId" value="conf_$Id;" />
<sendevent session="$generatedSessionId;" value="join_to_conference" />

sendfax Initiates RE-INVITE with T.38 fax SDP offer, sends fax from TIFF image file
Does not return control untile fax operation is complete. If the fax operation fails, raises an "error" event, it could be handled in CallXML script.
Default installation contains a file "sample_fax.tiff" for tests Attributes:
value (required) - subtype of the external event
<sendfax value="C:\fax\01.tiff" />

sendhttprequest Sends HTTP/HTTPS request to a web server
Is used to integrate with third-party APIs, to check availability of web servers, to test internet connection Attributes:
value (required) - HTTP URL where to send the request
contentvar (optional) - name of variable where to store downloaded HTTP message body
delayvar (optional) - name of variable where to store measured delay of HTTP response (in milliseconds)
statusvar (optional) - name of variable where to store HTTP response status code
user (optional) - user name for authentication
password (optional) - password for authentication
method (optional, "GET"/"POST", default is "GET") - HTTP method to use. If using "POST", the software sends inner content of the "sendhttprequest" XML element to the web server (see example)
<sendhttprequest value="http://google.com" contentvar="c" delayvar="d" statusvar="s" />
<log value="HTTP test result: delay=$d;ms, HTTP status code = $s;, content: $c;" />
<sendhttprequest value="https://yourserver.com/savetestresult.aspx?token=$token;" method="POST" contentvar="c" delayvar="d" statusvar="s">
 <result>
  <callxmlSessionId value="$id;" />
  <status value="$status;" />
 </result>
</sendhttprequest>
<log value="HTTP POST delay=$d;ms, HTTP status code = $s;, returned content: $c;" />
<log value="sending request to another instance of SIP Tester to check if call exists there from 'test' to 'test'" />
<sendhttprequest value="http://10.10.10.10:19019/API/MainViewModel/CurrentCallExists?callerId=test&amp;calledId=test" user="admin" password="123456" contentvar="r" />
<log value="result: $r;" />
<log value="sending request to another instance of SIP Tester to create 2 synchronous calls. the another instance will send a HTTP request to your web server to get script for the second call" />
<sendhttprequest value="http://siptester-instance-2:19019/API/MainViewModel/CreateCall?url=http://your-web0server/script.xml&user=admin01&amp;password=passw01" user="admin" password="123456" />
<log value="sent request to the second instance. now making a call from this (first) instance" />
<call value="sip:test@192.168.10.56" callerId="test">
 <on event="answer">
  <playaudio value="music.wav" maxtime="20s" />
  <exit />
 </on>
</call>

sendsipinfo Sends SIP INFO with custom body content to current call or to other calls in conference
Attributes:
value (required) - SIP INFO message body content
contentType (optional, default is "application/dtmf-relay") - Content-Type SIP header value
<sendsipinfo value="Signal=1" />
<sendsipinfo value="the text" contentType="text/plain" />

sendsipmessage Sends a custom SIP message. The message is set by content of XML element
Uses a common SIP parsing procedure which is used to parse normal SIP messages received from IP network. If the message is recognized as SIP request, the "sendsipmessage" exits after receiving response. If the message is recognized as SIP response, the "sendsipmessage" exits immediately after sending. Attributes:
maxtime (optional) - for SIP requests: timeout to wait for response (see example)
var (optional) - for SIP requests: variable where to save response status code (see example)
delayvar (optional) - for SIP requests: variable where to save the response delay in milliseconds (see example)
<sendsipmessage>
<![CDATA[
SIP/2.0 180 Ringing
Via: $sipHeaderVia;
Call-ID: $sipCallId;
From: $sipHeaderFrom;
To: $sipHeaderTo; ;tag=b6a1c0b8e8334ef4b89f6a4d6154bbe1
CSeq: $sipHeaderCSeq;
Contact: <sip:192.168.0.13:5070>
Allow: INFO, PRACK, SUBSCRIBE, NOTIFY, REFER, INVITE, ACK, BYE, CANCEL, UPDATE
Server: StarTrinity.SIP 2014-04-28 20:20 UTC
Content-Type: application/sdp
Content-Length: 252

v=0
o=- 3607723560 3607723560 IN IP4 192.168.0.66
s=i14.proxy.stream0
t=0 0
m=audio 6666 RTP/AVP 8 101
c=IN IP4 192.168.0.66
a=rtcp:6667 IN IP4 192.168.0.66
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
]]>
</sendsipmessage>

<!-- at this time caller should send RTP to 192.168.0.66 -->
<wait value="3s" />

<sendsipmessage>
<![CDATA[
SIP/2.0 200 OK
Via: $sipHeaderVia;
Call-ID: $sipCallId;
From: $sipHeaderFrom;
To: $sipHeaderTo; ;tag=b6a1c0b8e8334ef4b89f6a4d6154bbe1
CSeq: $sipHeaderCSeq;
Contact: <sip:192.168.0.13:5070>
Allow: INFO, PRACK, SUBSCRIBE, NOTIFY, REFER, INVITE, ACK, BYE, CANCEL, UPDATE
Server: StarTrinity.SIP 2014-04-28 20:20 UTC
Content-Type: application/sdp
Content-Length: 252

v=0
o=- 3607723560 3607723560 IN IP4 192.168.0.77
s=i14.proxy.stream0
t=0 0
m=audio 7777 RTP/AVP 8 101
c=IN IP4 192.168.0.77
a=rtcp:7778 IN IP4 192.168.0.77
a=rtpmap:8 PCMA/8000
a=sendrecv
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
]]>
</sendsipmessage>

<!-- after this 200 OK response caller should send RTP to 192.168.0.77 -->
<wait value="100s" />
<exit/>
<sendsipmessage>
<![CDATA[
INVITE sip:88@localhost SIP/2.0
Max-Forwards: 69
Session-Expires: 3600;refresher=uac
Min-SE: 600
Supported: timer, 100rel
To: 888963217843506 <sip:888963217843506@80.239.172.171;user=phone>
From: <sip:905348591511@80.239.172.144>;tag=3621105032-66026
Remote-Party-Id: <sip:905348591511@80.239.172.144:5061;user=phone>;privacy=off;screen=yes
Call-ID: 5115009-3621105032-66020@msc1.voipdomain.com
CSeq: 1 INVITE
Allow: INVITE, BYE, OPTIONS, CANCEL, ACK, REGISTER, NOTIFY, INFO, REFER, SUBSCRIBE, PRACK, UPDATE, MESSAGE, PUBLISH
Via: SIP/2.0/UDP 80.239.172.144:5060;branch=z9hG4bK6e470d385b78ed88288a3488169f3448
Contact: <sip:905348591511@80.239.172.144:5060>
Call-Info: <sip:80.239.172.144>;method="NOTIFY;Event=telephone-event;Duration=1000"
Content-Type: application/sdp
Content-Length: 419

v=0
o=msc1 1412116227 1412116227 IN IP4 80.239.172.144
s=sip call
c=IN IP4 80.239.172.145
t=0 0
m=audio 31358 RTP/AVP 18 96 4 97 98 0 8
a=rtpmap:18 G729/8000
a=fmtp:18 annexb=no
a=rtpmap:96 G729/8000
a=fmtp:96 annexb=yes
a=rtpmap:4 G723/8000
a=fmtp:4 annexa=yes
a=rtpmap:97 G729/8000
a=fmtp:97 annexb=no
a=rtpmap:98 G729/8000
a=fmtp:98 annexb=yes
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=sendrecv
]]>
</sendsipmessage>
<sendsipmessage>
<![CDATA[
OPTIONS sip:test@192.168.10.6 SIP/2.0
Via: SIP/2.0/UDP 192.168.10.6
Max-Forwards: 70
To: <sip:test@192.168.10.6>
From: Alice <sip:test@192.168.10.5>;tag=test$id;
Call-ID: test$id;
CSeq: $id; OPTIONS
Contact: <sip:test@192.168.10.5>
Accept: application/sdp
Content-Length: 0
]]>
</sendsipmessage>
<log value="sending OPTIONS (SIP ping) to check availability of server. waiting for response during 3 seconds"/>
<sendsipmessage maxtime="3s" delayvar="delay" var="status">
<![CDATA[
OPTIONS sip:test@192.168.10.6 SIP/2.0
Via: SIP/2.0/UDP 192.168.10.6
Max-Forwards: 70
To: <sip:test@192.168.10.6>
From: Alice <sip:test@192.168.10.5>;tag=test$id;
Call-ID: test$id;
CSeq: $id; OPTIONS
Contact: <sip:test@192.168.10.5>
Accept: application/sdp
Content-Length: 0
]]>
</sendsipmessage>
<if test="$status; = 200" > <log value="server is available. response delay is $delay;ms" /> </if>
<else> <log value="server is unavailable. status: $status;" /> </else>

sendsiprequest Sends custom SIP request for current SIP call, within current INVITE dialog. The request is set by content of XML element. Returns control immediately. Headers like Call-ID and request URI are ovewritten, content length is calculated automatically
Uses a common SIP parsing procedure which is used to parse normal SIP messages received from IP network Attributes:
none
<call callerId="" value="sip:100@localhost"/> <!-- Make outgoing SIP call to 100@localhost -->
<on event="pr"> <!-- Handler for provisional responses (180, 183) -->
<sendsiprequest>
<!-- Send custom SIP request (NOTIFY) within same INVITE session -->
<![CDATA[
NOTIFY sip:xx.yy.zz SIP/2.0
User-Agent: XYZ
Event: message-summary
Content-Type: application/simple-message-summary

Messages-Waiting: no
Message-Account: sip:*97@10.10.10.10
Voice-Message: 0/0 (0/0)
]]>
</sendsiprequest >
</on>
<on event="answer"> <!-- Handler for final response (200 OK) -->
<playaudio value="music" repeat="10000" maxtime="10000ms" />
<exit />
</on>

setcallgeneratorparams Changes call generation parameters
The call generator starts new CallXML session on time (clock) every N milliseconds, with fixed or random intervals. The interval between calls is set by "maxcps", "maxcpsL", "maxcpsH", "callspertick" parameters, maximum number of concurrent calls is set by "maxconcurrentcalls", "maxoutgoingconcurrentcalls". If number of concurrent calls exceeds "maxconcurrentcalls", the call generator is temporary stopped, so number of calls per second will be limited also Attributes:
maxcps (optional) - max calls per second (fixed interval betweeen calls)
maxcpsL (optional) - max calls per second, lower bound (random interval betweeen calls, linear probability distribution)
maxcpsH (optional) - max calls per second, higher bound (random interval betweeen calls, linear probability distribution)
maxconcurrentcalls (optional) - max concurrent calls (incoming + outgoing)
maxoutgoingconcurrentcalls (optional) - max concurrent calls (outgoing only)
callspertick (optional) - number of calls to create at a time (number of calls in a burst)
<setcallgeneratorparams maxcps="3" maxconcurrentcalls="10" />
<assign var="numberOfConcurrentCalls" mathvalue="120 + 100 * sin(($timeOfDayInHours(); - 10) / 24 * 360)" />
<!-- 360 – 360 degrees in a cycle -->
<!-- 24 – 24 hours in day interval -->
<!-- 10 – 10 hours AM is 0-degree point in sinusoid -->
<!-- 120 – average channels count -->
<!-- 100 – amplitude of change for channels count -->

<setcallgeneratorparams maxconcurrentcalls="$numberOfConcurrentCalls;" />
<!-- please use SIP Tester's GUI to set daily start/stop time -->

<!-- here is the code to set different call load for different periods of time -->
<if test="$timeOfDayInHours(); > 10 & $timeOfDayInHours(); < 11">
<!-- from 10AM to 11AM - set number of channels = 30 -->
 <setcallgeneratorparams maxconcurrentcalls="30" />
</if>
<if test="$timeOfDayInHours(); > 11 & $timeOfDayInHours(); < 13">
<!-- from 11AM to 1PM - set number of channels = 50 -->
 <setcallgeneratorparams maxconcurrentcalls="50" />
</if>
<if test="$timeOfDayInHours(); > 13 & $timeOfDayInHours(); < 17">
<!-- from 1PM to 5PM - set number of channels = 10 -->
 <setcallgeneratorparams maxconcurrentcalls="10" />
</if>


<call maxringtime="$rand(45500);ms" value="$seq_sip_uri_from_csv(C:\StarTrinity\CSV Files\Mali Aug 26 Dialer Ready 4x 2xAST.csv);" codec="G729" />
<on event="answer">
<!-- on answer: verify called party, it should send DTMF digit 7 -->
 <inputdigits var="d" maxsilence="5s" />
 <if test="$d; != 7" > <exit /> </if>

<!-- play random wav file from folder -->
 <playaudio value="$randfile(C:\StarTrinity\Wav Files\*.wav);" repeat="infinite" maxtime="$rand(500000);ms" />
 <exit />
</on>

setexitcode Sets exit code for SIP Tester process. Is used to pass result from CallXML script into .bat script via using command line interface
See also: "exitcli" Attributes:
value (required) - exit code
<setexitcode value="-1" />

setinterval Executes internal CallXML code at specified intervals, when current SIP calls is still alive
Is similar to "setInterval" in JavaScript. The internal CallXML code is executed in a separate thread. See also: "settimeout" Attributes:
value (required) - interval between the executions of the internal CallXML code
<setinterval value="1s">
 <log value="do something every 1 second during the call. e.g. request database and destroy the call if needed" />
</setinterval>
<call value="sip:test@10.10.10.10" />
<on event="answer">
 <playaudio value="music.wav" repeat="infinite" />
</on>

setrtpextension Sets or removes RTP extension data for transmitted RTP stream
Attributes:
hexData (optional) - generic RTP extension data in hexademical text format. Example: '01C04FFA'
extensionId (required if 'hexData' is set) - identifier of RTP extension data format, defined by audio/video profile
wg67_pttType (optional) - PTT-type field, defined in INTEROPERABILITY STANDARDS FOR VOIP ATM COMPONENTS VOLUME 1: RADIO. If wg67_pttType is set to "rxptt", it gets PTT-type from received RTP stream, in other words it creates PTT-type RX-TX loopback connection. This loopback connection is used to measure round-trip RTP audio delay for ED-137 performance testing of air traffic management (ATM) VoIP networks.
wg67_pttId (optional) - PTT-ID
wg67_squ (optional, 1 or 0, default is 0) - SQU flag. If wg67_squ is set to "rxptt", it creates loopback connection from PTT-Type field of received RTP stream: If RX-PTT-ID is 0 then TX-SQU is 0, otherwise TX-SQU is 1
wg67_pm (optional, 1 or 0, default is 0) - PM flag
wg67_ptts (optional, 1 or 0, default is 0) - PTTS flag
wg67_sct (optional, 1 or 0, default is 0) - SCT flag
<call value="sip:line@192.168.3.3:5062" callerId="line"></call>
<on event="answer">
  <setrtpextension wg67_pttType="3" wg67_pttId="16" wg67_squ="1" wg67_pm="0" wg67_ptts="0" wg67_sct="1" />
<!-- set RTP extension data for transmitted stream in WG 67 format (0x167). For more information about fields see
   INTEROPERABILITY STANDARDS FOR VOIP ATM COMPONENTS VOLUME 1: RADIO -->

  <playaudio value="music.wav" maxtime="3s" /> <!-- play music.wav during 3 seconds -->
  <setrtpextension wg67_pttType="0" wg67_pttId="16" wg67_squ="1" wg67_pm="0" wg67_ptts="0" wg67_sct="1" />
<!-- set another RTP extension data -->
  <playaudio value="music.wav" maxtime="3s" />
  <setrtpextension wg67_pttType="0" wg67_pttId="16" wg67_squ="1" wg67_pm="0" wg67_ptts="0" wg67_sct="0" />
  <playaudio value="music.wav" maxtime="3s" />
  <setrtpextension wg67_pttType="0" wg67_pttId="16" wg67_squ="0" wg67_pm="0" wg67_ptts="0" wg67_sct="0" />
  <playaudio value="music.wav" maxtime="3s" />
  <setrtpextension /> <!-- turn off RTP extension data -->
  <playaudio value="music.wav" maxtime="3s" />
  <exit />
</on>
<call value="sip:test@192.168.3.3:5062" callerId="test"></call>
<on event="answer">
  <setrtpextension extensionId="359" hexData="01C00000" />
  <playaudio value="music.wav" maxtime="3s" />
  <exit />
</on>
<accept />
<setrtpextension wg67_pttType="rxptt" wg67_pttId="7" wg67_squ="0" wg67_pm="0" wg67_ptts="0" wg67_sct="0" />
<!-- set up PTT-type loop from RX RTP stream to TX RTP stream -->
<playaudio value="music2" repeat="infinite" maxtime="60000ms" />
<exit />

setsetting Sets a global setting value
The settings are described in the UI on the 'settings' screen. Attributes:
name (required) - name of setting
value (required) - value of setting
<setsetting name="SaveSipAndRtpPacketsToDisk" vaue="1" />

settimeout Executes internal CallXML code after specified timeout
Is similar to "setTimeout" in JavaScript. The internal CallXML code is executed in a separate thread. See also: "setinterval" Attributes:
value (required) - time to delay the execution of the internal CallXML code
<assign var="receivedReinvite" value="false" />
<call maxringtime="10s" value="sip:test@localhost:5060">
 <on event="answer">
  <settimeout value="60s">
   <log value="60 seconds passed: checking if received re-invite" />
   <if test="$receivedReinvite; = false" > <log value="aborting call" /> <disconnect /> </if>
   <else> <log value="received re-invite: continue the call" /> </else>
  </settimeout>
  <playaudio value="music.wav" repeat="infinite" /> <exit />
 </on>
 <on event="reinvite"> <log value="received re-invite" /> <assign var="receivedReinvite" value="true" /> </on>
</call>

srand Initializes the CallXML engine's random generator with the specified seed value
Is used to reproduce random tests Attributes:
value (required) - the seed value, integer
<!-- initialize random generator for the first CallXML session (ID = 0)
<if test="$id; = 0"> <srand value="123" /> </if>
<log value="random = $rand(100);" />

startcallgenerator Starts generation of outgoing calls
Attributes:
[none]
<startcallgenerator />

stopaudio Stops audio player which was started previously
Attributes:
[none]
<stopaudio />

stopcallgenerator Stops generation of outgoing calls
Attributes:
[none]
<stopcallgenerator />

substring Retrieves a substring from a specified value, saves result to a variable
Attributes:
value (required) - input string
startIndex (required) - zero-based starting character position of a substring
length (optional) - number of characters in the substring
<substring var="result1" value="01234567890" startIndex="0" length="2" />
<log value="result1=$result1;" />

<substring var="result2" value="01234567890" startIndex="6" />
<log value="result2=$result2;" />

<substring var="result3" value="startrinity CallXML" startIndex="12" length="4" />
<log value="result3=$result3;" />

switch Checks if a value matches to one of many conditions, executes an action accordingly
The conditions are defined by inner "case" XML elements. If no "case" element is found, "default" element is executed. If "probability" attributes are defined for the conditions, a random "case" is selected. "case" XML element may be empty. See also: "case", "default" Attributes:
value (optional) - input value for checking
<switch value="$callerId;">
 <case equals="111"> <log value="call is from 111" /> </case>
 <case equals="222"> <log value="call is from 222" /> </case>
 <case startsWith="2"> <log value="call is from 2xxx" /> </case>
 <default> <log value="caller ID is not recognized" /> </default>
</switch>
<switch>
  <case probability="10">
   <log value="this has probability of 10%" />
  </case>
  <case probability="30">
   <log value="this has probability of 30%" />
  </case>
  <case probability="60">
   <log value="this has probability of 60%" />
  </case>
</switch>
<switch value="$timeOfDayInHours();">
 <case from="0" to="12"> <setcallgeneratorparams callspertick="1" maxcpsL="0.1" maxcpsH="0.22" /> </case>
 <case from="13" to="24"> <setcallgeneratorparams callspertick="3" maxcpsL="0.2" maxcpsH="0.32" /> </case>
</switch>

throw Raises an event
Attributes:
value (required) - type and (optionally) subtype of event, separated by ":"
<inputdigits value="enter_digit.wav" var="entered_digit" maxsilence="20s" maxdigits="1" />
<throw value="digit:$entered_digit;" />
<on event="digit:1">
   <playaudio value="1" />
</on>
<on event="digit:2">
   <playaudio value="2" />
</on>

transfer Redirects call to another SIP URI. Is one of major elements for softswitches, SBCs, IP PBXes
Raises "pr", "audioSignal", "maxringtime", "maxansweredtime", "callfailure" and "answer" events
Attributes:
value (required if 'terminators' attribute is not set) - specifies SIP URI of destination. SIP URI can contain user and password for authentication, and "transport" query parameter ("udp" or "tcp", "udp" is default). The SIP URI may contain following query parameters:
  • "transport" - "udp" or "tcp", "udp" is default
  • "user", "password" - credentials for authentication
  • "proxyAddress", "proxyPort" - address of proxy server
  • "localSipPort" - local SIP UDP port to use for the call
  • "callerId" - user ID in 'From' header
  • "route" - if equals to "localregistrar", the SIP call is routed to an extension registered at local UAS registrar (URI is replaced by 'Contact' header of received REGISTER request)

terminators (required if 'value' attribute is not set) - identifiers of terminators, separated by semicolons, used for Softswitch scripts. Terminators are configured via web interface. If 'terminators' is set to 'all', all available terminators are used; if set to 'routed' - the terminators are taken from settings of originator and routing group
mode (optional, default is "bridged") - list of call transfer modes, separated by semicolon. If "terminators" attribute is set, default mode is taken from the terminator.
  • "blind" - if mode is "blind", sends REFER to current caller
  • "bridged" - if "mode" is "bridged", makes another SIP call (call B) and connects RTP streams between current call (call A) and call B. If call A is not answered yet, sends answer response to call A when call B is answered. Optionally plays ringback tone from WAV or MP3 file. Proxies provisional responses (180, 183) from call B to call A. Returns control on time out or after completion of call B. Automatically converts codecs (e.g. performs G.729-G.711 transcoding). Raises "callfailure" and "maxringtime" events. Automatically redirects call B to new destination if receives "302 Moved Temporarily" response. If "callfailure" event is not handled, rejects call A automatically
  • "proxydtmf" - pass DTMF messages between call A and call B
  • "disablehold" - disable call hold and 3-way conferencing
  • "suppressAnswerBeforeRbt" - suppress FAS, start billing only if there was ringback tone before answer. If the answer from terminator is received before ringback tone (450 Hz), it waits for the ringback tone and generates answer 5 seconds after last tone. Stops fake ringbacktone, if it was started before the "transfer" element in the script
  • "recognizeAnswerFromRtpB" - ignore answer signal from terminator, recognize it from RTP audio from call leg B - first sound after ringback tone
  • "recognizeAnswerFromRtpA" - ignore answer signal from terminator, recognize it from RTP audio from call leg A - first sound above specified level (in decibels, "level" attribute, default is "-20")
For "bridged" mode only:
ringbacktone (optional) - absolute or relative path to audio file which will be played to call A
to (optional) - "To" header for SIP INVITE message. If "to" is not set, it is taken from "value" SIP URI
callerId (optional, default is "unknown") - SIP ID for "From" header in INVITE message
sendSdpInInitialInvite (optional, "true" or "false", default is "true") - specifies whether to send SDP in SIP INVITE message. If no SDP is sent in request, and if destination also does not send SDP in response, the SIP call will be established without RTP media.
direction (optional, "SendOnly"/"ReceiveOnly"/"None"/"Both", default is "Both") - RTP media direction to be declared in SDP
maxringtime (optional, default is "no timeout") - timeout of waiting for call answer in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix). If "maxringtime" expires, call is aborted with CANCEL SIP message and "maxtime" event is generated
maxansweredtime (optional, default is "no timeout") - max call duration after answering in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix). If "maxansweredtime" expires, call leg B is aborted and "maxansweredtime" event is raised. If no event handler for "maxansweredtime" exists, the call leg A is aborted with BYE SIP message
headers (optional) - list of custom SIP headers to be included into the INVITE message.
Example: Header1Name=Header1Value|Header2Name=Header2Value|Header3Name=Header3Value
sdpAttributes (optional) - list of custom SDP attributes to be included into the INVITE message.
Example: Attr1Name:Attr1Value|Attr2Name:Attr2Value|Attr3Name:Attr3Value
codec (optional, "G711A"/"G711U"/"G723"/"G729", default is "any of supported") - RTP media codec (SDP media stream payload type) to be used for the SIP call.
disconnectOnSilenceLevel (optional, default is "none") - if specified, disconnects the call if both A and B call legs are silent for a long time
disconnectOnSilenceTimeout (optional, default is "30s") - if "disconnectOnSilenceLevel" attribute is set: minimal silent time before disconnecting the call
<transfer value="sip:152@192.168.0.56" mode="bridged" ringbacktone="wait_for_answer.wav"
     maxansweredtime="20m" maxringtime="40s" >
 <on event="callfailure:486">
   <playaudio value="busy.wav" />
 </on>
 <on event="callfailure">
   <playaudio value="call_error.wav" />
 </on>
 <on event="maxringtime">
   <playaudio value="call_does_not_answer_on_timeout.wav" />
 </on>  <on event="maxansweredtime">
   <playaudio value="speaking_timeout_call_again.wav" />
 </on>
</transfer>
<playaudio value="thank_you_for_call.wav" />
<exit />
<assign var="transferPrefix" value="+1" />
<transfer value="sip:$transferPrefix;$calledId;@x.x.x.x:5060" callerId="$callerId;" mode="bridged" maxringtime="50s" codec="G729" />
<on event="callfailure">
 <log value="call 'B' failed, status = $eventSubType;. rejecting call leg 'A' with same status code" />
 <reject value="$eventSubType;" />
 <exit />
</on>
<on event="maxringtime">
 <playaudio value="call_does_not_answer_on_timeout.wav" />
 <reject value="503" />
</on>
<accept value="183" />

<!-- play fake rbt -->
<playaudio value="rbt$randswitch(1,2,3,4,5);.wav" repeat="100" dontwait="true" />

<!-- split traffic into 2 gateways, 5 channels each. suppress IVR (announcement) from destination before receiving ringback tone -->
<transfer value="$rand_from_options;" callerId="$callerId;" mode="bridged;proxydtmf;suppressAnswerBeforeRbt" maxringtime="70s">
 <option value="sip:$calledId;@51.254.245.55" maxCallsPerDestinationResource="5" destinationResourceId="server1" />
 <option value="sip:$calledId;@51.254.245.43" maxCallsPerDestinationResource="5" destinationResourceId="server2" />
 <on event="callfailure"> <reject value="$eventSubType;" /> </on>
</transfer>
<!-- transfered to registered SIP phone with extension 100 -->
<transfer value="$ext(100);" >
 <on event="callfailure"> <reject value="$eventSubType;" /> </on>
</transfer>
<!-- simplest softswitch script for GSM termination and wholesale -->
<performAAA />
<transfer terminators="routed" />
<!-- script used to suppress FAS when getting an IVR from SIM - for GSM termination -->
<performAAA />
<transfer terminators="routed" mode="bridged;suppressAnswerBeforeRbt;proxydtmf" />
<!-- script used for bluetooth - GSM termination, to generate answer and disconnect signals from media streams -->
<performAAA />
<accept value="183" />
<transfer terminators="routed" mode="bridged;recognizeAnswerFromRtpB;proxydtmf" disconnectOnSilenceLevel="-40" disconnectOnSilenceTimeout="30s" maxringtime="60s" />
<on event="maxringtime"> <reject value="487" /> </on>
<!-- script used for bluetooth - GSM termination, to generate answer and disconnect signals from media streams -->
<performAAA />
<accept value="183" />
<transfer terminators="routed" mode="bridged;recognizeAnswerFromRtpA;proxydtmf" level="-20" disconnectOnSilenceLevel="-40" disconnectOnSilenceTimeout="30s" maxringtime="60s" />
<on event="maxringtime"> <reject value="487" /> </on>

verifyaudio Verifies RTP audio stream of current SIP call, compares it with one or many reference audio files. Identifies matched reference file along with either a confidence score, or audio quality measurement (PESQ MOS). Also, measures the delay between the start of audio verification and the occurrence of the matched audio file.
For offline mode: records audio signal into memory during "maxtime" regardless of reference file length. After that, passes the recording to audio verification threads and returns control after verification.
For real-time mode: verifies audio immediately, returns control when "waitConfidenceThreshold" is exceeded or when timeout is expired.
The known ("reference") audio fragment could be located in middle of a longer IVR prompt.
See also: "waitforsignal" to measure delay of IVR response without any verification Attributes:
reference (required) - absolute or relative reference audio file names, separated by ";"
maxtime (required) - max time of verification in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix). For real-time audio verification mode "maxtime" is a timeout of waiting for initial match
waitConfidenceThreshold (optional, 1-100) - Setting this value enables real-time audio verification. To enable real-time audio verification set this value to a number between 1 and 100. In real-time audio verification mode, the audio stream is verified for a match to any portion of the audio file (or files) specified in by the "reference" parameter. As soon as a partial match is made, the "maxtime" timer is cancelled. The audio stream continues to be monitored until either the confidence reaches the specified value, or for number of seconds equal to the longest reference audio file has occurred, whichever comes first. In the real-time mode audio verification is performed by media threads. It is recommended to set setting "MediaThreadsCount" greater than 64. The real-time mode works for G.711 codec only. By default, the algorithm searches for matches by testing delays equal to multiples of RTP frame duration (N*10ms), in this way saving CPU time. If there are partial-frame delays in your environment (e.g. if voice goes over non-RTP channels like TDM), set setting "EnablePartialFrameOffsetInRealtimeAudioVerifier" to "1"
debugRecordingThreshold (optional, 0-100) - for real-time audio verification: "verifyaudio" saves debug recordings of observed audio, if confidence is less than the "debugRecordingThreshold". Recorded file names are built from settings "DebugMediaPath" and "DebugMediaFileNamePattern"
confidencevar (optional) - name of variable to store measured confidence, i.e. similarity rate between RTP audio stream and reference audio file = 100 * matched_duration / reference_wav_duration
mosvar (optional) - name of variable to store PESQ MOS. If "mosvar" attribute exists, PESQ algorithm is used to calculate MOS. If recorded duration and reference duration are not equal, minimum duration is selected for PESQ.
Note: If waitConfidenceThreshold is specified, this value has no effect.
If you have low PESQ MOS scores while it is not expected, you can:
  • Enable RX debug recording (set setting "DebugMedia = "1"), listen to recorded audio to check if audio quality is really bad
  • Increase SIP Tester's jitter buffer size, set it according to settings of your VoIP software
  • Try to use recorded RX wav file as reference file. Some implementations like SIPP make small distortions which affect work of SIP Tester's jitter buffer loss compensator
  • Try to use a different audio file. The algorithm works better with speech, not music. There is a "speech.wav" in default installer

recognizedreferencevar (optional) - name of variable to store matched reference audio file. If more than one file is passed in the reference value, the file with the highest match is returned.
recognizeddelayvar (optional) - name of the variable to store delay between the start of audio verification and the occurrence of the matched audio file in milliseconds. The delay can be negative if some part of IVR file is already played before the start of verification
probability (optional) - probability of audio verification being executed. Is used to verify audio for only part of calls, in this way reducing CPU load. Valid range is a decimal value from 0-1.
<playdtmf value="1" /> <!-- simulate DTMF key "1" -->
<verifyaudio reference="c:\ivr2.wav;c:\ivr3.wav" maxtime="10s" recognizeddelayvar="delay" recognizedreferencevar="ref" confidencevar="conf" />
<!-- verify audio signal in RTP stream during 10 seconds, identify which IVR message is played (one of reference files ivr3.wav or ivr2.wav). reference files have to be in WAV or MP3 format. they should contain original IVR messages which are played by server
results are saved to variables:
recognizeddelayvar="delay" - delay in milliseconds between start of verification and start of identified IVR message
                                        - IVR server's response time to DTMF event
recognizedreferencevar="ref" - name of identified reference file
confidencevar="conf" - confidence rate of identification, from 0 to 100 -->

<log value="delay = $delay;ms, reference file = $ref;, confidence = $conf;" /> <!-- show results in "Log" tab -->
<writecdr header="IVR" value="$ref;" /> <!-- save results to CDR report -->
<writecdr header="IVRCONF" value="$conf;" />
<call value="sip:XX@10.10.10.10" />
<on event="answer">
   <verifyaudio reference="C:\reference_file_speech.wav" maxtime="10s" mosvar="pesq_mos" />
   <writecdr header="PESQ_MOS" value="$pesq_mos;" numeric="true" qualityIsAscending="true" />
   <exit />
</on>

wait Introduces delay with specified amount of time
See also: "waitforsignal" Attributes:
value (optional, default is "infinite") - timer in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix). If "value" is not specified, the "wait" sets current call into idle state
<wait value="1s" />
<wait value="$rand(10000);ms" />

waitforringbacktone Waits for a ringback audio tone with frequency 400..450Hz and level at least -30dB. Is used to validate SIP trunks
If there is no RTP, it does not return control. See also: "waitforsignal" Attributes:
var (optional) - name of variable to store measured delay in milliseconds. If the "maxtime" timeout expires, it receives a value of "maxtime"
maxtime (optional) - timeout of waiting in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix)
<call value="sip:test@10.10.10.10">
 <on event="pr:183">
  <log value="received 183 response. waiting for ringback tone for max 6000ms..." />
  <waitforringbacktone var="d" maxtime="6s" />
  <log value="RBT wait time = $d;ms" />
  <if test="$d; >= 6000"> <log value="RBT is not detected" /> </if>
 </on>
 <on event="answer">
  <log value="received 200 response" />
  <exit />
 </on>
</call>

waitforringbacktoneabsence Waits for absence of ringback audio tone with frequency 400..450Hz and level at least -30dB. Is used to skip fake SIM card answer and "welcome" announcement with GSM gateways (see sample script)
See also: "waitforringbacktone"
Attributes:
var (optional) - name of variable to store measured delay in milliseconds. If the "maxtime" timeout expires, it receives a value of "maxtime"
maxtime (optional) - timeout of waiting in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix)
minabsencetime (optional, default "5s") - minimum time without ringback tone, in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix)
<call value="sip:1234567@10.10.10.10" />
<on event="pr:183">
 <log value="got early media from destination: waiting for ringback tone (RBT). we ignore the 200 OK signal, use audio signal instead" />
 <waitForRingbacktone />
 <log value="got ringback tone. waiting for ringback tone absence (voice answer or silence)" />
 <waitForRingbacktoneAbsence />
 <log value="got RBT absence. playing audio file" />
 <playaudio value="music.wav" />
 <exit />
</on>

waitforsilence Waits for RTP audio signal below specified level. Is used to wait for the end of IVR prompt
If there is no RTP, it does not return control. See also: "waitforsignal" Attributes:
maxtime (optional) - timeout of waiting in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix)
level (optional, default is "-24dB") - threshold level in dB. 0dB corresponds to max level, -6dB to 50%, -[Infinity]dB to silence
minTimeBelowLevel (optional, default is "500ms") - minimal duration of audio below the "level" before exiting the "waitforsilence"
interruptableByDtmf (optional, default is "false") - specifies presence of additional DTMF event handlers in script
<playdtmf value="1" />
<waitforsignal />
<log value="detected IVR audio prompt" />
<waitforsilence />
<log value="detected silence after prompt" />

waitforsignal Waits for RTP audio signal above specified level, measures delay. Is used to verify response times in IVR menus
If there is no RTP, it does not detect any signal and does not return control. See also: "measuresignal", "waitforsilence" Attributes:
maxtime (optional) - timeout of waiting in milliseconds ("ms" suffix), seconds ("s" suffix) or minutes ("m" suffix)
signaldelayvar (optional) - name of variable to store measured delay in milliseconds. If the "maxtime" timeout expires, it receives a value of "maxtime"
level (optional, default is "-24dB") - threshold level in dB. 0dB corresponds to max level, -6dB to 50%, -[Infinity]dB to silence
minTimeAboveLevel (optional, default is "0ms") - minimal duration of exceeding the "level" before exiting the "waitforsignal"
callLeg (optional, "A" or "B", default is "A") - identifies call leg when doing call transfer
maxlevelvar (optional) - name of variable to save maximal (peak) signal level in decibels, if the "waitforsignal" is aborted by the "maxtime" timeout
<playdtmf value="1" />
<waitforsignal signaldelayvar="ivrDelay"/>
<report name="IVR_delay_1" qualityIsAscending="false" value="$ivrDelay;" />
<!-- RTP media should be established to execute 'waitforsignal' -->
<waitforsignal signaldelayvar="d" level="-15dB" maxtime="3s" minTimeAboveLevel="10ms" />
<log value="delay = $d;ms" />
<log value="received call from $callerId;" />
<accept value="183" />
<waitforsignal signaldelayvar="d" level="-20dB" maxtime="3000ms" />
<log value="signal delay (-20dB) = $d;ms" />
<block test="$d; > 3000">
 <log value="rejecting call: no signal is detected above -20dB within 3 seconds" />
 <reject value="503" />
</block>
<log value="accepting call: signal is detected above -20dB within 3 seconds" />
<accept value="200" />
<playaudio value="music.wav" maxtime="222s" />

writecdr Saves a variable to CDR report, optionally analyses it as numeric performance indicator
Notes:
  • A CDR record represents SIP call, not CallXML session. However it is possible to execute "writecdr" before making a call
  • If you use CDR CSV files, and if your code contains conditional branches (i.e. "writecdr" is not always executed), you should put a "writecdr" with empty value in the beginning of your script, so it will be always executed.
  • CSV CDR file's schema (headers) are updated only for the first call in the file. You may need to delete old CDR CSV files if you add new custom CDR headers
  • If you save CDR to your a database, you need to make CDR field names compatible with SQL syntax: e.g. column name must not start with a digit
See also: "report"
Attributes:
header (required) - header in CDR file
value (required) - variable to be saved
numeric (optional, "true"/"false", default is "false") - specifies whether to analyses variable as numeric performance indicator
qualityIsAscending (optional, "true"/"false") - indicates whether call quality increases or decreases with increasing of the variable. Is used to calculate percentiles and list of worst quality calls
<verifyaudio reference="C:\ivr.wav" maxtime="10s" mosvar="mos" />
<writecdr header="MOS" value="$mos;" numeric="true" qualityIsAscending="true" />
<-- if code contains conditional branches, you should put a "writecdr" with empty value in the beginning of your script, so it will be always executed -->
<writecdr header="callerCountry" value="" />
<if test="$calledId; matches ^\d{11}$">
 <writecdr header="callerCountry" value="Syria" />
</if>

writefile Writes a text to file. Is used to write files with custom format in CallXML script. Appends text to end of file
Attributes:
value (required) - text to be written to file
fileName (required) - absolute or relative file name
newLine (optional, "true"/"false", default is "false") - specifies whether to insert line break before the text
splitInterval (optional) - enables splitting file into parts periodically, sets the period in seconds ("s" suffix), minutes ("m" suffix) or hours ("h" suffix). Adds a suffix "_yyyyMMdd_HHmmss" to the file name
<readcsv value="b_numbers_2014mar.csv" var0="numB" repeat="5" mode="random" />
<readcsv value="a_numbers.csv" var0="numA" mode="random" />
<log value="calling from $numA; to $numB;" />
<assign var="callStart" value="$time();" />
<call value="sip:$numB;@85.110.209.50" callerId="$numA;" maxringtime="60s" />
<on event="answer">
  <log value="call answered from $numA; to $numB;" />
  <wait value="$rand(1000,3000);ms" />
  <assign var="callEnd" value="$time();" />
  <writefile newLine="true" fileName="F:\ftproot\SUCEEDED.txt" splitInterval="1m"
   value="$callStart;;$callEnd;;$numA;;$numB;"
  />
  <on event="hangup">
   <assign var="callEnd" value="$time();" />
   <writefile newLine="true" fileName="F:\ftproot\SUCEEDED.txt" splitInterval="100m"
    value="$callStart;;$callEnd;;$numA;;$numB;"
   />
  </on>
  <exit />
</on>
<on event="callfailure">
  <log value="call failed from $numA; to $numB;" />
  <assign var="callEnd" value="$time();" />
  <writefile newLine="true" fileName="F:\ftproot\FAILED.txt" splitInterval="1m"
   value="$callStart;;$callEnd;;$numA;;$numB;"
  />
</on>
<on event="maxringtime">
  <log value="call timed out from $numA; to $numB;" />
  <assign var="callEnd" value="$time();" />
  <writefile newLine="true" fileName="F:\ftproot\FAILED.txt" splitInterval="1m"
   value="$callStart;;$callEnd;;$numA;;$numB;"
  />
</on>

Substitutions

Attributes in script my contain substitutions. A substitution starts with '$' and ends with ';'. It is replaced in runtime with another string depending on type of substitution.

$rand(x); is replaced by random integer value which is exponentially distributed from 0 to infinity with mean of x
$rand(x,y); is replaced by random integer value which is uniformly distributed from x (inclusive) to y (inclusive)
$randswitch(case1,case2,case3,...); is replaced by one of optional cases, selected randomly
$randdigits(number_of_digits); is replaced by a string of random digits from 0 to 9, with specified length = number_of_digits
$randfile(path\mask); is replaced by a random file from directory:
<playaudio value="$randfile(C:\StarTrinity\wav\*.wav);" />

$x; is replaced by value of variable with name x. Variable names are not case-sensitive. Name of variable can be computed dynamically from a prefix and another variable: $prefix$suffixVar;; or $arrayName[$arrayIndex;];
$global.x is replaced by value of global variable with name x Name of global variable can be computed dynamically from a prefix and another variable: $global.prefix$suffixVar;; or $global.someCache[$key;];
$time();, $time(format); is replaced by current date and time:
<recordmessage value="d:\recordings\$time(yyyyMMdd_HH_mm_ss_fff);.wav" />
$timeMs(); is replaced by software uptime in milliseconds. Can be used to calculate delays:
<assign var="t1" value="$timeMs();"/>
<call value="sip:test@23.45.67.89:5060" />
<on event="answer">
 <assign var="delay" mathvalue="$timeMs(); - $t1;"/>
 <log value="delay = $delay;ms" />
 <exit />
</on>
$timeOfDayInMinutes(); is replaced by number of minutes between current moment and previous midnight
$timeOfHourInMinutes(); is replaced by number of minutes between current moment and beginning of current hour
$param.x; is replaced by value of parameter which is defined in <params> section inside the script
$env.x; is replaced by windows environment variable:
<log value="temp directory: $env.TMP;; user name: $env.USERNAME;; windows directory: $env.windir;; machine name: $env.COMPUTERNAME;" />
$ext(x); is replaced by 'Contact' header of registered extension (see UAC registrations)
<transfer value="$ext(100);"/>

XML escape characters

According to XML specifications of the W3C, there are 5 characters that must not appear in their literal form in an XML document. The characters must be replaced according to table:
Original character XML replacement
" &quot;
' &apos;
& &amp;
" &quot;
< &lt;
> &gt;
Example:
<call value="sip:111@10.10.10.1?user=XXX&amp;password=YYY" />
You can use this tool to escape the characters automatically

Default variables

  • answerDelay - for outgoing calls after answer: answer delay in milliseconds
  • calledId - user ID (number) in "To" SIP header
  • callerId - user ID (number) in "From" SIP header
  • callerIpAddress - IP address of SIP call initiator. Is taken from IP protocol (layer 3)
  • callNumberInBurst - number of call in burst, when generating calls in burst mode, starts from 0
  • eventSubType - subtype of event which is currently handled by "on" CallXML element. Contains additional information about the event
  • eventType - type of event which is currently handled by "on" CallXML element
  • Id - CallXML session identifier. Starts with 0, increments sequentially
  • launcherType - identifies the way how the CallXML script is launched: "cli" - SIP Tester CLI; "gui" - SIP Tester GUI; "softswitch" - Softswitch
  • originatorId - identifier of current originator. Is set by "performAAA" CallXML element
  • redirectedNumber - user ID (number) in "Diversion" SIP header for incoming calls
  • sdpAttribute[name] - prefix for variables which contain attributes of remote SDP. Example: sdpAttributeptime, sdpAttributefmtp[0], sdpAttributefmtp[1], sdpAttributertpmap[2]
  • sipCallId - "Call-ID" SIP header
  • sipHeader[name] - prefix for variables which contain headers of "INVITE" message for incoming calls and "200 OK" for outgoing calls. Example: sipHeaderVia, sipHeaderVia[0], sipHeaderVia[1]
  • tenantId - identifier of current tenant, in softswitch multi-tenant mode. Is set by "performAAA" CallXML element

Attributes which are common to all CallXML elements

  • enabled ("true"/"false", default is "true") - turns off execution of a CallXML element. Is used to temporarily disable and enable some parts of the CallXML script
  • label - is used to identify the destination CallXML element in "goto"

Boolean expressions

The boolean expressions are used in "if", "block" and "goto" CallXML elements and in CDR display filter. The expression contain one or many comparisons, parentheses, boolean operators, strings in single quotes. Comparison operators are:
<less than
<=less than or equal
>greater than
>=greater than or equal
=, ==equal
!=, <>inequal
startswithleft operand starts with prefix (right operand)
matchesleft operand matches to regular expression (right operand)
containsleft operand contains right operand as a substring
Boolean operators are:
&, &&, and|, ||, or
Strings which are considered as "boolean false":
false0[empty string]
Examples of boolean expressions for CallXML script:
  • $calledId; = 98764352343
  • $callerId; startswith 123 or $calledId; = 345
  • $callerId; = 123456 and $calledId; = 1345678
  • 'a=123' = 'a=123'
Examples of boolean expressions for CDR filter:
  • Answered_Duration > 1000
  • Answered_Duration > 1000 and (CalledId startswith 10 or CalledId startswith 11)
  • Disconnection_Status = 200
  • Answer_Delay > 10000
  • CalledId = 123456
  • CallerId = 123456
  • CallerId contains 456
  • SIP_CallId = asefruyhnsdfteomhu7sngd@10.10.10.20
  • MyCustomCdrField1 > 10000 and MyCustomCdrField2 != OK
List of available CDR columns (fields) is displayed in GUI (CDR - fields..)
Copyright 2011-2017 StarTrinity.com | Blog | Contact lead developer via LinkedIn | Get support via TeamViewer