Preliminary and Postliminary Scripting
A preliminary is an executable script, written in the Javascript language, that defines processing actions (filtering or transformation) to be applied to a dial string before the dial rule’s action is performed.
A postliminary is an executable script, written in the Javascript language, that defines dial string transformations to be applied before querying an external device (gatekeeper, SIP peer, SBC, or MCU).
Transformation scripts output some modification of the DIAL_STRING variable (which is initially set to the dial string being evaluated).
Filtering scripts may pass the dial string on to the dial rule’s action (if the filter criteria aren’t met) or return one of the following:
●NEXT_RULE: Skips the rule being processed and passes the dial string to the next rule.
●BLOCK: Rejects the call.
Predefined Preliminary/Postliminary Scripting Variables
The following table describes the predefined variables you can use in a preliminary or postliminary script. The script can evaluate a variable or change its value (the change isn’t preserved after the script completes).
Variable | Initial value |
---|---|
CALLER_E164 | For H.323 calls only, an array variable initially set to the set of E.164 addresses of the caller. The length of the array is 0 if the caller doesn’t have an E.164 address. |
CALLER_H323ID | Array variable initially set to the set of H323ID addresses of the caller. The length of the array is 0 if the caller doesn’t have an H323ID address. |
CALLER_IS_IPV6 | “TRUE” if the caller is an IPv6 endpoint. Blank otherwise. |
CALLER_SIP_URI | Array variable initially set to the set of SIP URI addresses of the caller. The length of the array is 0 if the caller doesn’t have a SIP URI address. |
CALLER_SITE_AREA_CODE | Area code of the caller’s site. Blank if the site doesn’t have an area code. |
CALLER_SITE_COUNTRY_CODE | Country code of the caller’s site. Blank if the site doesn’t have a country code. |
CALLER_SITE_DIGITS | The number of subscriber number digits in the caller’s site (that is, the length of a phone number at the site, excluding area code). Blank if the site doesn’t have a number of digits. |
CALLER_SITE_NAME | The name of the caller’s site. |
CALLER_TEL_URI | Array variable initially set to the set of Tel URI addresses of the caller. The length of the array is 0 if the caller doesn’t have a Tel URI address. |
DIAL_STRING | Initially set to the dial string being evaluated. If the script modifies the DIAL_STRING value, the modified value is used as the input to the dial rule action. For SIP, when the DIAL_STRING is modified by the script, it’s use depends on the dial rule action: |
INPUT_SIP_HEADERS | For SIP calls only, an associative array containing the SIP headers in the received SIP INVITE message. Usage example: if(INPUT_SIP_HEADERS[« Supported »].matches(/.*ms-forking.*/)) { … } |
OUTPUT_SIP_HEADERS | An empty associative array. Headers that the script adds to this array replace the corresponding headers in the received SIP INVITE message. If a header added to this array isn’t in the received INVITE message, it’s added to the INVITE message. Usage example 1: var list = OUTPUT_SIP_HEADERS.get(« User-Agent »); if (list == null) { list = new java.util.LinkedList(); OUTPUT_SIP_HEADERS.put(« User-Agent », list); } list.add(« Someone. Not a RealPresence DMA 7000. »); Usage example 2: var list = OUTPUT_SIP_HEADERS.get(« Some-Custom-Header »); if (list == null) { list = new java.util.LinkedList(); OUTPUT_SIP_HEADERS.put(« Some-Custom-Header », list); } list.add(« Whatever you want »); |
Preliminary/Postliminary Scripting Functions
The following table describes the functions you can use in a preliminary or postliminary script. The parentheses at the end of the function name contain the parameters, if any, that the function accepts.
Function name and parameters | Details |
---|---|
getCallLicensesAllowed() | Return value: The <integer> total number of calls allowed by the current license. Includes aggregate/combined counts. |
getCallLicensesFree() | Return value: The <integer> total number of calls in the license still allowed (total allowed – total used). Includes aggregate/combined counts. |
getCallLicensesUsed() | Return value: The <integer> total number of calls used from the license. Includes aggregate/combined counts. |
isCallLicenseBurstEnabled() | Return value: The <boolean> value if the Call License Burst feature is licensed and enabled (true), or if it is either not licensed or is licensed but not enabled (false). |
getConferenceRoomOrID() | Return value: •For dial-outs to endpoints from VMRs or Polycom RealConnectTM conferences, returns the VMR or Skype Conference ID. •For dial-outs to the VMR or Polycom RealConnectTM conferences, and for dial-ins, returns the empty string. |
getHeader(<SIP header name>) | Return value: The contents of the specified SIP header in the original SIP INVITE request. Note: The return value is not changed if the SIP header is changed with setHeader. |
setHeader(<SIP header name>, <text>) | Replaces the current contents of the specified SIP header in the output version of the SIP INVITE request with <text>. Return value: None. Note: Any changes made using setHeader do not affect subsequent values returned by getHeader. |
getDisplayName(<text>) | Return value: The display name portion of <text>. Note: This function assumes that <text> uses the format of a SIP INVITE “To” header. |
getUser(<text>) | Return value: The user portion of <text>. Note: This function assumes that <text> uses the format of a SIP INVITE “To” header. |
getParameterString(<text>) | Return value: Returns the parameter string portion of <text>. Note: This function assumes that <text> uses the format of a SIP INVITE “To” header. |
appendParameterString(<headerText>, <text>) | Return value: Returns the result of appending <text> to the end of <headerText>, using the format of a SIP INVITE “To” header. |
removeHeader(<text>) | Removes the header named <text> from the SIP INVITE. Return value: None. |
getPeerHost() | Return value: •If invoked from an External SIP Peer postliminary script, returns the Next hop address configured for this SIP peer. •Otherwise, returns the empty string. |
getPeerNetOrNextHop() | Return value: •If invoked from an External SIP Peer postliminary script, returns one of the following: ©The Destination network value configured for this SIP peer, if defined ©The Next hop address for this SIP peer, if the Destination network setting is not configured •If not invoked from an External SIP Peer postliminary script, returns the empty string. |
getPeerPort() | Return value: •If invoked from an External SIP Peer postliminary script, returns the IP network port configured for this SIP peer. •Otherwise, returns the empty string. |
getPeerTransport() | Return value: •If invoked from an External SIP Peer postliminary script, returns the Transport type configured for this SIP peer. •Otherwise, returns the empty string. |
How Dial Rule Actions Affect SIP Headers
The following table shows how different dial rule actions apply a preliminary script’s modified dial string to the output SIP headers in a SIP call:
Dial rule action | Output SIP headers |
---|---|
Resolve to registered endpoint | The To header is replaced with the modified dial string. The request URI is based on the contact address of the registered endpoint, and not replaced with the modified dial string. |
Resolve to external address | The “To” header and the request URI are both replaced with the modified dial string. |
Resolve to service prefix | For a SIP peer proxy of type OCS: The “To” header is replaced with the modified dial string. The request URI is based on the address, port, and transport type of the proxy, and not replaced with the modified dial string. |
For a SIP peer proxy of type Other: The “To” header and the request URI are both replaced with the modified dial string. | |
Resolve to peer proxy | For a SIP peer proxy of type OCS: The “To” header is replaced with the modified dial string. The request URI is based on the address, port, and transport type of the proxy, and not replaced with the modified dial string. |
For a SIP peer proxy of type Other: The “To” header and the request URI are both replaced with the modified dial string. | |
Resolve to IP address | The “To” header and the request URI are both replaced with the modified dial string. |
Sample Preliminary and Postliminary Scripts
A preliminary is an executable script, written in the Javascript language, that defines processing actions (filtering or transformation) to be applied to a dial string before the dial rule’s action is performed.
A postliminary is an executable script, written in the Javascript language, that defines dial string transformations to be applied before querying an external device (gatekeeper, SIP peer, SBC, or MCU).
Transformation scripts output some modification of the DIAL_STRING variable (which is initially set to the dial string being evaluated).
Filtering scripts may pass the dial string on to the dial rule’s action (if the filter criteria aren’t met) or return one of the following:
●NEXT_RULE: Skips the rule being processed and passes the dial string to the next rule.
●BLOCK: Rejects the call.
The following sample scripts address many of the scenarios for which you might need a preliminary or postliminary script. You can use them as templates or starting points for your scripts.
// Example preliminary and postliminary scripts
///////////////////////////////
// STRIP PREFIX
// If the dial string has prefix 99, remove it
// 991234 –> 1234
DIAL_STRING = DIAL_STRING.replace(/^99/, » »);
///////////////////////////////
// ADD PREFIX
// Add prefix 99 to the dial string
// 1234 –> 991234
DIAL_STRING = « 99 » + DIAL_STRING;
///////////////////////////////
// STRIP PREFIX (SIP)
// If the dial string is a SIP URI with prefix 99 in the user part, remove it
// SIP:991234@abc.com –> sip:1234@abc.com
DIAL_STRING = DIAL_STRING.replace(/^sip:99([^@]*@)/i, »sip:$1″);
///////////////////////////////
// ADD PREFIX (SIP)
// If the dial string is a SIP URI, add prefix 99 to the user part
// SIP:1234@abc.com –> sip:991234@abc.com
DIAL_STRING = DIAL_STRING.replace(/^sip:([^@]*@)/i, »sip:99$1″);
///////////////////////////////
// SUBSTITUTE DOMAIN (SIP)
// If the dial string is a SIP URI, change the domain part to « example.com »
// SIP:1234@abc.com –> sip:1234@example.com
DIAL_STRING = DIAL_STRING.replace(/^sip:([^@]*)@(.*)/i, »sip:$1@example.com »);
///////////////////////////////
// FILTER
// If the dial string has prefix 99, do not match on this rule. Skip to the next rule.
// 991234 –> NEXT_RULE
if (DIAL_STRING.match(/^99/))
{
return NEXT_RULE;
}
///////////////////////////////
// FILTER (Inverted)
// Do not match on this rule unless the dial string has prefix 99.
// 1234 –> NEXT_RULE
if (!DIAL_STRING.match(/^99/))
{
return NEXT_RULE;
}
///////////////////////////////
// FILTER (SIP)
// If the dial string is a SIP URI with domain « example.com », do not match on this rule.
// Skip to the next rule.
// sip:1234@example.com –> NEXT_RULE
if (DIAL_STRING.toLowerCase().match(/^sip:[^@]*@example\.com/))
{
return NEXT_RULE;
}
///////////////////////////////
// PRINTLN
// Print out the information available to the script for this call.
// Information printed using the print or println functions
// is saved as a call audit event, which is viewable in the
// DMA interface under Reports > Call History, and also in the
// Script Debugging dialog box.
println(« DIAL_STRING: » + DIAL_STRING);
println(« CALLER_SITE_NAME: » + CALLER_SITE_NAME);
println(« CALLER_SITE_COUNTRY_CODE: » + CALLER_SITE_COUNTRY_CODE);
println(« CALLER_SITE_AREA_CODE: » + CALLER_SITE_AREA_CODE);
println(« CALLER_SITE_DIGITS: » + CALLER_SITE_DIGITS);
println(« CALLER_H323ID: » + CALLER_H323ID[0]);
println(« CALLER_E164: » + CALLER_E164[0]);
println(« CALLER_TEL_URI: » + CALLER_TEL_URI);
println(« CALLER_SIP_URI: » + CALLER_SIP_URI);
///////////////////////////////
// FILTER (Site)
// Do not allow callers from the atlanta site to use this rule.
// (Caller site == « atlanta ») –> NEXT_RULE
if (CALLER_SITE_NAME == « atlanta »)
{
return NEXT_RULE;
}
///////////////////////////////
// SITE BASED NUMERIC NICKNAMES
// Allow caller to omit country and area code when calling locally.
// Assumes that country and area codes are set in site topology.
// Assumes that all endpoints are registered with their full alias, including
// country and area code.
// 5551212 –> 14045551212
if (DIAL_STRING.length == CALLER_SITE_DIGITS)
{
DIAL_STRING = CALLER_SITE_COUNTRY_CODE + CALLER_SITE_AREA_CODE + DIAL_STRING;
}
else if (DIAL_STRING.length == ( parseInt(CALLER_SITE_AREA_CODE.length,10)
+ parseInt(CALLER_SITE_DIGITS,10)))
{
DIAL_STRING = CALLER_SITE_COUNTRY_CODE + DIAL_STRING;
}
///////////////////////////////
// SITE BASED NUMERIC NICKNAMES (SIP)
// Allow caller to omit country and area code when calling locally.
// Assumes that country and area codes are set in site topology.
// Assumes that all endpoints are registered with their full alias, including
// country and area code.
// sip:5551212@example.com –> sip:14045551212@example.com
if (DIAL_STRING.toLowerCase().match(/^sip:[^@]*@example\.com/))
{
user = DIAL_STRING.replace(/^sip:([^@]*)@.*/i, »$1″);
if (user.length == CALLER_SITE_DIGITS)
{
user = CALLER_SITE_COUNTRY_CODE + CALLER_SITE_AREA_CODE + user;
}
else if (user.length == ( parseInt(CALLER_SITE_AREA_CODE.length,10)
+ parseInt(CALLER_SITE_DIGITS,10)))
{
user = CALLER_SITE_COUNTRY_CODE + user;
}
DIAL_STRING = « sip: » + user + « @example.com »;
}
///////////////////////////////
// Limiting calls to a certain numeric dial range.
// (like the range specified Conference Settings screen)
//
var minGeneratedRoomId = 1000;
var maxGeneratedRoomId = 9999;
var number = parseInt(DIAL_STRING.replace(/^sip:([^@]*)@?(.*)/i, »$1″));
if (NaN != number && number > minGeneratedRoomId && number < maxGeneratedRoomId)
{
return;
}
return NEXT_RULE;
////////////////////////////////
// A sample script that routes all dial-out calls from a
// whitelist of VMRs to a SIP peer with prefix 11. All other dial-out
// calls will be routed to a SIP peer with prefix 22.
// The getConferenceRoomOrID() function returns a value only when
// the call is a dial-out from a VMR or Skype scheduled conference
// to an endpoint.
var whitelist_vmrs = [
« 1000 », // Specify list of VMRs; add or remove VMRs from this list.
« 2000 », // Make sure you use the syntax « <vmr number> »<comma>
« 3000 »,
];
var prefix = « 22 »;
////////////////////////////////
// Match against individual VMRs. ACCEPT if any of them matches.
//
if (0 <= whitelist_vmrs.indexOf(getConferenceRoomOrID()))
{
prefix = « 11 »;
}
DIAL_STRING = prefix + DIAL_STRING;
////////////////////////////////
// This script may be useful with « Resolve to external SIP peer » dial rules.
//
// This script skips this dial rule unless the call is SIP or SIPs. (Without
// this, the H.323-SIP gateway function could be invoked).
if (!DIAL_STRING.match(/^sips?:/i))
{
return NEXT_RULE;
}
////////////////////////////////
// This script may be useful with « Resolve to registered endpoint » dial rules.
//
// This script applies to registered H.323 endpoints calling registered SIP
// endpoints (e.g., 1001, 1002, …) and forces a H.323-SIP gateway call by
// adding the « sip: » dialing scheme.
//
// System configuration: Replace sip.domain.com with your system’s SIP domain.
DIAL_STRING = DIAL_STRING.replace(/(^1001$)/, »sip:$1@sip.domain.com »);
DIAL_STRING = DIAL_STRING.replace(/(^1002$)/, »sip:$1@sip.domain.com »);
////////////////////////////////
// This script may be useful with « Resolve to registered endpoint » dial rules.
//
// This script applies to registered SIP endpoints calling registered H.323
// endpoints (e.g., 1001, 1002, …) and forces a SIP-H.323 gateway call by
// removing the dialing scheme.
//
// System configuration: Replace sip.domain.com with your system’s SIP domain.
DIAL_STRING = DIAL_STRING.replace(/^sips?:(1001)@sip.domain.com.*/, »$1″);
DIAL_STRING = DIAL_STRING.replace(/^sips?:(1002)@sip.domain.com.*/, »$1″);
///////////////////////////////
// This script illustrates how to accept SIP dial strings that include upper case
// characters and convert them into dial strings with only lower case characters. Thus,
// calls to sip:AbCdEfG123@MyDomain.com are converted to sip:abcdefg123@mydomain.com.
//
// This script can configured as the preliminary for a dial rule with the action « Resolve
// to registered endpoint ».
//
// CAUTION: This script should be used in conjunction with some method to assure that all
// SIP registered endpoints have only lower-case characters. One way to assure this is to
// use this script in conjunction with a registration policy script that only allows
// endpoints with lower case SIP URIs to register. See « Sample Preliminary and
// Postliminary Scripts. »
//
// Applying this script to other dial rules can cause problems with interoperability.
// For example, if this script is applied to calls to external SIP peers, then the
// endpoints that are eventually contacted through those SIP peers must have lower case
// SIP URIs, or the calls will fail.
//
// Convert all SIP dial strings to lower case and record instances where the dial string
// was changed.
//
if (CALLER_SIP_URI != null && CALLER_SIP_URI != « ») {
var origDS = DIAL_STRING;
DIAL_STRING = DIAL_STRING.toLowerCase();
if (origDS != DIAL_STRING) {
println(« Dial string case changed. Original dialstring= » + origDS + » Lowered= » + DIAL_STRING);
}
}
////////////////////////////////
// This script may be useful with « Resolve to registered endpoint » or « Resolve
// to conference room ID » dial rules.
//
// This script prepends a prefix (8237) to any 4 digit dial string beginning
// with 4, 5, or 6 (SIP or H.323).
DIAL_STRING=DIAL_STRING.replace(/^([4-6][0-9]{3})$/, »8237$1″);
DIAL_STRING=DIAL_STRING.replace(/^(sips?:)([4-6][0-9]{3})$/, »$18237$2″);
DIAL_STRING=DIAL_STRING.replace(/^(sips?:)([4-6][0-9]{3})@/, »$18237$2″);
////////////////////////////////
// This script may be useful with « Resolve to service prefix » dial rules.
//
// This applies to PSTN or ISDN dial-outs from H.323 endpoints where the E.164
// number is prefixed with 9.
// The MCU is configured with prefix 2082 and 001 is the gateway session
// prefix. The MCU expects ** as the delimiter for the E.164 number.
DIAL_STRING=DIAL_STRING.replace(/^9([0-9]*$)/, »2082001**$1″);
////////////////////////////////
// This script may be useful with « Resolve to external gatekeeper » dial rules
// that send h323 calls to a Cisco VCS device.
//
// This script skips this dial rule if the call is SIP or SIPs. (Without this,
// the SIP-H.323 gateway function would be invoked).
// For H.323 Annex O dial strings of the form <alias>@<domain>, this script
// prepends the dialing scheme « h323: ».
if (DIAL_STRING.match(/^sips?:/i))
{
return NEXT_RULE;
}
else
{
DIAL_STRING=DIAL_STRING.replace(/^([^:@]*)@([^@]*)/, »h323:$1@$2″);
println(« new dial string is: » + DIAL_STRING);
}
////////////////////////////////
// This script may be useful with « Resolve to external SIP peer » dial rules.
// System configuration: Each SIP peer selected in the dial rule is configured
// with a prefix (11, 22, or 33).
// The script skips this dial rule for dial strings that are’t SIP, whose alias
// isn’t 5 characters, or that don’t specify one of the prefixes.
// For dial strings that meet these criteria, the domain is removed.
alias = DIAL_STRING.replace(/^sips?:([^@]*)@.*/i, »$1″);
if (alias.length != 5)
{
return NEXT_RULE;
}
if (alias.match(/^11/) || alias.match(/^22/) || alias.match(/^33/))
{
DIAL_STRING = DIAL_STRING.replace(/(^sips?:)([^@]*)@.*/i, »$1$2″);
println(« new DIAL_STRING: » + DIAL_STRING);
}
else
{
return NEXT_RULE;
}
////////////////////////////////
// This script may be useful with various dial rules.
//
// This script skips this dial rule if the dial string is not a 10 digit
// number. This works for both H.323 and SIP.
alias = DIAL_STRING.replace(/^sips?:([^@]*).*/i, »$1″);
if (!alias.match(/^[0-9]{10}$/))
{
return NEXT_RULE;
}
////////////////////////////////
// This script may be useful with « Resolve to conference room ID » dial rules.
//
// If there are conference rooms with the same numbers as registered endpoints,
// this script adds a prefix for conference rooms to distinguish them.
if(CALLER_SITE_NAME.match(/USDMAs/))
{
if(!(DIAL_STRING.match(/^61*|^(sip:61|h323:61)/)))
{
if(DIAL_STRING.match(/^sip:/))
{
DIAL_STRING = DIAL_STRING.replace(/^sip:([^@]*@)/i, »sip:61$1″);
}
else if (DIAL_STRING.match(/^h323:/))
{
DIAL_STRING = DIAL_STRING.replace(/^h323:([^@]*@)/i, »h323:61$1″);
}
else
{
DIAL_STRING = « 61 » + DIAL_STRING;
}
}
println(« New translated DIAL_STRING: » + DIAL_STRING);
}
if(!(DIAL_STRING.match(/^61*|^(sip:61|h323:61)/))){
return NEXT_RULE;
}