Call Processing Language (CPL): A Language for User Control of Internet Telephony Services
Extracted elements (29)
CPL is deliberately non-Turing-complete: it has no variables, loops, or ability to run external programs. This makes it safe to execute on multi-tenant telephony servers where users cannot be allowed to run arbitrary code.
CPL scripts are represented as XML documents so that parsing is easy, many parsers are publicly available, and graphical tools can create and edit any valid script. The tree structure of XML maps directly to the acyclic node-output graph of CPL actions.
Subaction references are restricted to back-references only (a 'sub' tag may only refer to subactions defined earlier in the script). This forbids all recursion, preventing non-terminating or non-decidable CPL scripts.
The set of call destinations is stored as an implicit global variable (the 'location set') rather than as explicit language parameters. This allows locations to be retrieved from external sources, filtered, and manipulated without requiring general language features that would harm simplicity and tractability.
Time switches reuse the iCalendar COS (RFC 2445) recurrence specification verbatim, enabling CPL scripts to be generated automatically from calendar applications and avoiding duplicate standardization work for time interval description.
For SIP, proxy node outputs map to: 'busy' (486/600 response), 'redirection' (3xx response), 'failure' (any other 4xx/5xx/6xx response), and 'noanswer' (no final response before timeout). SIP servers SHOULD honor the 'q' parameter of registrations for location priority.
For SIP, the 'origin' address-switch field maps to the 'From' header, 'destination' maps to the 'Request-URI', and 'original-destination' maps to the 'To' header. The 'destination' field never has a 'display' subfield due to SIP syntax constraints.
For SIP, the redirect node SHOULD send a 3xx response: '301 Moved Permanently' if permanent='yes', or '302 Moved Temporarily' otherwise. The reject node SHOULD map named statuses to SIP codes (e.g., 'busy'→486, 'notfound'→404, 'reject'→603, 'error'→500).
A CPL server MUST reject any script containing a reference to a namespace it does not understand, and MUST reject any script containing an extension tag or attribute that is not properly qualified to an appropriate XML namespace.
Every CPL extension MUST have an appropriate XML namespace assigned to it, different from the base CPL namespace 'urn:ietf:params:xml:ns:cpl', and MUST NOT change the syntax or semantics of the base CPL schema.
For any completely unknown address subfield, if the script is executed (rather than rejected at upload), the server MUST treat the 'not-present' output as the valid one.
References to subactions MUST be back-references only: a 'sub' tag MUST NOT refer to the action it appears in or to any action defined later in the script. Script servers MUST verify this at script upload time.
The CPL server SHOULD NOT directly map log file names uninterpreted onto local filesystem names, for security reasons, lest a security-critical file be overwritten.
The 'password' subfield of SIP URIs in address-switch nodes is NOT RECOMMENDED for general security reasons, as matching on passwords exposes sensitive credential material in scripts.
The 'until' and 'count' parameters MUST NOT both appear in the same 'time' output node. For recurring intervals, the 'duration' parameter MUST be small enough that consecutive intervals do not overlap.
The 'address-switch' node makes decisions based on the 'origin', 'destination', or 'original-destination' address of a call. Subfields include 'address-type', 'user', 'host', 'port', 'tel', and 'display', with match operators 'is', 'subdomain-of', and 'contains'.
The 'language-switch' node matches caller-preferred languages against language-tags (RFC 3066). The special range '*' and languages with q=0 are ignored. For SIP, the source is the 'Accept-Language' header.
The 'location' node adds a URL-specified address to the current location set. Parameters include 'url' (required), 'priority' (0.0–1.0, default 1.0), and 'clear' (whether to empty the set before adding). Multiple locations are added by cascading nodes.
The 'log' node records call event information to non-volatile storage identified by an optional logical 'name'. The log name MUST NOT be mapped directly to a filesystem path. A correctly operating server SHOULD NOT allow log operations to fail.
The 'lookup' node populates the location set from an external source specified by 'source' (a URI returning text/uri-list, or the keyword 'registration'). It has three outputs: 'success', 'notfound', and 'failure'. Default timeout is 30 seconds.
The 'mail' node sends an email notification to a 'mailto' URL when executed. It has a single result (no failure output) since e-mail delivery failures cannot be reliably detected in real time. Execution continues to the next node after sending.
The 'priority-switch' node routes calls based on priority level. Priorities in decreasing order are: 'emergency', 'urgent', 'normal', 'non-urgent'. If no priority is specified, 'normal' is assumed; unknown priorities are treated as 'normal' for 'greater'/'less' comparisons.
The 'proxy' node forwards the call to the current location set. It has outputs for 'busy', 'noanswer', 'redirection', 'failure', and 'default'. The 'ordering' parameter controls parallel (default), sequential, or first-only dispatch. After proxy completes, used locations are cleared from the set.
The 'redirect' node immediately terminates script execution and directs the calling party to the current location set. Its sole parameter 'permanent' (default 'no') controls whether a permanent or temporary redirection response is sent.
The 'reject' node immediately terminates the script and rejects the call. The required 'status' parameter takes named values ('busy', 'notfound', 'reject', 'error') or protocol-specific status codes. An optional 'reason' phrase may be specified.
The 'string-switch' node matches free-form Unicode string fields in the call request: 'subject', 'organization', 'user-agent', or 'display'. Strings are canonicalized to Unicode KC form and compared using locale-insensitive caseless mapping before matching.
The 'time-switch' node makes decisions based on iCalendar COS recurrence rules. It supports 'dtstart', 'dtend'/'duration', 'freq' (secondly through yearly), 'interval', 'until', 'count', and all byxxx parameters. Consecutive recurrence intervals MUST NOT overlap.
IANA registers the URN sub-namespace 'urn:ietf:params:xml:ns:cpl' for the CPL XML namespace, a corresponding XML schema, and the MIME type 'application/cpl+xml' for CPL scripts.
Because CPL scripts run on shared telephony servers and may be submitted by untrusted users, CPL is intentionally restricted: no variables, no loops, no external program execution, and no recursion. Servers MUST validate scripts at upload time rather than at call processing time to prevent denial-of-service from malformed scripts.