RFC 3880

Call Processing Language (CPL): A Language for User Control of Internet Telephony Services

๐Ÿ“… published November 2004, from ietf

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 (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. so subdomain-of="example.com" would match example.com, research.example.com, and zaphod.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, so subdomain-of="1212555" would match the telephone number 1 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 count parameter can't be checked in constant running time, because the server has to enumerate every recurrence from dtstart up to the present to see whether the current recurrence satisfies it. However, a server can expand a count parameter once, off-line, to find the date of the last recurrence. That date can then be treated as a virtual until parameter for the server's internal processing ๐Ÿ“†.
  • Similarly, the bysetpos parameter 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 a bysetpos parameter 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 &amp; 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 ๐Ÿ’…

  1. 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 ๐Ÿ’Œ
  2. The "From" field of the email is set to a CPL server configured address, overriding any "From" field in the "mailto" URI ๐Ÿซถ
  3. 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.) ๐Ÿงš
  4. 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 ๐Ÿซถ

  1. Work out the time of the call, in the timezone of the time switch ๐ŸŒ
  2. If the call time is earlier than dtstart, fail NOMATCH. ๐Ÿ™…โ€โ™€๏ธ
  3. If the call time is less than duration after dtstart, succeed MATCH. ๐ŸŽ‰
  4. Find the smallest unit named in a byxxx rule or by freq. 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 matches dtstart. 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 match dtstart. For every other Minimum Unit, the time-of-day has to match dtstart. If the Minimum Unit is a week, the day-of-the-week has to match dtstart. If it's a month, the day-of-the-month has to match dtstart. If it's a year, the month and day-of-month both have to match dtstart. ๐Ÿ—“๏ธ

(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. ๐ŸŽ€

  1. If the time between the Candidate Start Time and the call time is more than the duration, fail NOMATCH. ๐Ÿšซ
  2. If the Candidate Start Time is later than the until parameter of the recurrence (or the virtual until computed off-line from count), fail NOMATCH. ๐Ÿ™…
  3. Call the unit of the freq parameter the Frequency Unit. Figure out the frequency unit enclosing the Candidate Start Time, and the one enclosing dtstart. Count how many frequency units have passed between those two. If that number isn't a multiple of the interval parameter, fail NOMATCH. ๐Ÿ”ข
  4. For every byxxx rule, check that the Candidate Start Time matches one of the options that rule lists. If it does, succeed MATCH. ๐Ÿฅณ
  5. 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

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