RFC 3880
Call Processing Language (CPL): A Language for User Control of Internet Telephony Services
Call Processing Language (CPL): A Language for User Control of Internet Telephony Services โจ
okay bestie, this is RFC 3880 ๐ and it's giving Call Processing Language (CPL). It came from the Network Working Group and was written by J. Lennox, X. Wu, and H. Schulzrinne, all from Columbia University. It's on the Standards Track, and it's dated October 2004 ๐๏ธ. The header doesn't list anything it obsoletes or updates, so there's nothing to cross-check there ๐ .
Status of This Memo
This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (2004).
Abstract
okay so the abstract is the big-picture pitch ๐ฆ. CPL is a language for describing and controlling Internet telephony services, and it's built to run on either network servers or user agents. It's meant to be simple, extensible, and easy for graphical clients to edit, and it doesn't depend on any operating system or signalling protocol ๐ธ. It's also safe for a server where users aren't allowed to run arbitrary programs, because it has no variables, no loops, and no way to run external programs ๐.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. Conventions of This Document. . . . . . . . . . . . . . 4
2. Structure of CPL Scripts . . . . . . . . . . . . . . . . . . . 4
2.1. High-level Structure. . . . . . . . . . . . . . . . . . 4
2.2. Abstract Structure of a Call Processing Action. . . . . 5
2.3. Location Model. . . . . . . . . . . . . . . . . . . . . 6
2.4. XML Structure . . . . . . . . . . . . . . . . . . . . . 6
3. Script Structure: Overview . . . . . . . . . . . . . . . . . . 7
4. Switches . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.1. Address Switches. . . . . . . . . . . . . . . . . . . . 9
4.1.1. Usage of "address-switch" with SIP. . . . . . . 11
4.2. String Switches . . . . . . . . . . . . . . . . . . . . 12
4.2.1. Usage of "string-switch" with SIP . . . . . . . 13
4.3. Language Switches . . . . . . . . . . . . . . . . . . . 14
4.3.1. Usage of "language-switch" with SIP . . . . . . 14
4.4. Time Switches . . . . . . . . . . . . . . . . . . . . . 15
4.4.1. iCalendar differences and implementation
issues. . . . . . . . . . . . . . . . . . . . . 20
4.5. Priority Switches . . . . . . . . . . . . . . . . . . . 21
4.5.1. Usage of "priority-switch" with SIP . . . . . . 22
5. Location Modifiers . . . . . . . . . . . . . . . . . . . . . . 22
5.1. Explicit Location . . . . . . . . . . . . . . . . . . . 23
5.1.1. Usage of "location" with SIP. . . . . . . . . . 23
5.2. Location Lookup . . . . . . . . . . . . . . . . . . . . 24
5.2.1. Usage of "lookup" with SIP. . . . . . . . . . . 25
5.3. Location Removal. . . . . . . . . . . . . . . . . . . . 25
5.3.1. Usage of "remove-location" with SIP . . . . . . 26
6. Signalling Operations. . . . . . . . . . . . . . . . . . . . . 26
6.1. Proxy . . . . . . . . . . . . . . . . . . . . . . . . . 26
6.1.1. Usage of "proxy" with SIP . . . . . . . . . . . 29
6.2. Redirect. . . . . . . . . . . . . . . . . . . . . . . . 29
6.2.1. Usage of "redirect" with SIP. . . . . . . . . . 30
6.3. Reject. . . . . . . . . . . . . . . . . . . . . . . . . 30
6.3.1. Usage of "reject" with SIP. . . . . . . . . . . 30
7. Non-signalling Operations. . . . . . . . . . . . . . . . . . . 31
7.1. Mail. . . . . . . . . . . . . . . . . . . . . . . . . . 31
7.1.1. Suggested Content of Mailed Information . . . . 32
7.2. Log . . . . . . . . . . . . . . . . . . . . . . . . . . 32
8. Subactions . . . . . . . . . . . . . . . . . . . . . . . . . . 33
9. Ancillary Information. . . . . . . . . . . . . . . . . . . . . 34
10. Default Behavior . . . . . . . . . . . . . . . . . . . . . . . 35
11. CPL Extensions . . . . . . . . . . . . . . . . . . . . . . . . 35
12. Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
12.1. Example: Call Redirect Unconditional. . . . . . . . . . 37
12.2. Example: Call Forward Busy/No Answer. . . . . . . . . . 38
12.3. Example: Call Forward: Redirect and Default . . . . . . 39
12.4. Example: Call Screening . . . . . . . . . . . . . . . . 40
12.5. Example: Priority and Language Routing. . . . . . . . . 41
12.6. Example: Outgoing Call Screening. . . . . . . . . . . . 42
12.7. Example: Time-of-day Routing. . . . . . . . . . . . . . 43
12.8. Example: Location Filtering . . . . . . . . . . . . . . 44
12.9. Example: Non-signalling Operations. . . . . . . . . . . 45
12.10. Example: Hypothetical Extensions. . . . . . . . . . . . 46
12.11. Example: A Complex Example. . . . . . . . . . . . . . . 48
13. Security Considerations. . . . . . . . . . . . . . . . . . . . 49
14. IANA Considerations. . . . . . . . . . . . . . . . . . . . . . 49
14.1. URN Sub-Namespace Registration for
urn:ietf:params:xml:ns:cpl. . . . . . . . . . . . . . . 49
14.2. Schema registration . . . . . . . . . . . . . . . . . . 50
14.3. MIME Registration . . . . . . . . . . . . . . . . . . . 50
15. Acknowledgments. . . . . . . . . . . . . . . . . . . . . . . . 51
A. An Algorithm for Resolving Time Switches . . . . . . . . . . . 52
B. Suggested Usage of CPL with H.323. . . . . . . . . . . . . . . 53
B.1. Usage of "address-switch" with H.323. . . . . . . . . . 53
B.2. Usage of "string-switch" with H.323 . . . . . . . . . . 55
B.3. Usage of "language-switch" with H.323 . . . . . . . . . 55
B.4. Usage of "priority-switch" with H.323 . . . . . . . . . 55
B.5. Usage of "location" with H.323. . . . . . . . . . . . . 56
B.6. Usage of "lookup" with H.323. . . . . . . . . . . . . . 56
B.7. Usage of "remove-location" with H.323 . . . . . . . . . 56
C. The XML Schema for CPL . . . . . . . . . . . . . . . . . . . . 56
Normative References . . . . . . . . . . . . . . . . . . . . . . . 70
Informative References . . . . . . . . . . . . . . . . . . . . . . 71
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 73
Full Copyright Statement . . . . . . . . . . . . . . . . . . . . . 74
1. Introduction
okay bestie, CPL is a language you can use to describe and control Internet telephony services ๐ฑ. It isn't tied to any one signalling architecture or protocol, and it's expected to get used with both the Session Initiation Protocol (SIP) [1] and H.323 [16] ๐.
CPL is powerful enough to describe a ton of services and features ๐. But it's also limited on purpose, so it can run safely on Internet telephony servers ๐ก๏ธ. The whole point is that users can't do anything more complex (or dangerous) than describe Internet telephony services ๐ โโ๏ธ. The language is not Turing-complete, and there's no way to write loops or recursion ๐.
CPL is also designed to be easily created and edited by graphical tools ๐. It's based on the Extensible Markup Language (XML) [2], so parsing it is easy, and there are lots of publicly available parsers for it ๐ง.
The structure of the language maps closely to its behavior, so an editor can understand any valid script, even ones written by hand โ๏ธ. The language is also designed so a server can easily confirm a script is valid when it receives it, instead of finding problems while a call is already being processed ๐ญ.
Implementations of CPL are expected to show up in both Internet telephony servers and advanced clients, and both can usefully process and direct users' calls ๐โจ. This document mainly talks about usage in servers ๐ฅ๏ธ. A mechanism will be needed to transport scripts between clients and servers. This document doesn't describe that mechanism, but related documents will ๐.
The framework and requirements for the CPL architecture are described in RFC 2824, "Call Processing Language Framework and Requirements" [17] ๐ง .
1.1. Conventions of This Document
okay so this is the important part for reading the rest ๐. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" are to be read as described in BCP 14, RFC 2119 [3]. They tell you the requirement levels for compliant CPL implementations ๐.
Some paragraphs are indented, like this ๐. They give motivations behind design choices, advice to implementors, or thoughts on future development of CPL or its extensions. They aren't essential to the specification of the language, so they're non-normative.
2. Structure of CPL Scripts
okay, now the fun part: how a script is actually put together ๐.
2.1. High-level Structure
A CPL script has two kinds of information in it: ancillary information about the script, and call processing actions ๐.
A call processing action is a structured tree. It describes the operations and decisions a telephony signalling server performs when a call set-up event happens ๐ณ. There are two types of call processing actions: top-level actions and subactions ๐. Top-level actions are triggered by signalling events that arrive at the server. Two top-level actions are defined. "incoming" is the action performed when a call arrives whose destination is the owner of the script. "outgoing" is the action performed when a call arrives whose originator is the owner of the script ๐ฒ.
Subactions are actions that can be called from other actions ๐. CPL forbids subactions from being called recursively, so see Section 8 ๐ซ๐.
Ancillary information is the stuff a server needs to process a script correctly, but it doesn't directly describe any operations or decisions ๐๏ธ. Right now, no ancillary information is defined, but that section is reserved for extensions to use ๐ธ.
2.2. Abstract Structure of a Call Processing Action โจ
okay so a call processing action is basically a bunch of nodes ๐ธ Each node is either an operation it performs or a decision it makes. Nodes can have parameters that tune exactly how they behave, and they usually have outputs that depend on what happened (the result of the decision or action). Think of it like a choose-your-own-adventure, but make it protocol ๐
Nodes and outputs are basically boxes and arrows, which is why CPL is designed so you can edit actions graphically. Nodes are arranged in a tree that starts at one root node, and outputs connect to more nodes. When an action runs, the top-level node does its thing, the server follows whichever output matches the result, and then it runs the node that output points to. This keeps going until it hits a node with no outputs specified. Because the graph is acyclic (no loops, bestie ๐), you always get a bounded and predictable number of nodes visited. no infinite spirals, we love stability ๐ฆ
If an output doesn't point to another node, the CPL server does a node- or protocol-specific action instead. Some nodes have default behaviour built in. For others, the default is implicit in the underlying signalling protocol or can be configured by the server administrator. For the full details on this, see Section 10 ๐
_________________ ___________________ ________ busy
| Address-switch | | location | | proxy |--------\
Call-->| field: origin | ->| url: sip:jones@ |->|timeout:| timeout|
| subfield: host | / | example.com | | 10s |--------|
|-----------------|/ |___________________| | | failure|
| subdomain-of: | |________|--------|
| example.com | |
|-----------------| ___________________________________________/
| otherwise | /........................................
| |\|. Voicemail .
|_________________| \. ____________________ .
->| location | __________ .
. | url: sip:jones@ | | redirect | .
. | voicemail. |->| | .
. | example.com | |__________| .
. |____________________| .
........................................
Figure 1: Sample CPL Action: Graphical Version ๐
2.3. Location Model
okay this part is so smart ๐ง one piece of info CPL needs is NOT stored in node parameters, and that's the set of locations a call should go to. Instead, it lives as an implicit global variable during the whole run of a processing action (including its subactions) ๐ This lets locations be pulled from external sources, filtered, and so on, without the language needing extra built-in support for that stuff (which could mess with the simplicity and tractability of understanding the language, and nobody wants that ๐).
The specific operations that add, retrieve, or filter location sets are covered in Section 5 โจ
For the incoming top-level call processing action, the location set starts out as the empty set. For the outgoing action, it starts out as the destination address of the call ๐
2.4. XML Structure
so CPL scripts are written as XML documents ๐ XML is thoroughly specified in the XML specification [2], and anyone implementing this spec should be familiar with that document, no cap. Quick recap though: XML is a hierarchy of tags, and each tag can have a number of attributes. It looks and feels a lot like HTML [18], because both are simplifications of the older, bigger standard SGML [19] ๐ฆ
Figure 2 shows the XML document for the graphical script in Figure 1. Both nodes and outputs are XML tags, and parameters are tag attributes. Usually node tags contain output tags, and vice-versa (with a few exceptions: see Sections 5.1, 5.3, 7.1, and 7.2) ๐
A connection from an output to another node is shown by nesting the pointed-to node's tag inside the outer node's output tag. When several outputs point at the same node (convergence), that's handled with subactions, which we'll get into in Section 8 ๐ซถ
The higher-level structure is made of tags for each piece of ancillary information, subactions, and top-level actions, in that order. All of this sits inside one special tag called "cpl", which is the outermost tag of the document ๐
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<subaction id="voicemail">
<location url="sip:jones@voicemail.example.com">
<redirect />
</location>
</subaction>
<incoming>
<address-switch field="origin" subfield="host">
<address subdomain-of="example.com">
<location url="sip:jones@example.com">
<proxy timeout="10">
<busy> <sub ref="voicemail" /> </busy>
<noanswer> <sub ref="voicemail" /> </noanswer>
<failure> <sub ref="voicemail" /> </failure>
</proxy>
</location>
</address>
<otherwise>
<sub ref="voicemail" />
</otherwise>
</address-switch>
</incoming>
</cpl>
Figure 2: Sample CPL Script: XML Version ๐ง
A complete XML Schema for CPL is in Appendix C ๐ The rest of the main sections describe CPL's semantics and give the syntax informally. For the formal syntax, go to the appendix, periodt ๐
3. Script Structure: Overview
okay so as I said, a CPL script is made of ancillary information, subactions, and top-level actions ๐ The full syntax of the "cpl" node is in Figure 3.
Tag: "cpl"
Parameters: None
Sub-tags: "ancillary" See Section 9
"subaction" See Section 8
"outgoing" Top-level actions to take on this user's
outgoing calls
"incoming" Top-level actions to take on this user's
incoming calls
Figure 3: Syntax of the top-level "cpl" tag ๐
Call processing actions (both top-level actions and subactions) are a tree of nodes and outputs, and both are described by XML tags. There are four categories of CPL nodes, and honestly they're all iconic ๐:
- switches, which represent choices a CPL script can make
- location modifiers, which add or remove locations from the location set
- signalling operations, which cause signalling events in the underlying protocol
- non-signalling operations, which trigger behaviour that does not affect the underlying protocol
4. Switches
switches are where the script gets to make choices ๐ A choice can be based on attributes of the original call request, or on things that are independent of the call.
Every switch is a list of conditions that can match a variable. Each condition corresponds to a node output, and that output points to the next node to run if the condition is true. The conditions get tried in the order they're written in the script, and the output for the first matching node is the one taken ๐ฆ
There are two special switch outputs that work on every switch type. The first is "not-present". It MAY occur anywhere in the list of outputs, and it's true if the variable the switch was meant to match was not in the original call setup request. (In this document, that's sometimes described as the information being "absent" ๐) The second is "otherwise", which MUST be the last output specified if it's present. It matches when no other condition did ๐
if no condition matches and there's no "otherwise" output in the script, the default script behaviour kicks in. See Section 10 for more on that ๐ซถ
Switches MAY contain no outputs. They MAY only contain an "otherwise" output โจ
Such switches are not particularly useful, but might be created by tools which automatically generate CPL scripts. ๐ค
4.1. Address Switches ๐
okay so address switches are how a CPL script makes decisions based on one of the addresses that showed up in the original call request ๐โจ they're summarized in Figure 4 below, bestie ๐ซถ
Node: "address-switch"
Outputs: "address" Specific addresses to match
Parameters: "field" "origin", "destination",
or "original-destination"
"subfield" "address-type", "user", "host",
"port", "tel", or "display"
(also: "password" and "alias-type")
Output: "address"
Parameters: "is" Exact match
"contains" Substring match (for "display" only)
"subdomain-of" Sub-domain match (for "host", "tel")
Figure 4: Syntax of the "address-switch" node
address switches have two node parameters, "field" and "subfield" ๐ the "field" one is mandatory, and it's how the script picks which address gets checked: the call's origin address ("origin"), its current destination address ("destination"), or its original destination ("original-destination"), which is the destination the call had before any earlier forwarding got invoked ๐ฆ servers MAY define additional field values, so you might see extra ones depending on the server ๐
the "subfield" one is optional and picks which part of the address matters. the possible values are "address-type", "user", "host", "port", "tel", and "display" โจ additional subfield values MAY be defined for protocol-specific stuff too ๐ (the "password" subfield is defined for SIP in Section 4.1.1, and the "alias-type" subfield is defined for H.323 in Appendix B.1 ๐ง) if you don't specify a subfield, the "entire" address gets matched, and what that actually means is defined for each underlying signalling protocol ๐ธ servers MAY define additional subfield values here as well.
here's the breakdown of each subfield ๐
address-type: this tells you the type of the underlying address, which is the URI scheme, if the address can be written as a URI ๐ฅ the types this document specifically talks about are"sip","tel", and"h323". it's not case-sensitive, and every defined address type has a value for it.user: for e-mail style addresses, this is the user part of the address ๐ for a telephone-number-style address, it's the subscriber number. it's case-sensitive, and it may be absent.host: this is the Internet host name or IP address that goes with the address, written in host name, IPv4, or IPv6 [4] textual format ๐ host names get compared as strings, and IP addresses get compared numerically. (the presence or location of an IPv6::omitted-zero-bits block doesn't matter for matching ๐) host names are never equal to IP addresses, because no DNS resolution is performed, and IPv4 addresses are never equal to IPv6 addresses, even when the IPv6 address is a v4-in-v6 embedding ๐ this one is not case sensitive, and it may be absent.
for host names only, you get subdomain matching with the "subdomain-of" match operator ๐ฆ that operator ignores leading dots in the hostname or the match pattern, if there are any โจ
port: this is the TCP or UDP port number of the address, as a number in decimal format ๐ it's not case sensitive, because it MUST only contain decimal digits, and leading zeros get ignored ๐tel: this is a telephone subscriber number, if the address has one in it ๐ it's not case sensitive (telephone numbers may contain the symbols'A','B','C', or'D'), and it may be absent. it can be matched with the"subdomain-of"match operator, and punctuation and separator characters in telephone numbers get discarded ๐ซถdisplay: this is the "display name," or the user-visible name that goes with an address ๐ it's a Unicode string, and it gets matched with the case-insensitive algorithm described in Section 4.2 ๐ the"contains"operator can be applied to it, and it may be absent.
for any completely unknown subfield, the server MAY reject the script when it's submitted, with some indication of the problem ๐ but if a script with an unknown subfield does get executed, the server MUST consider the "not-present" output to be the valid one ๐ญ
the "address" output tag can take exactly one of three possible parameters, and they tell you what kind of matching is allowed ๐
is: an output with this match operator gets followed if the subfield being matched in the"address-switch"exactly matches the argument of the operator โจ it can be used for any subfield, or for the entire address if no subfield was specified.subdomain-of: this one only works for the"host"and"tel"subfields ๐ฆ for"host", it matches if the hostname being matched is a subdomain of the domain in the operator's argument. sosubdomain-of="example.com"would matchexample.com,research.example.com, andzaphod.sales.internal.example.com๐ IP addresses can be given as arguments too, but they only match exactly ๐ฅ for"tel", the output matches if the telephone number being matched has a prefix that matches the argument, sosubdomain-of="1212555"would match the telephone number1 212 555 1212.๐งcontains: this only applies to the"display"subfield ๐ the output matches if the display name being matched contains the argument of the match as a substring ๐ธ
4.1.1. Usage of "address-switch" with SIP ๐ฆ
for SIP, the "origin" address corresponds to the From header, "destination" corresponds to the Request-URI, and "original-destination" corresponds to the To header ๐
the "display" subfield of an address is the display-name part of that address, if it's there ๐ because of SIP's syntax, the "destination" address field will never have a "display" subfield ๐
the "address-type" subfield of an address is the URI scheme of that address, and the other address fields depend on that "address-type" โจ
for SIP URIs, the "user", "host", and "port" subfields correspond to the user, host, and port elements of the URI syntax ๐ (here's the tea: following the definitions of RFC 3261 [1], a SIP URI that doesn't specify a port is not the same as an explicit port 5060. the first one is indicated by an absent port subfield ๐) the "tel" subfield is defined to be the user part of the URI, with visual separators stripped, if the user=phone parameter is given to the URI, or if the server is otherwise configured to recognize the user part as a telephone number ๐ there's also an extra subfield, "password", which corresponds to the password element of the SIP URI and is case-sensitive ๐ญ however, using this field is NOT RECOMMENDED for general security reasons ๐ฅ
for tel URLs, the "tel" and "user" subfields are the subscriber name, and in the "tel" case, visual separators get stripped ๐ the "host" and "port" subfields are both not present, so don't go looking for them ๐
for h323 URLs, subfields MAY be set according to the scheme in Appendix B ๐ง
for other URI schemes, only the "address-type" subfield is defined by this specification ๐ธ servers MAY set other pre-defined subfields, or MAY support additional subfields ๐
if no subfield is specified for addresses in SIP messages, the string being matched is the URI part of the address ๐ซถ for "is" matches, standard SIP URI matching rules get used, and for "contains" matches, the URI is used verbatim ๐
4.2. String Switches โจ
string switches let a CPL script make decisions based on free-form strings that show up in a call request ๐ they're summarized in Figure 5 ๐ฆ
Node: "string-switch"
Outputs: "string" Specific string to match
Parameters: "field" "subject", "organization",
"user-agent", or "display"
Output: "string"
Parameters: "is" Exact match
"contains" Substring match
Figure 5: Syntax of the "string-switch" node
string switches have one node parameter, "field" ๐ it's mandatory, and it specifies which string gets matched ๐
string switches depend on which call signalling protocol is being used ๐ธ
four fields are defined, and here they are. each one's value is a free-form Unicode string with no other structure defined ๐
subject: the subject of the call ๐organization: the organization of the call's originator ๐ซถuser-agent: the name of the program or device that the call request was made with ๐display: free-form text associated with the call, meant to be shown to the recipient, with no other semantics defined by the signalling protocol ๐
strings get matched as case-insensitive Unicode strings, in this order ๐ first, strings get canonicalized to the "Compatibility Composition" (KC) form, as specified in Unicode Standard Annex #15 [5] โจ then, strings get compared using locale-insensitive caseless mapping, as specified in Unicode Standard Annex #21 [6] ๐ฅ
Heads up, bestie: code to perform the first step, in Java and Perl, is available. see the links from Annex 5 of UAX 15 [5]. the case-insensitive string comparison in the Java standard class libraries already performs the second step, and other Unicode-aware libraries should be similar ๐ง
the output tag of string matching is named "string", and it has a mandatory argument, which is either "is" or "contains". those mean whole-string match or substring match, respectively ๐
4.2.1. Usage of "string-switch" with SIP ๐
for SIP, the fields "subject", "organization", and "user-agent" correspond to the SIP header fields with the same name ๐ฆ they're used verbatim, exactly as they appear in the message ๐
the "display" field is not used, and it's never present ๐ญ
4.3. Language Switches โจ
okay bestie, language switches ๐ธ these let a CPL script make decisions based on which languages the caller wants to talk in. Figure 6 has the whole vibe ๐
Node: "language-switch"
Outputs: "language" Specific string to match
Parameters: None
Output: "language"
Parameters: "matches" Match if the given language
matches a language-range of the
call.
Figure 6: Syntax of the "language-switch" node
The language switch itself takes no parameters ๐ฆ
The "language" output has one parameter, "matches" ๐ Its value is a language-tag, as defined in RFC 3066 [7]. The caller may have sent a set of language-ranges, also defined in RFC 3066, and the CPL server checks each language-tag in the script against those language-ranges in the request. Main character energy ๐
For the full details of how language-ranges match language-tags, go read RFC 3066 ๐ค But the short version is this: a language-range matches a language-tag if it exactly equals the tag, or if it exactly equals a prefix of the tag where the first character right after that prefix is "-" โจ
If the caller sends the special language-range "*", it gets ignored when matching ๐ Languages with a "q" value of 0 get ignored too.
This switch MAY be not-present. ๐
4.3.1. Usage of "language-switch" with SIP
With SIP, the language-ranges for the "language-switch" come from the SIP "Accept-Language" header field ๐ If the initial SIP request doesn't have that header field, the switch is not-present ๐ญ
Note that because of CPL's first-match semantics in switches, "q" values other than 0 of the "Accept-Language" header fields are ignored. ๐
4.4. Time Switches
Time switches let a CPL script make decisions based on the time and/or date when the script is running โฐ Figure 7 is the cheat sheet ๐ง
Time switches don't care what signalling protocol is underneath ๐
Node: "time-switch"
Outputs: "time" Specific time to match
Parameters: "tzid" RFC 2445 Time Zone Identifier
"tzurl" RFC 2445 Time Zone URL
Output: "time"
Parameters: "dtstart" Start of interval (RFC 2445 DATE-TIME)
"dtend" End of interval (RFC 2445 DATE-TIME)
"duration" Length of interval (RFC 2445 DURATION)
"freq" Frequency of recurrence ("secondly",
"minutely", "hourly", "daily",
"weekly", "monthly", or "yearly")
"interval" How often the recurrence repeats
"until" Bound of recurrence (RFC 2445 DATE-TIME)
"count" Number of occurrences of recurrence
"bysecond" List of seconds within a minute
"byminute" List of minutes within an hour
"byhour" List of hours of the day
"byday" List of days of the week
"bymonthday" List of days of the month
"byyearday" List of days of the year
"byweekno" List of weeks of the year
"bymonth" List of months of the year
"wkst" First day of the work week
"bysetpos" List of values within
set of events specified
Figure 7: Syntax of the "time-switch" node
Time switches are modelled closely on recurring time intervals from the Internet Calendaring and Scheduling Core Object Specification (iCalendar COS), RFC 2445 [8] ๐
This means CPL scripts can be generated automatically from calendar books ๐ It also means we get to re-use all the amazing existing work on specifying time intervals. iykyk ๐
If future standards-track documents come out that update or obsolete RFC 2445, any changes or clarifications they make to recurrence handling apply to CPL time-switches too ๐ฆ
An algorithm for working out whether an instant falls inside a given recurrence is in Appendix A ๐งฎ
The "time-switch" tag takes two optional parameters, "tzid" and "tzurl", both defined in RFC 2445 (Sections 4.8.3.1 and 4.8.3.5 respectively) ๐ธ The "tzid" is the label a time zone definition gets referenced by. If it starts with a forward slash (solidus), it points at a to-be-defined global time zone registry. Otherwise it's defined locally at the server. The "tzurl" is a network location where you can grab an up-to-date VTIMEZONE definition for the timezone โจ
Labels that don't start with a forward slash are defined locally, but it is RECOMMENDED that servers support at least the naming scheme used by the Olson Time Zone database [9] ๐ Examples of timezone databases that use the Olson scheme are the zoneinfo files on most Unix-like systems, and the standard Java TimeZone class ๐
Servers SHOULD resolve "tzid" and "tzurl" references to time zone definitions at the time the script is uploaded. They MAY periodically refresh these resolutions so they've got the freshest definition of a time zone ๐ And if a "tzurl" goes invalid, servers SHOULD remember the most recent valid data retrieved from the URL. Protect that data like it's your bestie's secret ๐ซถ
If a script gets uploaded with a "tzid" and "tzurl" the CPL server doesn't recognize or can't resolve, it SHOULD diagnose and reject this at script upload time. ๐ซ If neither "tzid" nor "tzurl" is present, all non-UTC times within this time switch should be interpreted as "floating" times, i.e., they're specified in the local timezone of the CPL server ๐งญ
Because of daylight-savings-time changes over the year, you have to specify time switches in a given timezone. UTC offsets aren't enough. A time-of-day routing rule that held between 9 am and 5 pm in the eastern United States would start holding between 8 am and 4 pm at the end of October ๐
Authors of CPL servers should be careful to handle intervals correctly when local time jumps, at the start or end of daylight-savings time โณ Watch out especially for times that happen more than once when clocks get set back ๐ The algorithm in Appendix A is believed to handle this correctly ๐
Time nodes give you a list of periods where their output should be taken ๐ They have two required parameters. The first is "dtstart", which marks the beginning of the first period in the list. The second is exactly one of "dtend" or "duration", which give the ending time or the length of the period, respectively ๐ The "dtstart" and "dtend" parameters are formatted as iCalendar COS DATE-TIME values, as specified in Section 4.3.5 of RFC 2445 [8]. Since time zones live in the top-level "time-switch" tag, only forms 1 or 2 (floating or UTC times) can be used here ๐ The "duration" parameter is an iCalendar COS DURATION parameter, as specified in section 4.3.6 of RFC 2445. Both the DATE-TIME and DURATION syntaxes are subsets of the matching syntaxes from ISO 8601 [20] ๐ง
For a recurring interval, the "duration" parameter MUST be small enough such that subsequent intervals do not overlap. ๐จ For non-recurring intervals, durations of any positive length are fine โจ Zero-length and negative-length durations are not allowed ๐ โโ๏ธ
If no other parameters are specified, a time node indicates just a single period of time ๐ฆ Fancier sets of periods get built as recurrences. A recurrence is set up by including the "freq" parameter, which says what kind of recurrence rule you've got ๐ Parameters other than "dtstart", "dtend", and "duration" SHOULD NOT be specified unless "freq" is present, though CPL servers SHOULD accept scripts with such parameters present, and ignore the other parameters. ๐ซถ
The "freq" parameter takes one of these values: "secondly" for periods repeating on an interval of a second or more, "minutely" for a minute or more, "hourly" for an hour or more, "daily" for a day or more, "weekly" for a week or more, "monthly" for a month or more, and "yearly" for a year or more ๐ These values are not case-sensitive ๐
The "interval" parameter holds a positive integer saying how often the recurrence rule repeats ๐ Its default value is "1", which means every second for a "secondly" rule, every minute for a "minutely" rule, every hour for an "hourly" rule, every day for a "daily" rule, every week for a "weekly" rule, every month for a "monthly" rule, and every year for a "yearly" rule โจ
The "until" parameter defines an iCalendar COS DATE or DATE-TIME value that bounds the recurrence rule in an inclusive way ๐ If the "until" value lines up with the recurrence, that date or date-time becomes the last instance of it ๐ If specified as a date-time value, then it MUST be specified in UTC time format. โฑ๏ธ If "until" isn't present and "count" isn't present either, the recurrence is considered to repeat forever โพ๏ธ
The "count" parameter sets the number of occurrences that range-bound the recurrence ๐ข The "dtstart" parameter counts as the first occurrence ๐ฅ The "until" and "count" parameters MUST NOT occur in the same "time" output. ๐ โโ๏ธ๐
The "bysecond" parameter is a comma-separated list of seconds within a minute, valid from 0 to 59 โฒ๏ธ The "byminute" parameter is a comma-separated list of minutes within an hour, also 0 to 59 ๐ The "byhour" parameter is a comma-separated list of hours of the day, valid from 0 to 23 ๐
The "byday" parameter is a comma-separated list of days of the week. "MO" means Monday, "TU" means Tuesday, "WE" means Wednesday, "TH" means Thursday, "FR" means Friday, "SA" means Saturday, and "SU" means Sunday ๐ These values are not case-sensitive ๐
Each "byday" value can also get a positive (+n) or negative (-n) integer in front of it ๐ฅ When that's there, it means the nth occurrence of that day within a "monthly" or "yearly" recurrence. For example, in a "monthly" rule, +1MO (or simply 1MO) is the first Monday of the month, while -1MO is the last Monday of the month ๐๏ธ No integer modifier means all days of that type within the specified frequency. So in a "monthly" rule, MO means every Monday in the month ๐ซง
The "bymonthday" parameter is a comma-separated list of days of the month. Valid values are 1 to 31 or -31 to -1 ๐ For example, -10 is the tenth to last day of the month ๐คฉ
The "byyearday" parameter is a comma-separated list of days of the year. Valid values are 1 to 366 or -366 to -1 ๐ธ For example, -1 is the last day of the year (December 31st), and -306 is the 306th to last day of the year (March 1st) ๐
The byweekno parameter lets you list weeks of the year as a comma-separated list of ordinals, like 3 for the third week ๐. Valid values are 1 to 53 or -53 to -1, and these follow the week numbering from ISO 8601 [20]. A week is a seven-day period that starts on the week start day (see wkst). Week one of the calendar year is the first week with at least four (4) days in that year ๐๏ธ. This parameter is only valid for yearly rules.
Note: Assuming a Monday week start, week 53 can only occur when January 1 is a Thursday or, for leap years, if January 1 is a Wednesday. ๐ค
The bymonth parameter takes a comma-separated list of months, with valid values of 1 to 12 ๐ธ.
The wkst parameter sets the day the work week starts. Valid values are "MO", "TU", "WE", "TH", "FR", "SA" and "SU". It matters when a weekly recurrence has an interval greater than 1 and a byday parameter is specified. It also matters in a yearly recurrence when a byweekno parameter is specified. The default is "MO", following ISO 8601 [20] ๐
.
The bysetpos parameter takes a comma-separated list of values that pick the nth occurrence within the set of events the rule creates. Valid values are 1 to 366 or -366 to -1. It MUST only be used in conjunction with another byxxx parameter. For example, "the last work day of the month" looks like this ๐ผ:
<time -timerange- freq="monthly" byday="MO,TU,WE,TH,FR"
bysetpos="-1">
Each bysetpos value can include a positive (+n) or negative (-n) integer. When present, it points at the nth occurrence of that specific item within the set of events the rule specifies ๐ฏ.
If byxxx parameter values fall outside the available scope (for example, bymonthday="30" in February), they are simply ignored ๐.
Byxxx parameters change the recurrence in some way. When a byxxx rule part covers a period that is the same as or longer than the frequency, it usually reduces or limits how many occurrences get generated ๐. For example, freq="daily" bymonth="1" shrinks the recurrence from every day (when bymonth isn't present) down to just the days in January โ๏ธ. When a byxxx parameter covers a period shorter than the frequency, it usually expands the number of occurrences instead ๐. For example, freq="yearly" bymonth="1,2" takes the days in the yearly set from 1 (when bymonth isn't present) up to 2 โจ.
If multiple byxxx parameters are specified, then after the freq and interval parameters are evaluated, the byxxx parameters are applied to the current set of occurrences in this order: bymonth, byweekno, byyearday, bymonthday, byday, byhour, byminute, bysecond, and bysetpos. After that, count and until are evaluated ๐งฎ.
Here is an example of how multiple byxxx parameters get evaluated ๐:
<time dtstart="19970105T083000" duration="10M"
freq="yearly" interval="2" bymonth="1" byday="SU"
byhour="8,9" byminute="30">
First, interval="2" gets applied to freq="yearly", which gives "every other year." Then bymonth="1" gets applied, giving "every January, every other year." Next, byday="SU" gives "every Sunday in January, every other year." Then byhour="8,9" gives "every Sunday in January at 8 AM and 9 AM, every other year." Next, byminute="30" gives "every Sunday in January at 8:30 AM and 9:30 AM, every other year." Finally, the second is derived from dtstart to end up in "every Sunday in January from 8:30:00 AM to 8:40:00 AM, and from and 9:30:00 AM to 9:40:00 AM, every other year." ๐ฅฐ Similarly, if the byminute, byhour, byday, bymonthday, or bymonth parameter were missing, the matching minute, hour, day, or month would be pulled from the dtstart parameter ๐.
The iCalendar COS RDATE, EXRULE, and EXDATE recurrence rules don't map directly to components of the time-switch node ๐
โโ๏ธ. You can get the same effect as the exception rules by ordering your switch rules so earlier ones exclude times ๐ซ. You can get the same effect as the additional-date RDATE rules by using sub nodes (see Section 8) to link several outputs to the same following node ๐.
The "not-present" output is never true for a time switch. However, it MAY be included to keep switch processing more regular ๐ .
4.4.1. iCalendar Differences and Implementation Issues
4.4.1. iCalendar Differences and Implementation Issues โจ
(This sub-sub-section is non-normative.)
The way recurring events work in this section is identical (apart from syntax and formatting) to RFC 2445 [8], with just one extra restriction ๐. That restriction is that consecutive instances of recurrence intervals may not overlap ๐ง.
While CPL was being designed, people really debated whether the entire iCalendar COS recurrence spec should go into CPL or just a subset of it ๐ค. In the end, compatibility between the two protocols was declared the top priority ๐. That choice creates some extra implementation issues for CPL server implementors ๐ ๏ธ.
It doesn't seem possible to figure out, in constant time, whether a given instant falls within one of the intervals defined by a full iCalendar COS recurrence ๐ญ. The main problems are these:
- The
countparameter can't be checked in constant running time, because the server has to enumerate every recurrence fromdtstartup to the present to see whether the current recurrence satisfies it. However, a server can expand acountparameter once, off-line, to find the date of the last recurrence. That date can then be treated as a virtualuntilparameter for the server's internal processing ๐. - Similarly, the
bysetposparameter requires the server to enumerate every instance of the occurrence from the start of the current recurrence set until the present. This takes some more complex pre-processing, but generally a single recurrence with abysetposparameter can be split into several recurrences without it ๐งฉ. - Finally, constant running time for time switches also requires that a candidate starting time for a recurrence can be established quickly and uniquely, so we can check whether it satisfies the other restrictions ๐โโ๏ธ. This requires that a recurrence's duration not be longer than its repetition interval, so a given instant can't fall within several consecutive potential repetitions of the recurrence. The restriction that consecutive intervals not overlap partially satisfies this condition, but doesn't fully ensure it. Again, pre-processing can help resolve this to some extent ๐งน.
The algorithm given in Appendix A runs in constant time after these pre-processing steps ๐ฆ.
Servers ought to check that recurrence rules don't create absurd run-time or memory requirements, and reject the ones that do, just as they ought to check that CPL scripts in general aren't absurdly large ๐.
4.5. Priority Switches
Priority switches let a CPL script make decisions based on the priority set for the original call ๐จ. They're summarized in Figure 8, and they depend on the underlying signalling protocol ๐ก.
Node: "priority-switch"
Outputs: "priority" Specific priority to match
Parameters: None
Output: "priority"
Parameters: "less" Match if priority is less
than that specified
"greater" Match if priority is greater
than that specified
"equal" Match if priority is equal
to that specified
Figure 8: Syntax of the "priority-switch" node
Priority switches take no parameters ๐.
The "priority" tag takes one of three parameters: "greater", "less", or "equal". The values of these parameters are one of the following priorities, in decreasing order: "emergency", "urgent", "normal", and "non-urgent". These values are matched in a case-insensitive way. Outputs with the "less" parameter are taken if the call's priority is less than the priority given in the argument, and so on ๐ฏ.
If no priority is specified in a message, the priority is considered to be "normal". If an unknown priority is specified in the call, it's treated as equivalent to "normal" for "greater" and "less" comparisons, but it's compared literally for "equal" comparisons ๐ซถ.
Since every message has a priority, the "not-present" output is never true for a priority switch. However, it MAY be included, to keep switch processing more regular ๐.
4.5.1. Usage of "priority-switch" with SIP
The priority of a SIP message corresponds to the "Priority" header in the initial INVITE message ๐.
5. Location Modifiers โจ
The abstract location model of CPL is described in Section 2.3. The behavior of several of the signalling operations (defined in Section 6) depends on the current location set specified. Location nodes add or remove locations from the location set ๐.
There are three types of location nodes. Explicit locations add literally-specified locations to the current location set ๐. Location lookups obtain locations from some outside source ๐. Location filters remove locations from the set, based on some specified criteria ๐งน.
5.1. Explicit Location ๐
okay so explicit location nodes are the ones that just say the location, literally, no detours ๐ Their syntax is in Figure 9.
Explicit location nodes are dependent on the underlying signalling protocol ๐ฆ
Node: "location"
Outputs: None (Next node follows directly)
Next node: Any node
Parameters: "url" URL of address to add to location set
"priority" Priority of this location (0.0-1.0)
"clear" Whether to clear the location set before
adding the new value
Figure 9: Syntax of the "location" node
Explicit location nodes have three node parameters ๐ธ The mandatory "url" parameter is the URL of the address you want to add to the location set. Only one address per location node, so if you want a bunch, you just cascade these nodes like a little chain ๐
The optional "priority" parameter sets a priority for the location. It's a floating-point number between 0.0 and 1.0. If you skip it, the server SHOULD assume a default priority of 1.0. The optional "clear" parameter decides whether the location set gets wiped before the new location goes in. It can be "yes" or "no", and "no" is the default โจ
Basic location nodes only have one possible result, because there's literally no way they can fail ๐ (If a basic location node points at a location the underlying signalling protocol doesn't support, the script server SHOULD detect that and report it to the user when the script is submitted. Caught early, bestie ๐) That's why their XML representations don't have explicit output tags. The <location> tag just directly contains another node.
5.1.1. Usage of "location" with SIP
All SIP locations are represented as URLs, so the locations in "location" tags get interpreted directly. No translation drama ๐ง
5.2. Location Lookup
Locations can also come in through external means, using location lookups ๐ The syntax for these tags is in Figure 10.
Location lookup is dependent on the underlying signalling protocol ๐
Node: "lookup"
Outputs: "success" Next node if lookup was successful
"notfound" Next node if lookup found no addresses
"failure" Next node if lookup failed
Parameters: "source" Source of the lookup
"timeout" Time to try before giving up on the lookup
"clear" Whether to clear the location set before
adding the new values
Output: "success"
Parameters: none
Output: "notfound"
Parameters: none
Output: "failure"
Parameters: none
Figure 10: Syntax of the "lookup" node
Location lookup nodes have one mandatory parameter and two optional ones ๐ซถ The mandatory one is "source", which is where the lookup goes. It can be a URI or a non-URI value. If "source" is a URI, it points at a location the CPL server can query to get an object with the text/uri-list media type (see the IANA registration of this type, which also shows up in RFC 2483 [10]). The query runs verbatim, with no extra information (like URI parameters) tacked on. The server then adds the locations inside that object to the location set ๐ฅ
CPL servers MAY refuse to allow URI-based sources for location queries, for some or all URI schemes. If they do that, they SHOULD reject the script at script upload time ๐ โโ๏ธ
There has been discussion of having CPL servers add URI parameters to the location request, so that (for instance) CGI scripts could be used to resolve them. However, the consensus was that this should be a CPL extension, not a part of the base specification. ๐
Non-URL sources are sources not specified by a URL, which the server can query for addresses to add to the location set. The only non-URL source currently defined is "registration", which means all the locations currently registered with the server โจ
The "lookup" node also has two optional parameters. The "timeout" parameter is how long, as a positive integer number of seconds, the script is willing to wait for the lookup. If you don't specify it, the default is 30. The "clear" parameter decides whether the location set gets cleared before the new locations are added ๐
Lookup has three outputs: "success", "notfound", and "failure". "notfound" is taken when the lookup succeeded but didn't find any locations. "failure" is taken when the lookup failed for some reason, including when the specified timeout got exceeded. If a given output isn't present, script execution terminates and the default behavior gets performed ๐
5.2.1. Usage of "lookup" with SIP
For SIP, the "registration" lookup source corresponds to the locations registered with the server using "REGISTER" messages ๐ฎ
5.3. Location Removal
A CPL script can also take locations out of the location set, using the "remove-location" node ๐งน The syntax of this node is defined in Figure 11.
The meaning of this node depends on the underlying signalling Protocol ๐ฆ
Node: "remove-location"
Outputs: None (Next node follows directly)
Next node: Any node
Parameters: "location" Location to remove
Figure 11: Syntax of the "remove-location" node
A "remove-location" node removes locations from the location set. It's mostly useful right after a "lookup" node. There's an example of this in Section 12.8 ๐ญ
The "remove-location" node has one optional parameter. The "location" parameter gives the URI of a location to remove from the set, in a signalling-protocol-dependent manner. If you don't give this parameter, all locations get removed from the set. Yikes, big reset ๐ญ
The "remove-location" node has no explicit output tags. In the XML syntax, the XML "remove-location" tag directly encloses the next node's tag ๐
5.3.1. Usage of "remove-location" with SIP
The location in the "location" parameter of the "remove-location" node gets matched against the location set using the standard rules for SIP URI matching (the same ones used, e.g., to match Contact addresses when refreshing registrations) ๐
6. Signalling Operations โจ
Signalling operation nodes cause signalling events in the underlying signalling protocol ๐ Three signalling operations are defined: "proxy," "redirect," and "reject." Main character energy ๐
6.1. Proxy
Proxy causes the triggering call to be forwarded on to the currently specified set of locations ๐ฆ The syntax of the proxy node is in Figure 12.
The specific signalling events invoked by the "proxy" node depend on the signalling protocol, though the general concept should apply to any signalling protocol ๐ธ
Node: "proxy"
Outputs: "busy" Next node if call attempt returned "busy"
"noanswer" Next node if call attempt was not
answered before timeout
"redirection" Next node if call attempt was redirected
"failure" Next node if call attempt failed
"default" Default next node for unspecified outputs
Parameters: "timeout" Time to try before giving up on the
call attempt
"recurse" Whether to recursively look up
redirections
"ordering" What order to try the location set in.
Output: "busy"
Parameters: none
Output: "noanswer"
Parameters: none
Output: "redirection"
Parameters: none
Output: "failure"
Parameters: none
Output: "default"
Parameters: none
Figure 12: Syntax of the "proxy" node
After a proxy operation completes, the CPL server picks the "best" response to the call attempt, as defined by the signalling protocol or the server's administrative configuration rules ๐ง
If the call attempt succeeded, CPL execution terminates and the server proceeds to its default behavior (normally, to allow the call to be set up) ๐ Otherwise, the next node matching one of the "proxy" node's outputs gets taken. The "busy" output gets followed if the call was busy. "noanswer" gets followed if the call wasn't answered before the "timeout" parameter expired. "redirection" gets followed if the call was redirected. And "failure" gets followed if the call setup failed for any other reason ๐
If one of those conditions is true but the matching output wasn't specified, the "default" output of the "proxy" node gets followed instead. If there's also no "default" node specified, CPL execution terminates and the server goes back to its default behavior (normally, forwarding the best response upstream to the originator) ๐
Note: CPL extensions to allow in-call or end-of-call operations will require an additional output, such as "success", to be added. ๐
If no locations were in the set, or if the only locations in the set were ones the server can't proxy a call to (for example, "http" URLs), the "failure" output gets taken ๐
Proxy has three optional parameters ๐ The "timeout" parameter specifies the time, as a positive integer number of seconds, to wait for the call to be completed or rejected. Once that time has elapsed, the call attempt is terminated and the "noanswer" branch gets taken. If you don't specify this parameter, the default is 20 seconds if the "proxy" node has a "noanswer" or "default" output specified. Otherwise, the server SHOULD allow the call to ring for a reasonably long period of time (to the maximum extent that server policy allows) โณ
The second optional parameter is "recurse", which can take two values: "yes" or "no". This controls whether the server should automatically place further call attempts to telephony addresses found in redirection responses returned from the initial server ๐ Heads up: if "recurse" is "yes", the "redirection" output never gets taken by the script. In that case, this output SHOULD NOT be present. The default value of this parameter is "yes" ๐
The third optional parameter is "ordering". It can have three possible values: "parallel", "sequential", and "first-only". This parameter says what order the locations in the location set should be tried in. "parallel" asks that they all get tried simultaneously. "sequential" asks that the one with the highest priority gets tried first, then the one with the next-highest priority second, and so on, until one succeeds or the set runs out. "first-only" tells the server to try only the highest-priority address in the set, then follow one of the outputs ๐ฅ The priority of locations in a set is determined by server policy, though CPL servers SHOULD honor the "priority" parameter of the "location" tag. The default value of this parameter is "parallel" โจ
Once a proxy operation completes, if control gets passed on to other nodes, all locations that have been used get cleared from the location set. So the set gets emptied of proxyable locations if "ordering" was "parallel" or "sequential". If "ordering" was "first-only", only the highest-priority item gets removed from the set. (In all cases, non-proxyable locations such as "http" URIs stay put ๐ง.) In the case of a "redirection" output, the new addresses the call was redirected to then get added to the location set ๐ฆ
6.1.1. Usage of "proxy" with SIP โจ
okay so for SIP, the best response to a "proxy" node gets picked by the algorithm in the SIP spec ๐ and the node's outputs line up with these events:
busy: a 486 or 600 response was the best response received for the call request ๐redirection: a 3xx response was the best response received for the call request ๐ฆfailure: any other 4xx, 5xx, or 6xx response was the best response received for the call request ๐no-answer: no final response came back for the call request before the timeout expired ๐
SIP servers SHOULD honor the q parameter of SIP registrations when they're figuring out location priority ๐ซถ
6.2. Redirect ๐ฆ
Redirect tells the server to make the calling party try placing its call to whatever set of locations is currently specified. The syntax is in Figure 13 ๐
Node: "redirect"
Outputs: None (No node may follow)
Next node: None
Parameters: "permanent" Whether the redirection should be
considered permanent
Figure 13: Syntax of the "redirect" node
So the exact behavior depends on the signalling protocol underneath, but the semantics are pretty universal โจ
Redirect immediately ends the CPL script, which is why it has no outputs and no next node. It has one parameter, permanent, that says whether the result should count as a permanent redirection. The value is either "yes" or "no", and the default is "no." ๐ธ
6.2.1. Usage of "redirect" with SIP
The SIP server SHOULD send a 3xx class response to a call request when it hits a "redirect" tag ๐ If "permanent" was "yes", the server SHOULD send "301" (Moved permanently). Otherwise it SHOULD send "302" (Moved temporarily) ๐
6.3. Reject ๐
Reject nodes make the server turn down the call attempt. Their syntax is in Figure 14, and the behavior depends on the signalling protocol involved, though the semantics are generally the same everywhere ๐ง
Node: "reject"
Outputs: None (No node may follow)
Next node: None
Parameters: "status" Status code to return
"reason" Reason phrase to return
Figure 14: Syntax of the "reject" node
A reject node immediately terminates the CPL script, so no outputs and no next node. Literally the vibe is "bye" ๐
It has two arguments, "status" and "reason". The "status" argument is required, and it can take one of the values "busy", "notfound", "reject", "error", or a signalling-protocol-defined status. The "reason" argument optionally lets the script give a reason for the rejection ๐
6.3.1. Usage of "reject" with SIP
Servers that implement SIP SHOULD also allow the "status" field to be a numeric argument matching a SIP status in the 4xx, 5xx, or 6xx range ๐ฅ
They SHOULD send the "reason" parameter in the SIP reason phrase โจ
Here's a suggested mapping for the named statuses. Servers MAY use a different mapping, though similar semantics SHOULD be preserved ๐ซถ
"busy": 486 Busy Here
"notfound": 404 Not Found
"reject": 603 Decline
"error": 500 Internal Server Error
7. Non-signalling Operations ๐
okay so besides the signalling operations, CPL also defines a bunch of operations that don't affect the telephony signalling protocol and don't depend on it either ๐
7.1. Mail ๐
The mail node has the server notify a user about the status of the CPL script through electronic mail. Its syntax is in Figure 15 ๐ง
Node: "mail"
Outputs: None (Next node follows directly)
Next node: Any node
Parameters: "url" Mailto url to which the mail should be sent
Figure 15: Syntax of the "mail" node
The mail node takes one argument: a "mailto" URL that gives the address, plus any extra parameters you want on the mail. The server sends the message with the content to that url, and it SHOULD also include other status info about the original call request and the CPL script at the time of the notification ๐ฆ
Using a full "mailto" URL instead of just an email address lets you specify extra email headers, like this:
<mail url="mailto:jones@example.com?subject=Lookup%20failed" /> ๐
A mail node has only one possible result, since failure of email delivery can't reliably be known in real time ๐ญ So its XML version doesn't have output tags. The <mail> tag just directly contains another node tag โจ
Also, XML syntax requires that ampersand characters, &, which are used as parameter separators in "mailto" URLs, get quoted as & inside parameter values. (See Section C.12 of the XML specification [2].) ๐
7.1.1. Suggested Content of Mailed Information
This section gives suggested guidelines for the mail sent because of a "mail" node, for requests triggered by SIP. The message mailed (no matter what protocol triggered it) SHOULD contain all of this info, but servers MAY choose a different format if they want ๐
- If the "mailto" URI didn't specify a subject header, the subject of the email is "[CPL]", followed by the subject header of the SIP request. If the URI did specify a subject header, that one gets used instead ๐
- The "From" field of the email is set to a CPL server configured address, overriding any "From" field in the "mailto" URI ๐ซถ
- Any "Reply-To" header in the URI is honored. If none is given, then an email-ized version of the origin field of the request is used, if possible. (For example, a SIP "From" header with a sip: URI would be converted to an email address by stripping the URI scheme.) ๐ง
- If the "mailto" URI specifies a body, that body is used. If none was specified, the body SHOULD contain at least the identity of the caller (both the caller's display name and address), the date and time of day, the call subject, and, if available, the call priority ๐ฅ
The server SHOULD honor the user's requested languages, and send the mail notification using an appropriate language and character set ๐ธ
7.2. Log ๐
The Log node has the server log info about the call to non-volatile storage. Its syntax is in Figure 16 ๐พ
Node: "log"
Outputs: None (Next node follows directly)
Next node: Any node
Parameters: "name" Name of the log file to use
"comment" Comment to be placed in log file
Figure 16: Syntax of the "log" node
Log takes two arguments, both optional. "name" specifies the name of the log, and "comment" gives a comment about the info being logged. Servers SHOULD also include other info in the log, like the time of the logged event, the info that triggered the call to be logged, and so forth. Logs belong to the owner of the script that logged the event. If the "name" parameter isn't given, the event goes to a standard, server-defined log file for the script owner. This spec doesn't define how users retrieve their logs from the server ๐
The name of a log is only a logical name, and it doesn't necessarily match any physical file on the server. How the log file name gets interpreted is server defined, and so is the mechanism for accessing these logs ๐
The CPL server SHOULD NOT directly map log names uninterpreted onto local file names, for security reasons, lest a security-critical file be overwritten. ๐
A correctly operating CPL server SHOULD NOT ever allow the "log" event to fail ๐ซถ So log nodes can only have one possible result, and their XML version doesn't have explicit output tags. A CPL <log> tag directly contains another node tag โจ
8. Subactions ๐
XML syntax defines a tree. To allow more general call flow diagrams, and to allow script re-use and modularity, we define subactions ๐ฆ
Two tags are defined for subactions: subaction definitions and subaction references. Their syntax is in Figure 17 ๐
Tag: "subaction"
Subtags: Any node
Parameters: "id" Name of this subaction
Pseudo-node: "sub"
Outputs: None in XML tree
Parameters: "ref" Name of subaction to execute
Figure 17: Syntax of subactions and "sub" pseudo-nodes
Subactions get defined through "subaction" tags. These tags are placed in the CPL script after any ancillary information (see Section 9), but before any top-level tags. They take one argument, "id", a token that gives the subaction a script-chosen name. The "id" value for every "subaction" tag in a script MUST be unique within that script ๐
Subactions get called from "sub" tags. The "sub" tag is a "pseudo-node", and it can be used anyplace in a CPL action where a true node could be used. It takes one parameter, "ref", which is the name of the subaction to be called. The "sub" tag has no outputs of its own, since control passes straight to the subaction ๐ง
References to subactions MUST refer to subactions defined before the current action. A "sub" tag MUST NOT refer to the action it appears in, or to any action defined later in the CPL script. Top-level actions can't be called from "sub" tags, or any other way. Script servers MUST verify at submission time that no "sub" node refers to any subaction that isn't its proper predecessor ๐ฅ
Allowing only back-references of subs forbids any sort of recursion. Recursion would introduce the possibility of non-terminating or non-decidable CPL scripts, a possibility our requirements specifically excluded. ๐
Every sub MUST refer to a subaction ID defined within the same CPL script. No external links are permitted ๐ซถ
Subaction IDs are case sensitive ๐ธ
If any subsequent version or extension defines external linkages, it should probably use a different tag, perhaps XLink [21]. Ensuring termination in the presence of external links is a difficult problem. ๐
9. Ancillary Information โจ
No ancillary information is defined in the base CPL specification. If ancillary information, not part of any operation, turns out to be necessary for a CPL extension, it SHOULD be placed within this tag ๐
The (trivial) definition of the ancillary information tag is in Figure 18 ๐
It may be useful to include timezone definitions inside CPL scripts directly, rather than referencing them externally with "tzid" and "tzurl" parameters. If it is, an extension could be defined to include them here. ๐ฆ
Tag: "ancillary"
Parameters: None
Subtags: None
Figure 18: Syntax of the "ancillary" tag
10. Default Behavior โจ
okay so bestie, this is the part where a CPL node hits an output that nobody filled in ๐ either the output tag is missing, or it's there but has no node inside. Whatever happens next depends on what the script has already done. Here's the playbook for each case, and yes, it's giving very "if no one told me what to do, I'll do what I'd normally do" energy ๐
- No location modifications or signalling operations performed, location set empty: Look up the user's location using whatever mechanism the server would use if there were no CPL script at all. Then proxy, redirect, or send a rejection message, using whatever policy the server would normally follow without a CPL script. ๐ธ
- No location modifications or signalling operations performed, location set non-empty: (This can only happen for outgoing calls. ๐) Proxy the call to the addresses in the location set. ๐ฆ
- Location modifications performed, no signalling operations: Proxy or redirect the call, whichever is the server's standard policy, to the addresses in the current location set. If the location set is empty, return a "notfound" rejection. ๐
- noanswer output of proxy, no timeout given: (this is a special case, iykyk ๐) If the "noanswer" output of a proxy node is unspecified, and no timeout parameter was given to the proxy node, the call should be allowed to ring for the maximum length of time allowed by the server (or the request, if the request specified a timeout). โณ
- Proxy operation previously taken: Return whatever the "best" response is of all the accumulated responses to the call up to this point, according to the rules of the underlying signalling protocol. ๐
11. CPL Extensions โจ
ngl this section is about how servers can go beyond the basics ๐ง Servers MAY support additional CPL features beyond the ones in this document. Some extensions that have been floated around are a way to check how a call got authenticated, richer control over H.323 addressing, end-system or admin-specific features, regular-expression matching for strings and addresses, and mid-call or end-of-call controls. ๐
Extensions are marked with XML namespaces [11]. Every extension MUST have its own appropriate XML namespace assigned to it. That namespace MUST be different from the XML namespace defined in Section 14. An extension MUST NOT change the syntax or semantics of the CPL schema defined in this document. Every XML tag and attribute that belongs to the extension MUST be properly qualified so it lives inside that namespace. ๐ซถ
Tags or attributes in a CPL script that are in the global namespace (so, not tied to any namespace at all) are treated the same as tags and attributes in the CPL namespace "urn:ietf:params:xml:ns:cpl". โจ
A CPL script SHOULD NOT declare any namespaces it doesn't use. For compatibility with parsers that aren't namespace-aware, a CPL script MAY leave out the base CPL namespace for a script that doesn't use any extensions. ๐
A CPL server MUST reject any script that references a namespace it doesn't understand. It MUST reject any script containing an extension tag or attribute that isn't qualified to be in an appropriate namespace. ๐ โโ๏ธ
Here's an alternate idea that was suggested for handling extensions:
<extension-switch>
<extension has="http://www.example.com/foo">
[extended things]
</extension>
<otherwise>
[non-extended things]
</otherwise>
</extension-switch>
The vibe was that this would let scripts be uploaded to a server without the author needing to figure out which extensions the server supports. ๐ฅบ But experience developing other languages, notably Sieve [22], was that it added way too much complexity. The "extension-switch" tag could, of course, be defined in a CPL extension itself. ๐ง
In the XML schema of CPL, we introduce three abstract elements: 'toplevelaction', 'switch', and 'action'. They have the abstract types 'TopLevelActionType', 'SwitchType', and 'ActionType'. Any top-level action in a CPL extension MUST be defined as a substitutionGroup of the abstract 'toplevelaction' element, and have its type extended from 'TopLevelActionType'. Any switch in a CPL extension MUST be defined as a substitutionGroup of the abstract 'switch' element, and have its type extended from 'SwitchType'. Any action in a CPL extension MUST be defined as a substitutionGroup of the abstract 'action' element, and have its type extended from 'ActionType'. ๐
12. Examples ๐
12.1. Example: Call Redirect Unconditional
This one is the simplest script ever ๐ It redirects every call to one fixed location. Check out Figure 19:
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<incoming>
<location url="sip:smith@phone.example.com">
<redirect/>
</location>
</incoming>
</cpl>
Figure 19: Example Script: Call Redirect Unconditional ๐ฆ
12.2. Example: Call Forward Busy/No Answer
Figure 20 shows slightly more drama ๐ฅ It starts with a proxy attempt to one address, and then does more stuff if that fails. It also shows how several outputs can share the same action subtree, using subactions. ๐ง
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<subaction id="voicemail">
<location url="sip:jones@voicemail.example.com">
<proxy/>
</location>
</subaction>
<incoming>
<location url="sip:jones@jonespc.example.com">
<proxy timeout="8">
<busy>
<sub ref="voicemail"/>
</busy>
<noanswer>
<sub ref="voicemail"/>
</noanswer>
</proxy>
</location>
</incoming>
</cpl>
Figure 20: Example Script: Call Forward Busy/No Answer ๐
12.3. Example: Call Forward: Redirect and Default
Figure 21 is giving proxy behavior with a twist ๐ The server first tries to proxy to a single address. If that attempt gets redirected, a new redirection is made using the locations that came back. In every other failure case for the proxy node, a default operation kicks in: forwarding to voicemail ๐
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<incoming>
<location url="sip:jones@jonespc.example.com">
<proxy>
<redirection>
<redirect/>
</redirection>
<default>
<location url="sip:jones@voicemail.example.com">
<proxy/>
</location>
</default>
</proxy>
</location>
</incoming>
</cpl>
Figure 21: Example Script: Call Forward: Redirect and Default โจ
12.4. Example: Call Screening
Figure 22 is a call screening script, and it shows address switches and call rejection in action ๐ โโ๏ธ Note that because the address-switch has no "otherwise" clause, if the initial pattern doesn't match, the script doesn't define any operations. The server then carries on with its default behavior, which would presumably be to contact the user. ๐ซถ
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<incoming>
<address-switch field="origin" subfield="user">
<address is="anonymous">
<reject status="reject" reason="I reject anonymous calls"/>
</address>
</address-switch>
</incoming>
</cpl>
Figure 22: Example Script: Call Screening ๐
12.5. Example: Priority and Language Routing
Figure 23 is all about routing based on a call's priority and language settings ๐ If the call request has a priority of "urgent" or higher, the default script behavior runs. Otherwise, the language field gets checked for "es" (Spanish). If it's there, the call goes to a Spanish-speaking operator. Everything else goes to an English-speaking operator. ๐ธ
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<incoming>
<priority-switch>
<priority greater="urgent"/>
<otherwise>
<language-switch>
<language matches="es">
<location url="sip:spanish@operator.example.com">
<proxy/>
</location>
</language>
<otherwise>
<location url="sip:english@operator.example.com">
<proxy/>
</location>
</otherwise>
</language-switch>
</otherwise>
</priority-switch>
</incoming>
</cpl>
Figure 23: Example Script: Priority and Language Routing ๐
12.6. Example: Outgoing Call Screening
Figure 24 is a filter for outgoing calls, and it stops 1-900 (premium) calls from ever being placed ๐ โโ๏ธ It also shows subdomain matching, which is lowkey so useful ๐
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<outgoing>
<address-switch field="original-destination" subfield="tel">
<address subdomain-of="1900">
<reject status="reject"
reason="Not allowed to make 1-900 calls."/>
</address>
</address-switch>
</outgoing>
</cpl>
Figure 24: Example Script: Outgoing Call Screening ๐
12.7. Example: Time-of-day Routing
Figure 25 shows time-based conditions and timezones, and honestly it's so satisfying ๐ฆ
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<incoming>
<time-switch tzid="America/New_York"
tzurl="http://zones.example.com/tz/America/New_York">
<time dtstart="20000703T090000" duration="PT8H" freq="weekly"
byday="MO,TU,WE,TH,FR">
<lookup source="registration">
<success>
<proxy/>
</success>
</lookup>
</time>
<otherwise>
<location url="sip:jones@voicemail.example.com">
<proxy/>
</location>
</otherwise>
</time-switch>
</incoming>
</cpl>
Figure 25: Example Script: Time-of-day Routing ๐
12.8. Example: Location Filtering ๐บ๏ธ
okay bestie, Figure 26 is about filtering the location set, and the vibe is "the server quietly fixes a buggy client so the call still goes through" ๐ . the story: version 0.9beta2 of the "Inadequate Software SIP User Agent" mis-implements some features ๐, so we have to work around its problems. one mobile device we registered can't talk to it successfully, so we just remove that location from the location set. once that's done, call setup is allowed to proceed normally โจ
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<incoming>
<string-switch field="user-agent">
<string is="Inadequate Software SIP User Agent/0.9beta2">
<lookup source="registration">
<success>
<remove-location location="sip:me@mobile.provider.net">
<proxy/>
</remove-location>
</success>
</lookup>
</string>
</string-switch>
</incoming>
</cpl>
Figure 26: Example Script: Location Filtering ๐
12.9. Example: Non-signalling Operations ๐ง
Figure 27 is all about out-of-band notifications, aka the server pinging you by email when the lookup server failed ๐ฌ. the main reason the "mail" node exists is so you can flag an error without a call even being involved, bc the user might otherwise have zero clue something went wrong ๐ฅบ
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<incoming>
<lookup
source="http://www.example.com/cgi-bin/locate.cgi?user=mary"
timeout="8">
<success>
<proxy/>
</success>
<failure>
<mail url="mailto:mary@example.com?subject=Lookup%20failed"/>
</failure>
</lookup>
</incoming>
</cpl>
Figure 27: Example Script: Non-signalling Operations ๐ธ
12.10. Example: Hypothetical Extensions ๐
Figure 28 shows a hypothetical extension that does distinctive ringing, and it's giving "future feature but make it spec" โจ The XML namespace "http://www.example.com/distinctive-ring" defines a brand new node named "ring".
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://www.example.com/distinctive-ring"
xmlns="http://www.example.com/distinctive-ring"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:CPL="urn:ietf:params:xml:ns:cpl"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:import namespace="urn:ietf:params:xml:ns:cpl"
schemaLocation="cpl.xsd"/>
<xs:complexType name="DRingAction">
<xs:complexContent>
<xs:extension base="CPL:ActionType">
<xs:attribute name="ringstyle" type="xs:string"
use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="ring" type="DRingAction"
substitutionGroup="CPL:action"/>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:dr="http://www.example.com/distinctive-ring"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd
http://www.example.com/distinctive-ring distinctive-ring.xsd">
<incoming>
<address-switch field="origin">
<address is="sip:boss@example.com">
<dr:ring ringstyle="warble"/>
</address>
</address-switch>
</incoming>
</cpl>
Figure 28: Example Schema and Script: Hypothetical Distinctive-Ringing Extension ๐ถ
Figure 29 implements a hypothetical new attribute for address switches so you can do regular-expression matches ๐ง It defines a new attribute "regex" for the standard "address" node.
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<incoming>
<address-switch field="origin" subfield="user"
xmlns:re="http://www.example.com/regex">
<address re:regex="(.*.smith|.*.jones)">
<reject status="reject"
reason="I don't want to talk to Smiths or Joneses"/>
</address>
</address-switch>
</incoming>
</cpl>
Figure 29: Example Script: Hypothetical Regular-Expression Extension ๐
12.11. Example: A Complex Example ๐
Finally, Figure 30 is the big boss example ๐ญ It shows the sophisticated behavior you can get by combining CPL nodes. Here the user tries to have calls reach their desk first. if they don't answer within a small amount of time, calls from the boss get forwarded to the mobile phone, and everything else goes to voicemail. if the call setup failed, no operation is specified, so the server's default behavior runs. iconic, honestly ๐ซถ
<?xml version="1.0" encoding="UTF-8"?>
<cpl xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:cpl cpl.xsd ">
<subaction id="voicemail">
<location url="sip:jones@voicemail.example.com">
<redirect />
</location>
</subaction>
<incoming>
<location url="sip:jones@phone.example.com">
<proxy timeout="8">
<busy>
<sub ref="voicemail" />
</busy>
<noanswer>
<address-switch field="origin">
<address is="sip:boss@example.com">
<location url="tel:+19175551212">
<proxy />
</location>
</address>
<otherwise>
<sub ref="voicemail" />
</otherwise>
</address-switch>
</noanswer>
</proxy>
</location>
</incoming>
</cpl>
Figure 30: Example Script: A Complex Example โจ
13. Security Considerations ๐
okay this section is SERIOUS, no cap ๐ค CPL is designed so services can be specified in a way that stops potentially hostile or mis-configured scripts from launching security attacks, denial-of-service attacks included. script runtime is strictly bounded by acyclicity, and the number of possible script operations is strictly limited, so scripts should not be able to inflict damage on a CPL server.
Because scripts can direct users' telephone calls, the method by which scripts are transmitted from a client to a server MUST be strongly authenticated. Such a method is not specified in this document. ๐จ
Script servers SHOULD allow server administrators to control the details of what CPL operations are permitted ๐งโ๐ป
14. IANA Considerations ๐
This document registers a new MIME type, application/cpl+xml, and a new URN per RFC 2141 [12], RFC 2648 [13], and RFC 3688 [14].
The XML namespace urn:ietf:params:xml:ns:cpl will only refer to the version of CPL in this document and will not change. Any CPL enhancements MUST be made by extensions and MUST have different namespaces. ๐
14.1. URN Sub-Namespace Registration for urn:ietf:params:xml:ns:cpl ๐งพ
URI: urn:ietf:params:xml:ns:cpl
Registrant Contact: Jonathan Lennox <lennox@cs.columbia.edu>
Xiaotao Wu <xiaotaow@cs.columbia.edu>
Henning Schulzrinne <hgs@cs.columbia.edu>
XML:
BEGIN
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type"
content="text/html;charset=iso-8859-1"/>
<title>Call Processing Language Namespace</title>
</head>
<body>
<h1>Namespace for Call Processing Language</h1>
<h2>urn:ietf:params:xml:ns:cpl</h2>
<p><a href="ftp://ftp.rfc-editor.org/in-notes/rfc3880.txt">
RFC3880</a>.</p>
</body>
</html>
END
14.2. Schema registration ๐๏ธ
This specification registers XML Schema for CPL, as per the guidelines in [14].
URI: urn:ietf:params:xml:schema:cpl
Registrant contact:
Jonathan Lennox <lennox@cs.columbia.edu>
Xiaotao Wu <xiaotaow@cs.columbia.edu>
Henning Schulzrinne <hgs@cs.columbia.edu>
XML: The XML can be found in Appendix C.
14.3. MIME Registration ๐ฆ
As an XML type, CPL's MIME registration conforms with "XML Media Types," RFC 3023 [15].
MIME media type name: application
MIME subtype name: cpl+xml
Mandatory parameters: none
Optional parameters: charset
As for application/xml in RFC 3023.
Encoding considerations: As for application/xml in RFC 3023.
Security considerations: See Section 13, and Section 10 of RFC
3023.
Interoperability considerations: Different CPL servers may use
incompatible address types. However, all potential
interoperability issues should be resolvable at the time a
script is uploaded; there should be no interoperability
issues which cannot be detected until runtime.
Published specification: This document.
Applications which use this media type: SIP proxy servers and
other telephony servers, and client software to control
their behavior.
Additional information:
Magic number: None
File extension: .cpl or .xml
Macintosh file type code: "TEXT"
Person and e-mail address for further information:
Jonathan Lennox <lennox@cs.columbia.edu>
Xiaotao Wu <xiaotaow@cs.columbia.edu>
Henning Schulzrinne <hgs@cs.columbia.edu>
Intended usage: COMMON
Author/Change Controller: The IETF.
15. Acknowledgments ๐
This document was reviewed and commented upon by the IETF IP Telephony Working Group. We specifically acknowledge the following people for their help:
The outgoing call screening script was written by Kenny Hom.
Paul E. Jones contributed greatly to the mappings of H.323 addresses.
The text of the time-switch section was taken (lightly modified) from RFC 2445 [8], by Frank Dawson and Derik Stenerson.
We drew a good deal of inspiration, notably the language's lack of Turing-completeness and the syntax of string matching, from the specification of Sieve [22], a language for user filtering of electronic mail messages. ๐ง
Thomas F. La Porta and Jonathan Rosenberg had many useful discussions, contributions, and suggestions. ๐ซถ
Richard Gumpertz performed a very useful last-minute technical and editorial review of the specification. ๐
A. An Algorithm for Resolving Time Switches โฐโจ
okay bestie, this one is the algorithm that tells you whether a given moment lands inside a repeating "time-switch" recurrence ๐๐ if you did the pre-processing from Section 4.4.1, it runs in constant time, which is so efficient it's giving main character ๐
there's open-source Java for it at http://www.cs.columbia.edu/~lennox/Cal-Code/ if you want to poke around ๐ง
the author believes it's correct, but this section is non-normative, so it's a helper, not the rulebook ๐ Section 4.4, and RFC 2445 [8], are the definitive definitions of recurrences, so those win if there's ever drama ๐ซถ
- Work out the time of the call, in the timezone of the time switch ๐
- If the call time is earlier than
dtstart, fail NOMATCH. ๐ โโ๏ธ - If the call time is less than
durationafterdtstart, succeed MATCH. ๐ - Find the smallest unit named in a
byxxxrule or byfreq. Call this the Minimum Unit. Then find the previous instant (before or equal to the call time) where every time unit smaller than the Minimum Unit matchesdtstart. If the Minimum Unit is a second, that instant is the instant itself. If it's a minute or an hour, the minutes (or the minutes and hours) have to matchdtstart. For every other Minimum Unit, the time-of-day has to matchdtstart. If the Minimum Unit is a week, the day-of-the-week has to matchdtstart. If it's a month, the day-of-the-month has to matchdtstart. If it's a year, the month and day-of-month both have to matchdtstart. ๐๏ธ
(ngl this part is where it gets spicy ๐ถ๏ธ you might have to roll back more than one Minimum Unit, because some months don't have a 31st (or 30th or 29th), and some years don't have a February 29th. in the Gregorian calendar you'll never need to roll back more than two months for a month unit, or eight years for a year unit. between 1904 and 2096, you'll never need more than four years, and the eight-year rollback only happens when the Gregorian calendar "skips" a leap year ๐)
Call this instant the Candidate Start Time. ๐
- If the time between the Candidate Start Time and the call time is more than the
duration, fail NOMATCH. ๐ซ - If the Candidate Start Time is later than the
untilparameter of the recurrence (or the virtualuntilcomputed off-line fromcount), fail NOMATCH. ๐ - Call the unit of the
freqparameter the Frequency Unit. Figure out the frequency unit enclosing the Candidate Start Time, and the one enclosingdtstart. Count how many frequency units have passed between those two. If that number isn't a multiple of theintervalparameter, fail NOMATCH. ๐ข - For every
byxxxrule, check that the Candidate Start Time matches one of the options that rule lists. If it does, succeed MATCH. ๐ฅณ - Work out a previous Candidate Start Time, and keep going until the gap between the Candidate Start Time and the call time is more than the
duration. If no Candidate Start Time ever got validated, fail NOMATCH. ๐
B. Suggested Usage of CPL with H.323 ๐๐ฆ
this appendix gives a suggested way to use CPL with H.323 [16] ๐ ITU Study Group 16, the folks who developed H.323, are planning to work on official CPL mappings for it, so this section is not normative ๐ซถ
B.1. Usage of "address-switch" with H.323 ๐
address switches are specified in Section 4.1, and this section spells out how H.323 messages map onto the fields and subfields of an address-switch ๐
for H.323, the "origin" address matches the alias addresses in the sourceAddress field of the Setup-UUIE user-user information element, and also the Q.931 [23] information element "Calling party number." if both fields are there, or if there are several alias addresses for sourceAddress, which one wins is a matter of local server policy. the server SHOULD use the same resolution it would use for routing decisions in that case ๐ง in the same way, the "destination" address matches the alias addresses of the destinationAddress field, and the Q.931 information element "Called party number." ๐ธ
the "original-destination" address matches the "Redirecting number" Q.931 information element if it's present. otherwise it's the same as the "destination" address ๐
how an H.323 address breaks into subfields depends on the type of the alias address ๐ there's an extra subfield type, "alias-type", defined for H.323 servers, which matches the address type. the possible values are "dialedDigits", "h323-ID", "url-ID", "transportID", "email-ID", "partyNumber", "mobileUIM", and "Q.931IE". if future versions of the H.323 specification add new alias address types, those names MAY also be used too โจ
before version 4 of H.323, "dialedDigits" was called "e164". the two names SHOULD be treated as synonyms ๐ฏโโ๏ธ
the "address-type" subfield for H.323 messages is "h323", unless the alias type is "url-ID" and the URL scheme is something other than h323. in that case the address-type is the URL scheme, as specified in Section 4.1.1 for SIP ๐
an H.323-aware CPL server SHOULD map the address subfields from the primary alias used for routing. it MAY also map subfields from other aliases, but only if the subfields in the primary address aren't present ๐ซถ
these mappings apply to the H.323 alias types:
- dialedDigits, partyNumber, mobileUIM, and Q.931IE: the "tel" and "user" subfields are the string of digits, same as the "entire-address" form. the "host" and "port" subfields are not present. ๐ข
- url-ID: the same mappings are used as for SIP, in Section 4.1.1. ๐
- h323-ID: the "user" field is the string of characters, same as the "entire-address" form. every other subfield is not present. ๐ชช
- email-ID: the "user" and "host" subfields are set to the matching parts of the e-mail address. the "port" and "tel" subfields are not present. the "entire-address" form matches the whole e-mail address ๐ง
- transportID: if the TransportAddress is of type "ipAddress," "ipSourceRoute," or "ip6Address," the "host" subfield is set to the "ip" element of the sequence, translated into the standard IPv4 or IPv6 text form, and the "port" subfield is set to the "port" element of the sequence in decimal. the "tel" and "user" fields are not present. the "entire-address" form is not defined. the representation and mapping of transport addresses is not defined for non-IP addresses ๐
H.323 [16] defines an "h323" URI scheme. this appendix defines a mapping for these URIs onto the CPL "address-switch" subfields, as given in Section 4.1. this definition is also available as RFC 3508 [24], which is an excerpt from the H.323 specification ๐
for h323 URIs, the "user", "host", and "port" subfields are set to the matching parts of the H.323 URL. the "tel" subfield is not present. the "entire-address" form matches the whole URI ๐
this mapping MAY be used for h323 URIs in an h323 "url-ID" address alias, and also for h323 URIs in SIP messages ๐
B.2. Usage of "string-switch" with H.323 ๐งต
for H.323, the "string-switch" node (see Section 4.2) works like this. the field "display" matches the Q.931 information element with the same name, copied verbatim. the fields "subject", "organization", and "user-agent" are not used and are never present ๐ โโ๏ธ
the "display" IE is usually used for Caller-ID purposes, so you could argue it should map to the "display" subfield of an "address-match" with the field "originator". but a) it's a message-level information element, not an address-level one, and b) the Q.931 specification [23] only says that "[t]he purpose of the Display information element is to supply display information that may be displayed by the user," so it seems more fitting to let it be matched in a "string-switch" instead ๐ค
B.3. Usage of "language-switch" with H.323 ๐
the language-ranges for the "language-switch" switch come from the H.323 UUIE "language". the switch is not-present if the initial message didn't contain this UUIE ๐ฃ๏ธ
B.4. Usage of "priority-switch" with H.323 ๐ฆ
every H.323 message is treated as having priority "normal" for the purpose of a priority switch (see Section 4.5) ๐
B.5. Usage of "location" with H.323 ๐
locations in explicit location nodes (Section 5.1) are specified as URLs. so every location added this way is read as alias type "url-ID" in H.323 ๐
other H.323 address alias types will need a CPL extension to be supported (see Section 11) ๐งฉ
B.6. Usage of "lookup" with H.323 ๐
for location lookup nodes (Section 5.2), the "registration" lookup source matches the locations registered with the server using "RAS" messages ๐ก
B.7. Usage of "remove-location" with H.323 ๐งน
location removal nodes (Section 5.3) remove addresses with the alias type "url-ID" using verbatim string matching on the URLs. if a "tel" URL is specified as the location, matching addresses (ignoring visual separators) with the alias types "dialedDigits" ("e164"), "partyNumber", "mobileUIM", or "Q.931IE" get removed too. no mechanism is provided to remove other alias types ๐๏ธ
C. The XML Schema for CPL ๐งพ๐
this section includes a full XML Schema describing the XML syntax of CPL ๐ every script submitted to a CPL server SHOULD comply with this XML Schema ๐ซถ when parsing scripts that comply with the CPL DTD in earlier documents, the DOCTYPE lines in those scripts should be ignored ๐
compliance with this schema is not a sufficient condition for correctness of a CPL script, because many of the conditions described in this specification can't be expressed in schema syntax. so passing the schema doesn't mean the script is actually correct ๐ฅบ
Figure 31 shows the structure of the schema. 'incoming' and 'outgoing' are defined as the substitutionGroup of the 'toplevelaction'. all the switches are defined as the substitutionGroup of the 'switch' element. all the actions are defined as the substitutionGroup of the 'action' element. ๐ธ
Okay bestie, here's the whole map of the schema ๐บ๏ธโจ It's giving tree vibes, and once you see how the switches branch you'll be obsessed ๐
+---------+ +------+ +--address
+-+ancillary| |switch|** +--------------+ | +-not-present
| +---------+ +---+--+ **|address-switch+-+-+-address
| | * +--------------+ +--otherwise
| +---------+ +----+ | * +--language
+-+subaction+-+Node| | * +---------------+ | +-not-present
| +---------+ +----+ | **|language-switch|-+-+-language
| | * +---------------+ +--otherwise
| | * +--priority
| | * +---------------+ | +-not-present
| | **|priority-switch|-+-+-priority
| | * +---------------+ +--otherwise
| | * +--string
cpl-+ | * +-------------+ | +-not-present
| | **|string-switch|-+ +-string
| | * +-------------+ +--otherwise
| | * +--time
| +--------------+ +-+--+ * +-----------+ | +-not-present
+-+toplevelaction+-+Node| *|time-switch|-+-+-time
+-----*--------+ +-+--+ +-----------+ +--otherwise
* | +--------+ +----+
* | **|location+-|Node|
* | +--------+ * +--------+ +----+
* +--------+ |-+modifier|** +------+ +-success-Node
**|incoming| | +--------+ *-|lookup+-+-notfound-Node
* +--------+ | * +------+ +-failure-Node
* | +---+ * +---------------+ +----+
* +--------+ +-+Sub+-sub **|remove-location+-+Node|
*|outgoing| | +---+ +---------------+ +----+
+--------+ | +---+
| **|log+-Node
| * +---+
| * +----+
| +------+ **|mail+-Node
+-+action|** +----+ +-busy-Node
---- contains +------+ * +-----+ |
**|proxy+----+-noanswer-Node
**** substitutes * +-----+ |
* +--------+ +-failure-Node
**|redirect| |
* +--------+ +-redirection-Node
* +------+ |
*|reject| +-default-Node
+------+
Figure 31: The structure of the XML schema for CPL ๐ธ
BEGIN
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="urn:ietf:params:xml:ns:cpl"
xmlns="urn:ietf:params:xml:ns:cpl"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="TopLevelActionType" abstract="true">
<xs:group ref="Node"/>
</xs:complexType>
<xs:element name="toplevelaction" type="TopLevelActionType"/>
<xs:complexType name="ActionType" abstract="true"/>
<xs:element name="action" type="ActionType"/>
<xs:complexType name="SwitchType" abstract="true"/>
<xs:element name="switch" type="SwitchType"/>
<xs:complexType name="ModifierType" abstract="true"/>
<xs:element name="modifier" type="ModifierType"/>
<xs:element name="location" type="LocationType"
substitutionGroup="modifier"/>
<xs:element name="lookup" type="LookupType"
substitutionGroup="modifier"/>
<xs:element name="remove-location" type="RemoveLocationType"
substitutionGroup="modifier"/>
<xs:element name="sub" type="SubAction"/>
<xs:group name="Node">
<xs:choice>
<xs:element ref="switch" minOccurs="0" maxOccurs="1"/>
<xs:element ref="modifier" minOccurs="0" maxOccurs="1"/>
<xs:element ref="sub" minOccurs="0" maxOccurs="1"/>
<xs:element ref="action" minOccurs="0" maxOccurs="1"/>
</xs:choice>
</xs:group>
<xs:complexType name="OtherwiseAction">
<xs:group ref="Node"/>
</xs:complexType>
<xs:complexType name="NotPresentAction">
<xs:group ref="Node"/>
</xs:complexType>
<xs:simpleType name="YesNoType">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="yes"/>
<xs:enumeration value="no"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="StatusType">
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="busy"/>
<xs:enumeration value="notfound"/>
<xs:enumeration value="reject"/>
<xs:enumeration value="error"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:union>
</xs:simpleType>
<xs:simpleType name="OrderingType">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="parallel"/>
<xs:enumeration value="sequential"/>
<xs:enumeration value="first-only"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="AddressFieldType">
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="origin"/>
<xs:enumeration value="destination"/>
<xs:enumeration value="original-destination"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:union>
</xs:simpleType>
<xs:simpleType name="AddressSubfieldType">
<xs:union>
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="address-type"/>
<xs:enumeration value="user"/>
<xs:enumeration value="host"/>
<xs:enumeration value="port"/>
<xs:enumeration value="tel"/>
<xs:enumeration value="display"/>
<xs:enumeration value="password"/>
<xs:enumeration value="alias-type"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType>
<xs:restriction base="xs:string"/>
</xs:simpleType>
</xs:union>
</xs:simpleType>
<xs:complexType name="AddressType">
<xs:annotation>
<xs:documentation>Exactly one of the three attributes must
appear</xs:documentation>
</xs:annotation>
<xs:group ref="Node"/>
<xs:attribute name="is" type="xs:string" use="optional"/>
<xs:attribute name="contains" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>for "display" only</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="subdomain-of" type="xs:string"
use="optional">
<xs:annotation>
<xs:documentation>for "host", "tel" only</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:anyAttribute namespace="##any" processContents="lax"/>
</xs:complexType>
<xs:complexType name="AddressSwitchType">
<xs:complexContent>
<xs:extension base="SwitchType">
<xs:sequence>
<xs:element name="address" type="AddressType" minOccurs="0"
maxOccurs="unbounded"/>
<xs:sequence minOccurs="0">
<xs:element name="not-present" type="NotPresentAction"/>
<xs:element name="address" type="AddressType"
minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:element name="otherwise" type="OtherwiseAction"
minOccurs="0"/>
</xs:sequence>
<xs:attribute name="field" type="AddressFieldType"
use="required"/>
<xs:attribute name="subfield" type="AddressSubfieldType"
use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="address-switch" type="AddressSwitchType"
substitutionGroup="switch"/>
<xs:simpleType name="StringFieldType">
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="subject"/>
<xs:enumeration value="organization"/>
<xs:enumeration value="user-agent"/>
<xs:enumeration value="display"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="StringType">
<xs:group ref="Node"/>
<xs:attribute name="is" type="xs:string" use="optional"/>
<xs:attribute name="contains" type="xs:string" use="optional"/>
<xs:anyAttribute namespace="##any" processContents="lax"/>
</xs:complexType>
<xs:complexType name="StringSwitchType">
<xs:complexContent>
<xs:extension base="SwitchType">
<xs:sequence>
<xs:element name="string" type="StringType" minOccurs="0"
maxOccurs="unbounded"/>
<xs:sequence minOccurs="0">
<xs:element name="not-present" type="NotPresentAction"/>
<xs:element name="string" type="StringType" minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
<xs:element name="otherwise" type="OtherwiseAction"
minOccurs="0"/>
</xs:sequence>
<xs:attribute name="field" type="StringFieldType"
use="required">
<xs:annotation>
<xs:documentation>Strings are matched as case-insensitive
Unicode strings.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="string-switch" type="StringSwitchType"
substitutionGroup="switch"/>
<xs:complexType name="LanguageType">
<xs:group ref="Node"/>
<xs:attribute name="matches" type="xs:string" use="required">
<xs:annotation>
<xs:documentation>The value of one of these parameters is a
language-tag, as defined in RFC
3066.</xs:documentation>
</xs:annotation>
</xs:attribute> <xs:anyAttribute namespace="##any" processContents="lax"/> </xs:complexType> <xs:complexType name="LanguageSwitchType"> <xs:complexContent> <xs:extension base="SwitchType"> <xs:sequence> <xs:element name="language" type="LanguageType" minOccurs="0" maxOccurs="unbounded"/> <xs:sequence minOccurs="0"> <xs:element name="not-present" type="NotPresentAction"/> <xs:element name="language" type="LanguageType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:element name="otherwise" type="OtherwiseAction" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="language-switch" type="LanguageSwitchType" substitutionGroup="switch"/> <xs:simpleType name="FreqType"> <xs:restriction base="xs:NMTOKEN"> <xs:pattern value="[s|S][e|E][c|C][o|O][n|N][d|D][l|L][y|Y]"/> <xs:pattern value="[m|M][i|I][n|N][u|U][t|T][e|E][l|L][y|Y]"/> <xs:pattern value="[h|H][o|O][u|U][r|R][l|L][y|Y]"/> <xs:pattern value="[d|D][a|A][i|I][l|L][y|Y]"/> <xs:pattern value="[w|W][e|E][e|E][k|K][l|L][y|Y]"/> <xs:pattern value="[m|M][o|N][n|N][t|T][h|H][l|L][y|Y]"/> <xs:pattern value="[y|Y][e|E][a|A][r|R][l|L][y|Y]"/> </xs:restriction> </xs:simpleType> <xs:simpleType name="YearDayType"> <xs:union> <xs:simpleType> <xs:restriction base="xs:integer"> <xs:minInclusive value="-366"/> <xs:maxInclusive value="-1"/> </xs:restriction> </xs:simpleType> <xs:simpleType> <xs:restriction base="xs:integer"> <xs:minInclusive value="1"/> <xs:maxExclusive value="366"/> </xs:restriction> </xs:simpleType> </xs:union>
</xs:simpleType> <xs:simpleType name="DayType"> <xs:restriction base="xs:NMTOKEN"> <xs:pattern value="[m|M][o|O]"/> <xs:pattern value="[t|T][u|U]"/> <xs:pattern value="[w|W][e|E]"/> <xs:pattern value="[t|T][h|H]"/> <xs:pattern value="[f|F][r|R]"/> <xs:pattern value="[s|S][a|A]"/> <xs:pattern value="[s|S][u|U]"/> </xs:restriction> </xs:simpleType> <xs:complexType name="TimeType"> <xs:annotation> <xs:documentation>Exactly one of the two attributes "dtend" and "duration" must occur. None of the attributes following freq are meaningful unless freq appears. </xs:documentation> </xs:annotation> <xs:group ref="Node"/> <xs:attribute name="dtstart" type="xs:string" use="required"> <xs:annotation> <xs:documentation>RFC 2445 DATE-TIME</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="dtend" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>RFC 2445 DATE-TIME</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="duration" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>RFC 2445 DURATION</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="freq" type="FreqType" use="optional"/> <xs:attribute name="interval" type="xs:positiveInteger" default="1"/> <xs:attribute name="until" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>RFC 2445 DATE-TIME</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="count" type="xs:positiveInteger" use="optional"/> <xs:attribute name="bysecond" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>Comma-separated list of seconds within a
minute. Valid values are 0 to 59.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="byminute" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>Comma-separated list of minutes within an hour. Valid values are 0 to 59.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="byhour" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>Comma-separated list of hours of the day. Valid values are 0 to 23.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="byday" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>Comma-separated list of days of the week. Valid values are "MO", "TU", "WE", "TH", "FR", "SA" and "SU". These values are not case-sensitive. Each can be preceded by a positive (+n) or negative (-n) integer.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="bymonthday" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>Comma-separated list of days of the month. Valid values are 1 to 31 or -31 to -1.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="byyearday" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>Comma-separated list of days of the year. Valid values are 1 to 366 or -366 to -1.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="byweekno" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>Comma-separated list of ordinals specifying weeks of the year. Valid values are 1 to 53 or -53 to -1.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="bymonth" type="xs:string" use="optional"> <xs:annotation> <xs:documentation>Comma-separated list of months of the year.
Valid values are 1 to 12.</xs:documentation> </xs:annotation> </xs:attribute> <xs:attribute name="wkst" type="DayType" default="MO"/> <xs:attribute name="bysetpos" type="YearDayType"/> <xs:anyAttribute namespace="##any" processContents="lax"/> </xs:complexType> <xs:simpleType name="TZIDType"> <xs:restriction base="xs:string"/> </xs:simpleType> <xs:simpleType name="TZURLType"> <xs:restriction base="xs:anyURI"/> </xs:simpleType> <xs:complexType name="TimeSwitchType"> <xs:complexContent> <xs:extension base="SwitchType"> <xs:sequence> <xs:element name="time" type="TimeType" minOccurs="0" maxOccurs="unbounded"/> <xs:sequence minOccurs="0"> <xs:element name="not-present" type="NotPresentAction"/> <xs:element name="time" type="TimeType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:element name="otherwise" type="OtherwiseAction" minOccurs="0"/> </xs:sequence> <xs:attribute name="tzid" type="TZIDType"/> <xs:attribute name="tzurl" type="TZURLType"/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="time-switch" type="TimeSwitchType" substitutionGroup="switch"/> <xs:simpleType name="PriorityValues"> <xs:restriction base="xs:NMTOKEN"> <xs:pattern value="[e|E][m|M][e|E][r|R][g|G][e|E][n|N][c|C][y|Y]"/> <xs:pattern value="[u|U][r|R][g|G][e|E][n|N][t|T]"/> <xs:pattern value="[n|N][o|O][r|R][m|M][a|A][l|L]"/> <xs:pattern value="[n|N][o|O][n|N]-[u|U][r|R][g|G][e|E][n|N][t|T]"/> </xs:restriction> </xs:simpleType> <xs:complexType name="PriorityType"> <xs:annotation> <xs:documentation>Exactly one of the three attributes must appear </xs:documentation>
</xs:annotation> <xs:group ref="Node"/> <xs:attribute name="less" type="PriorityValues"/> <xs:attribute name="greater" type="PriorityValues"/> <xs:attribute name="equal" type="xs:string"> <xs:annotation> <xs:documentation>case-insensitive</xs:documentation> </xs:annotation> </xs:attribute> <xs:anyAttribute namespace="##any" processContents="lax"/> </xs:complexType> <xs:complexType name="PrioritySwitchType"> <xs:complexContent> <xs:extension base="SwitchType"> <xs:sequence> <xs:element name="priority" type="PriorityType" minOccurs="0" maxOccurs="unbounded"/> <xs:sequence minOccurs="0"> <xs:element name="not-present" type="NotPresentAction"/> <xs:element name="priority" type="PriorityType" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> <xs:element name="otherwise" type="OtherwiseAction" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> <xs:element name="priority-switch" type="PrioritySwitchType" substitutionGroup="switch"/> <xs:simpleType name="LocationPriorityType"> <xs:restriction base="xs:float"> <xs:minInclusive value="0.0"/> <xs:maxInclusive value="1.0"/> </xs:restriction> </xs:simpleType> <xs:complexType name="LocationType"> <xs:complexContent> <xs:extension base="ModifierType"> <xs:group ref="Node"/> <xs:attribute name="url" type="xs:anyURI" use="required"/> <xs:attribute name="priority" type="LocationPriorityType" use="optional" default="1.0"/> <xs:attribute name="clear" type="YesNoType" default="no"/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="LookupType">
okay the schema is still going bestie ๐ here's the rest of the CPL XML schema ๐
<xs:complexContent>
<xs:extension base="ModifierType">
<xs:all>
<xs:element name="success" minOccurs="0">
<xs:complexType>
<xs:group ref="Node"/>
</xs:complexType>
</xs:element>
<xs:element name="notfound" minOccurs="0">
<xs:complexType>
<xs:group ref="Node"/>
</xs:complexType>
</xs:element>
<xs:element name="failure" minOccurs="0">
<xs:complexType>
<xs:group ref="Node"/>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="source" type="xs:string"
use="required"/>
<xs:attribute name="timeout" type="xs:positiveInteger"
default="30"/>
<xs:attribute name="clear" type="YesNoType" default="no"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="RemoveLocationType">
<xs:complexContent>
<xs:extension base="ModifierType">
<xs:group ref="Node"/>
<xs:attribute name="location" type="xs:string"
use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="LogAction">
<xs:complexContent>
<xs:extension base="ActionType">
<xs:group ref="Node"/>
<xs:attribute name="name" type="xs:string" use="optional"/>
<xs:attribute name="comment" type="xs:string"
use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="log" type="LogAction"
substitutionGroup="action"/>
<xs:complexType name="IncomingType">
<xs:complexContent>
<xs:extension base="TopLevelActionType"/>
</xs:complexContent>
</xs:complexType>
<xs:element name="incoming" type="IncomingType"
substitutionGroup="toplevelaction"/>
<xs:complexType name="OutgoingType">
<xs:complexContent>
<xs:extension base="TopLevelActionType"/>
</xs:complexContent>
</xs:complexType>
<xs:element name="outgoing" type="OutgoingType"
substitutionGroup="toplevelaction"/>
<xs:complexType name="ProxyAction">
<xs:complexContent>
<xs:extension base="ActionType">
<xs:all>
<xs:element name="busy" minOccurs="0">
<xs:complexType>
<xs:group ref="Node"/>
</xs:complexType>
</xs:element>
<xs:element name="noanswer" minOccurs="0">
<xs:complexType>
<xs:group ref="Node"/>
</xs:complexType>
</xs:element>
<xs:element name="failure" minOccurs="0">
<xs:complexType>
<xs:group ref="Node"/>
</xs:complexType>
</xs:element>
<xs:element name="redirection" minOccurs="0">
<xs:complexType>
<xs:group ref="Node"/>
</xs:complexType>
</xs:element>
<xs:element name="default" minOccurs="0">
<xs:complexType>
<xs:group ref="Node"/>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="timeout" type="xs:positiveInteger"
use="optional" default="20"/>
<xs:attribute name="recurse" type="YesNoType"
use="optional" default="yes"/>
<xs:attribute name="ordering" type="OrderingType"
use="optional" default="parallel"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="proxy" type="ProxyAction"
substitutionGroup="action"/>
<xs:complexType name="RedirectAction">
<xs:complexContent>
<xs:extension base="ActionType">
<xs:attribute name="permanent" type="YesNoType"
default="no"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="redirect" type="RedirectAction"
substitutionGroup="action"/>
<xs:complexType name="RejectAction">
<xs:complexContent>
<xs:extension base="ActionType">
<xs:attribute name="status" type="StatusType"
use="required"/>
<xs:attribute name="reason" type="xs:string"
use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="reject" type="RejectAction"
substitutionGroup="action"/>
<xs:complexType name="MailAction">
<xs:complexContent>
<xs:extension base="ActionType">
<xs:group ref="Node"/>
<xs:attribute name="url" type="xs:anyURI" use="required"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="mail" type="MailAction"
substitutionGroup="action"/>
<xs:complexType name="SubAction">
<xs:attribute name="ref" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="AncillaryType"/>
<xs:complexType name="SubactionType">
<xs:group ref="Node"/>
<xs:attribute name="id" use="required"/>
</xs:complexType>
<xs:complexType name="CPLType">
<xs:sequence>
<xs:element name="ancillary" type="AncillaryType" minOccurs="0"
maxOccurs="1"/>
<xs:element name="subaction" type="SubactionType" minOccurs="0"
maxOccurs="unbounded"/>
<xs:element ref="toplevelaction" minOccurs="0"
maxOccurs="unbounded">
<xs:annotation>
<xs:documentation>Any toplevel action MUST NOT appear more
than once.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:element name="cpl" type="CPLType"/>
</xs:schema>
END
Normative References ๐โจ
- [1] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, June 2002.
- [2] Bray, T., Paoli, J., Sperberg-McQueen, C. M., Maler, E., and F. Yergeau, "Extensible Markup Language (XML) 1.0 (Third Edition)", W3C Recommendation REC-xml-20040204, World Wide Web Consortium (W3C), February 2004. Available at
http://www.w3.org/XML/. - [3] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
- [4] Hinden, R. and S. Deering, "Internet Protocol Version 6 (IPv6) Addressing Architecture", RFC 3513, April 2003.
- [5] Davis, M. F. and M. Duerst, "Unicode Normalization Forms", Unicode Standard Annex #15, Unicode Consortium, April 2003. Revision 23; part of Unicode 4.0.0. Available at
http://www.unicode.org/unicode/reports/tr15/. - [6] Davis, M. F., "Case Mappings", Unicode Standard Annex #21, Unicode Consortium, March 2001. Revision 5; part of Unicode 3.2.0. Available at
http://www.unicode.org/unicode/reports/tr21/. - [7] Alvestrand, H., "Tags for the Identification of Languages", BCP 47, RFC 3066, January 2001.
- [8] Dawson, F. and D. Stenerson, "Internet Calendaring and Scheduling Core Object Specification (iCalendar)", RFC 2445, November 1998.
- [9] Eggert, P., "Sources for Time Zone and Daylight Saving Time Data". Available at
http://www.twinsun.com/tz/tz-link.htm. - [10] Mealling, M. and R. Daniel, "URI Resolution Services Necessary for URN Resolution", RFC 2483, January 1999.
- [11] Bray, T., Hollander, D., and A. Layman, "Namespaces in XML", W3C Recommendation REC-xml-names-19990114, World Wide Web Consortium (W3C), January 1999. Available at
http://www.w3.org/TR/REC-xml-names/. - [12] Moats, R., "URN Syntax", RFC 2141, May 1997.
- [13] Moats, R., "A URN Namespace for IETF Documents", RFC 2648, August 1999.
- [14] Mealling, M., "The IETF XML Registry", BCP 81, RFC 3688, January 2004.
- [15] Murata, M., St.Laurent, S., and D. Kohn, "XML Media Types", RFC 3023, January 2001.
Informative References ๐ฆ
- [16] International Telecommunication Union, "Packet-based multimedia communication systems", Recommendation H.323, Telecommunication Standardization Sector of ITU, Geneva, Switzerland, July 2003.
- [17] Lennox, J. and H. Schulzrinne, "Call Processing Language Framework and Requirements", RFC 2824, May 2000.
- [18] Raggett, D., Le Hors, A., and I. Jacobs, "HTML 4.01 Specification", W3C Recommendation REC-html401-19991224, World Wide Web Consortium (W3C), December 1999. Available at
http://www.w3.org/TR/html4/. - [19] ISO (International Organization for Standardization), "Information processing -- Text and office systems -- Standard Generalized Markup Language (SGML)", ISO Standard ISO 8879:1986(E), International Organization for Standardization, Geneva, Switzerland, October 1986.
- [20] ISO (International Organization for Standardization), "Data elements and interchange formats -- Information interchange -- Representation of dates and times", ISO Standard ISO 8601:2000(E), International Organization for Standardization, Geneva, Switzerland, December 2000.
- [21] DeRose, S., Maler, E., Orchard, D., and B. Trafford, "XML Linking Language (XLink) Version 1.0", W3C Recommendation REC-xlink-20010627, World Wide Web Consortium (W3C), June 2001. Available at
http://www.w3.org/TR/xlink/. - [22] Showalter, T., "Sieve: A Mail Filtering Language", RFC 3028, January 2001.
- [23] International Telecommunication Union, "Digital Subscriber Signalling System No. 1 (DSS 1) - ISDN user-network interface layer 3 specification for basic call control", Recommendation Q.931, International Telecommunication Union, Geneva, Switzerland, March 1993.
- [24] Levin, O., "H.323 Uniform Resource Locator (URL) Scheme Registration", RFC 3508, April 2003.
Authors' Addresses ๐ธ
Jonathan Lennox Dept. of Computer Science Columbia University 1214 Amsterdam Avenue, MC 0401 New York, NY 10027 USA
EMail: lennox@cs.columbia.edu
Xiaotao Wu Dept. of Computer Science Columbia University 1214 Amsterdam Avenue, MC 0401 New York, NY 10027 USA
EMail: xiaotaow@cs.columbia.edu
Henning Schulzrinne Dept. of Computer Science Columbia University 1214 Amsterdam Avenue, MC 0401 New York, NY 10027 USA
EMail: schulzrinne@cs.columbia.edu
Full Copyright Statement ๐ฅ
Copyright (C) The Internet Society (2004).
This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.
This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Intellectual Property โจ
okay so the IETF is NOT picking a side on whether any patents or other rights apply to the tech in this doc ๐ โโ๏ธ it doesn't say whether you can get a license for it either, and it hasn't gone hunting for rights holders on its own. if you want the IETF's rules on rights in its documents, check out BCP 78 and BCP 79 ๐
if you're an implementer or user and you want to see IPR disclosures that were sent to the IETF Secretariat, or any promises of licenses, or what happened when someone tried to get a general license or permission to use the proprietary stuff, it's all in the IETF's online IPR repository at http://www.ietf.org/ipr ๐๏ธ๐
and the IETF is literally asking everyone ๐ซถ if you know about any copyrights, patents, patent applications, or other proprietary rights that might cover tech you'd need to implement this standard, please tell them! send it to ietf-ipr@ietf.org ๐ฌโจ
Acknowledgement
the RFC Editor function is currently funded by the Internet Society ๐ธ shoutout to them, they keep the lights on for the RFC Editor! ๐
๐ฆ where this page comes from
- ietf: rfc3880 2004-11
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms