1
0
mirror of https://github.com/moparisthebest/xeps synced 2024-10-31 15:35:07 -04:00
xeps/xep-0327.xml

4451 lines
197 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
<header>
<title>Rayo</title>
<abstract>This specification defines an XMPP protocol extension for the third-party control of telephone calls and other similar media sessions. The protocol includes support for session management/signaling, as well as advanced media resources such as speech recognizers, speech synthesizers and audio/video recorders. The protocol serves a different purpose from that of first-party protocols such as Jingle or SIP, and is compatible with those protocols.</abstract>
&LEGALNOTICE;
<number>0327</number>
<status>Deferred</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
<author>
<firstname>Ben</firstname>
<surname>Langfeld</surname>
<email>ben@langfeld.me</email>
<jid>ben@langfeld.me</jid>
<uri>http://langfeld.me</uri>
</author>
<author>
<firstname>Jose</firstname>
<surname>de Castro</surname>
<email>jdecastro@tropo.com</email>
<jid>jdecastro@tropo.com</jid>
<uri>http://tropo.com</uri>
</author>
<revision>
<version>0.8.1</version>
<date>2018-11-03</date>
<initials>pep</initials>
<remark>Fix a bunch of typos, batch-style.</remark>
</revision>
<revision>
<version>0.8</version>
<date>2017-09-11</date>
<initials>XEP Editor (jwi)</initials>
<remark>Defer due to lack of activity.</remark>
</revision>
<revision>
<version>0.7</version>
<date>2015-07-15</date>
<initials>bl</initials>
<remark><p>Updates based on XMPP Council feedback.</p></remark>
</revision>
<revision>
<version>0.6</version>
<date>2015-04-29</date>
<initials>bl</initials>
<remark><p>Changes to address Last Call feedback.</p></remark>
</revision>
<revision>
<version>0.5</version>
<date>2014-09-23</date>
<initials>bl</initials>
<remark><p>Add an extra recognition timeout to the Input component.</p></remark>
</revision>
<revision>
<version>0.4</version>
<date>2014-03-13</date>
<initials>bl</initials>
<remark><p>Suggest timestamping Rayo events; allow specifying a call URI when dialing.</p></remark>
</revision>
<revision>
<version>0.3</version>
<date>2014-01-30</date>
<initials>bl</initials>
<remark><p>Further updates.</p></remark>
</revision>
<revision>
<version>0.2</version>
<date>2013-06-10</date>
<initials>bl</initials>
<remark><p>Updates to address open issues.</p></remark>
</revision>
<revision>
<version>0.1</version>
<date>2013-05-06</date>
<initials>psa</initials>
<remark><p>Initial published version approved by the XMPP Council.</p></remark>
</revision>
<revision>
<version>0.0.1</version>
<date>2013-04-05</date>
<initials>bl</initials>
<remark><p>First draft.</p></remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>Rayo is a protocol to allow third-party remote control over media sessions, audio/video mixers and a variety of advanced media resources such as speech recognizers, speech synthesizers and audio/video recorders. These capabilities can be combined to create a wide variety of applications such as menu-based phone systems, in-game conferencing and anonymous dating services. Unlike &xep0166; or even SIP (&rfc3261;), a Rayo client is not concerned with being a party to either the session negotiation or the media stream itself.</p>
<ul>
<li>A Rayo server takes on the role of negotiating a media session between itself and some other endpoint, or between two external endpoints, by way of an implementation-specific means, be that Jingle, SIP, the public-switched telephone network, or anything else. The server may even bridge multiple networks.</li>
<li>The server then presents the Rayo protocol as an interface to a Rayo client, allowing it to monitor and/or exercise third-party control over the established media sessions.</li>
<li>The client has the option to accept/reject/answer inbound session requests, request the creation of outbound sessions and monitor their progress, execute media operations such as speech synthesis, speech recognition &amp; recording, and to end sessions.</li>
</ul>
<p>The relationship between the calling parties, the Rayo server and the Rayo client looks something like this:</p>
<code>
[caller] ----e.g. SIP---- [rayo server] ( -----e.g. Jingle---- [callee] ) optional
|
|
rayo client
</code>
<p>This document defines the core Rayo protocol, and contains provisions for its extension by further specifications.</p>
</section1>
<section1 topic='How it works' anchor='howitworks'>
<p>In order to understand the nature of a Rayo interaction, here we show a simple example of a control session.</p>
<example caption="New call announces itself to a potential controlling party"><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:call:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
<offer xmlns='urn:xmpp:rayo:1'
to='tel:+18003211212'
from='tel:+13058881212'/>
</presence>
]]></example>
<p>In this example, a call from 'tel:+13058881212' has reached the Rayo server 'shakespeare.lit' by calling 'tel:+18003211212', and been assigned an ID '9f00061'. The server has determined that 'juliet@capulet.lit' is a valid candidate to be the client to whom the server delegates control of the call, and so has directed an <link url='#def-offer'>offer event</link> to her 'balcony' resource.</p>
<p>The client, 'juliet@capulet.lit', then decides that it is able to handle the incoming call, and so accepts it from the server, thus gaining exclusive control and indicating to the calling party that the call will be processed and that it should ring.</p>
<example caption="Potential controlling party attempts to become definitive controlling party by sending the call an accept command"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='hd721'>
<accept xmlns='urn:xmpp:rayo:1'/>
</iq>
]]></example>
<example caption="Call acknowledges accept command to the (now) definitive controlling party"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='hd721'/>
]]></example>
<p>Following confirmation from the server that the attempt to gain control of the call was successful, the client proceeds to answer the call, opening up the media stream between the caller and the server.</p>
<example caption="Controlling party answers the call"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='43jo3'>
<answer xmlns='urn:xmpp:rayo:1'/>
</iq>
]]></example>
<example caption="Call acknowledges answer command to controlling party"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='43jo3'/>
]]></example>
<p>Once the client has confirmation that the call has been answered, it triggers the start of a media output component in order to play a message to the caller using a Text-to-speech (TTS) engine.</p>
<example caption="Controlling party requests a new output component"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='j9d3j'>
<output xmlns='urn:xmpp:rayo:output:1'
voice='allison'>
<document content-type="text/plain">
<![CDATA[
You have no new messages. Goodbye!
]]]]><![CDATA[>
</document>
</output>
</iq>
]]></example>
<example caption="Call acknowledges request for new output component and provides its ID"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='j9d3j'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:9f00061@call.shakespeare.lit/fgh4590'/>
</iq>
]]></example>
<p>After confirmation that the output component was successfully created, the client then awaits notification of its completion.</p>
<example caption="Output component announces its completion, giving the reason"><![CDATA[
<presence from='9f00061@call.shakespeare.lit/fgh4590'
to='juliet@capulet.lit/balcony'
type='unavailable'>
<complete xmlns='urn:xmpp:rayo:ext:1'>
<finish xmlns='urn:xmpp:rayo:output:complete:1' />
</complete>
</presence>
]]></example>
<p>The client then decides it has no further operations to perform on the call, and that the call should end. It instructs the server to hang up the call gracefully.</p>
<example caption="Controlling party hangs up the call"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='f3wh8'>
<hangup xmlns='urn:xmpp:rayo:1'/>
</iq>
]]></example>
<example caption="Call acknowledges hangup command to controlling party"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='f3wh8'/>
]]></example>
<example caption="Controlling party receives notification of the call being terminated"><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='unavailable'>
<end xmlns='urn:xmpp:rayo:1'>
<hangup-command/>
</end>
</presence>
]]></example>
</section1>
<section1 topic='Requirements' anchor='reqs'>
<p>The protocol defined herein is designed to provide the following features:</p>
<ol>
<li><strong>Call Control:</strong> Incoming calls are "offered" to clients at which point they can be answered, rejected, redirected to another destination, etc. Outbound calls may also be made and monitored. Every attempt is made to be shield the Rayo client from the low level telephony protocol (e.g. SIP, Jingle, PSTN, etc).</li>
<li><strong>Audio File Playback:</strong> A compatible Rayo server will fetch a file from a a specified URL and play the containing audio to the caller.</li>
<li><strong>Speech Synthesis / TTS:</strong> In cases where dynamic data must be spoken, a Speech Synthesis engine may be used to play computer generated speech to the caller.</li>
<li><strong>Touch-tone Events / DTMF:</strong> Rayo surfaces real-time event when the caller presses keys on their touch-tone keypad.</li>
<li><strong>Speech Recognition:</strong> Enables the phone application to take spoken queues allowing for sophisticated voice-driven menus and directory services.</li>
<li><strong>Call Recording:</strong> Can be used to capture the caller's voice (e.g. Voicemail) or both sides of the call for auditing and compliance purposes.</li>
<li><strong>Mixing:</strong> Typically referred to as an audio "conference"; calls can be joined together so that the participants can hear each other in real-time.</li>
</ol>
<p>Many third-party call control protocols have preceeded Rayo (see Asterisk's AGI/AMI, FreeSWITCH's eventsocket, Microsoft's TAPI, Java's JTAPI, Novell/AT&amp;T's TSAPI, CSTA, etc). None of these protocols is ideal, and all have one or more of the following drawbacks:</p>
<ul>
<li><strong>Totally ground-up wire protocol</strong> requiring implementation all the way down to the socket.</li>
<li><strong>Platform/vendor/hardware specific</strong> - each system implements its own proprietary protocol (in many cases, without a formal published specification) which does not allow easily porting an application from one back-end to another.</li>
<li><strong>Synchronous interface</strong> - Operations on calls or other entities are often blocking, and one must serialise all control messages.</li>
<li><strong>Inconsistent</strong> - evolved, rather than designed.</li>
<li><strong>Lacking in scalability</strong> - client/server sometimes tied one-to-one, servers rarely clustered, advanced message routing not possible.</li>
<li><strong>Poor security</strong> - lack of wire-level encryption, lack of or sub-standard authentication mechanisms, lack of or limited authorization mechanisms, lack of or poor sandboxing between multiple tenants on one system.</li>
<li><strong>Inextensible</strong> - The specification of extensions to the core protocol is either impossible or very difficult.</li>
</ul>
<p>Rayo has been designed with these failings in mind, and intends to address many concerns not addressed by these earlier attempts. The following considerations were made:</p>
<ul>
<li><strong>Simple client library implementation</strong> - XMPP client libraries exist in all modern languages, and many are of a high standard of quality and maturity.</li>
<li><strong>Cross-platform standard</strong> - The protocol must not expose any platform specifics and all elements should be candidates for implementation on any suitable platform. Addiditionally, the protocol must be ratified as a standard following a community discussion.</li>
<li><strong>Asynchronous interface</strong> - The protocol should present an asynchronous interface for the purposes of performance and flexibility in performing parallel operations.</li>
<li><strong>Consistent</strong> - The protocol must provide a considered, unobtrusive, logically and philisophically consistent interface.</li>
<li><strong>Federated</strong> - The protocol must support communication between client and server entities on separately owned, operated and addressed networks.</li>
<li><strong>Flexible routing</strong> - The protocol must lend itself to routing across wide networks such as the internet, and to potential complex routing such as proxying or redirection. Additionally, the client and server should each be aware of the presence of the other and be able to use such information to make routing decisions.</li>
<li><strong>Extensible</strong> - The protocol must provide for the possibility of extra functionality being added by future specifications or an individual implementation.</li>
<li><strong>Secure</strong> - The protocol should include appropriate measures for authentication and authorization of participants, as well as preventing third-parties from intercepting control messages.</li>
</ul>
<p>Many of the features in the above list are available to Rayo at no specification or implementation cost, since they are core to XMPP itself and thus Rayo inherits these 'for free'.</p>
<p>Additionally, the protocol is required to abstract away the complexity of the back-end negotiation, especially the details of the transport protocols such as SIP or Jingle, but to map conceptually to such protocols.</p>
</section1>
<section1 topic='Terminology' anchor='terms'>
<section2 topic='Glossary' anchor='terms-glossary'>
<dl>
<di>
<dt>Third-party call control (3PCC)</dt>
<dd>The observation and/or control of a live media session by an entity which is not a direct party to the session.</dd>
</di>
<di>
<dt>Command</dt>
<dd>Commands instruct the receiving entity to perform some atomic action. Commands may be executed against a given call, component or mixer and can be considered completed as soon as they receive a response. Some commands create components, and return a reference to the component in their response.</dd>
</di>
<di>
<dt>Component</dt>
<dd>Components extend the Rayo protocol by providing additional media and call control functionality. Components are created by an appropriate command, which returns a reference to the component. Components are executed asynchronously, and have a lifecycle attached to them, with the ability to trigger events or have commands issued to it. Once a component is stopped or comes to an end naturally, it will issue a special &lt;complete/&gt; event, indicating that it has ceased executing and deliver any required data.</dd>
</di>
<di>
<dt>Potential controlling party (PCP)</dt>
<dd>An XMPP entity to which an offer to control an incoming call may be sent.</dd>
</di>
<di>
<dt>Definitive controlling party (DCP)</dt>
<dd>The XMPP entity which gains a lock on control of a session, either by requesting the session's creation, or being the first respondent to an offer.</dd>
</di>
<di>
<dt>Security Zone</dt>
<dd>A security zone is the conceptual border around a call which defines which parties may interact with the call's media or signaling. A security zone MUST contain the rayo server's internal implementation, the media server to which the call is joined, the DCP, and any JID whose bare form is the same as the DCP. A server MAY relax this definition further, for example to consider all JIDs at the same domain to be in the same security zone.</dd>
</di>
</dl>
</section2>
<section2 topic='Conventions' anchor='terms-conventions'>
<p>In examples, the following JIDs are used:</p>
<ul>
<li><strong>juliet@capulet.lit/balcony, romeo@montague.lit/orchard</strong> - Potential controlling parties</li>
<li><strong>shakespeare.lit</strong> - The root domain of the Rayo service</li>
</ul>
</section2>
</section1>
<section1 topic='Concepts and Approach' anchor='concepts'>
<p>A complete Rayo deployment has several elements and interacting entities which must be understood.</p>
<section2 topic='Actors' anchor='concepts-actors'>
<section3 topic='Server' anchor='concepts-actors-server'>
<p>A Rayo server is an entity which is capable of receiving and initiating calls and being party to their media stream, while exposing a Rayo interface to a client in order to permit control over its calls. The Rayo server may handle calls in any way supported by the implementation, such as SIP, Jingle, etc, and should expose a full XMPP domain at the root level of the service deployment (eg shakespeare.lit).</p>
<p>The Rayo server is responsible for keeping track of valid clients, routing calls to the correct potential controlling parties, performing authorization measures on received stanzas, etc.</p>
<p>For the purposes of this specification, complex server-side deployments such as clusters, proxies, gateways, protocol translators, etc are not considered. Further details of such concepts may be found in their (present or future) relevant specifications.</p>
</section3>
<section3 topic='Client(s)' anchor='concepts-actors-client'>
<p>A Rayo client is an entity which implements the Rayo protocol for the purpose of asserting control over calls made available by a Rayo server. The method by which such control measures are determined is outside the scope of this document, but may be the result of human interaction or some automated decision-making process.</p>
<p>A Rayo client is responsible for indicating its availability to a Rayo server and responding to offer messages appropriately.</p>
</section3>
<section3 topic='Calls' anchor='concepts-actors-calls'>
<p>A Rayo call is a short-lived XMPP entity within the scope of the deployment's root domain, perhaps at a sub-domain, with the purpose of representing a single session. It is usually a simple alias for the main server process.</p>
<p>A Rayo call is the entity with which most client interactions are made, and is responsible for sending its events to and receiving commands from a client. Calls may host components.</p>
<p>Calls have separate presence from the root domain of the service and thus appear to be separate entities.</p>
</section3>
<section3 topic='Mixers' anchor='concepts-actors-mixers'>
<p>A Rayo mixer is an XMPP entity within the scope of the deployment's root domain, perhaps at a sub-domain, with the purpose of representing a service for the linking of media streams from several calls. It is usually a simple alias for the main server process.</p>
<p>A Rayo mixer is responsible for sending its events to and receiving commands from one or more clients, and can host components.</p>
<p>Mixers have separate presence from the root domain of the service and its calls and thus appear to be separate entities.</p>
</section3>
<section3 topic='Commands' anchor='concepts-actors-commands'>
<p>A Rayo command is a simple combination of request and response and may be issued directly to the service domain, a call, a mixer or a component attached to any of the former. Commands are executed serially and are generally very short-lived.</p>
</section3>
<section3 topic='Components' anchor='concepts-actors-components'>
<p>Components extend the Rayo protocol by providing additional media and call control functionality.</p>
<p>Components have a lifecycle and are started by sending a specialized command to a call or mixer. Thus, a request for creation of a component will return a reference to the component's ID, and the component will continue to execute until it completes, potentially sending events and processing commands along the way (such as an instruction to pause or terminate), before finally issuing an event indicating its completion and thus unavailability. Multiple components may be active on a call or mixer at any one time, and commands may be executed on any entity during the execution of a component.</p>
</section3>
<section3 topic='Remote Party' anchor='concepts-actors-remote-party'>
<p>A call's Remote Party is the software or device with which the Call's signalling (and optionally media) connection is established. This might be a software or hardware phone, a PBX, a gateway or some other such system.</p>
</section3>
</section2>
<section2 topic="Addressing Scheme" anchor='addressing'>
<p>All of the actors described in the previous section (with the exception of commands) are represented by XMPP entities with a JID of their own. Thus, a scheme for determining the JIDs of each of these entities is required. The following is the required naming scheme for Rayo deployments, where elements in square brackets are optional.</p>
<table>
<tr>
<th>Actor</th>
<th>JID format</th>
<th>Example JID</th>
</tr>
<tr>
<td>Server</td>
<td>[service domain]</td>
<td>shakespeare.lit</td>
</tr>
<tr>
<td>Client</td>
<td>any JID</td>
<td>juliet@capulet.lit/balcony</td>
</tr>
<tr>
<td>Call</td>
<td>&lt;call ID&gt;@[&lt;call sub-domain&gt;.]&lt;service domain&gt;</td>
<td>f88eh2@call.shakespeare.lit</td>
</tr>
<tr>
<td>Mixer</td>
<td>&lt;mixer name&gt;@[&lt;mixer sub-domain&gt;.]&lt;service domain&gt;</td>
<td>conf1@mixer.shakespeare.lit</td>
</tr>
<tr>
<td>Call Component</td>
<td>&lt;call ID&gt;@[&lt;call sub-domain&gt;.]&lt;service domain&gt;/&lt;component ID&gt;</td>
<td>f88eh2@call.shakespeare.lit/8f83jf</td>
</tr>
<tr>
<td>Mixer Component</td>
<td>&lt;mixer name&gt;@[&lt;mixer sub-domain&gt;.]&lt;service domain&gt;/&lt;component ID&gt;</td>
<td>conf1@mixer.shakespeare.lit/932eu</td>
</tr>
<tr>
<td>Server Component</td>
<td>&lt;service domain&gt;/&lt;component ID&gt;</td>
<td>shakespeare.lit/f3fg4</td>
</tr>
</table>
<p>Commands should be addressed to the entity on which they should be enacted. Individual commands only apply to certain object (for example instructing a component to hangup will return an error). In general, commands may be sent from a client to the service, a call, a mixer or a component. Events may be sent from a call, a mixer or a component to a client.</p>
</section2>
<section2 topic='Delivery Mechanism' anchor='concepts-delivery'>
<p>Rayo defines several events and commands which may be executed on one of the above actors. These payloads must be sent within an XMPP primitive element, and the rules are as such:</p>
<ul>
<li><strong>Events:</strong> Sent as directed presence from the entity producing the event to a client. Rayo servers SHOULD timestamp all events using &xep0203; in order to allow clients to reliably use Rayo events for billing purposes.</li>
<li><strong>Commands:</strong> Sent as an &lt;iq/&gt; with the 'type' attribute 'set' from the client to the entity to be acted on. Responses returned as an &lt;iq/&gt; with the 'type' attribute either 'result' or 'error'.</li>
</ul>
</section2>
</section1>
<section1 topic='Session Flow' anchor='session'>
<p>This section describes the form, function and order of Rayo stanzas sent across the wire, and the circumstances in which they apply and/or may arise.</p>
<section2 topic='Client Registration' anchor='session-registration'>
<p>In order for a Rayo client to be considered a potential controlling party for incoming sessions, it MUST first notify the Rayo server that it is available for the receipt of calls. This is done by sending directed presence to the Rayo server with a &lt;show/&gt; element containing 'chat' as in the example:</p>
<example caption="Client presents itself as available to the Rayo server"><![CDATA[
<presence from='juliet@capulet.lit/balcony'
to='shakespeare.lit'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:client:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
<show>chat</show>
</presence>
]]></example>
<p>Conversely, when a Rayo client wishes not to be considered a potential controlling party, it SHOULD send directed presence to the Rayo server with a &lt;show/&gt; element containing 'dnd' as in the example:</p>
<example caption="Client presents itself as unavailable to the Rayo server"><![CDATA[
<presence from='juliet@capulet.lit/balcony'
to='shakespeare.lit'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:client:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
<show>dnd</show>
</presence>
]]></example>
</section2>
<section2 topic='Session Establishment' anchor='session-establishment'>
<p>Sessions may be established either at the request of the Rayo client (an outbound call) or as a result of a 3rd party request (an inbound call). Each scenario differs in the Rayo protocol only up to the point at which the session is established and media begins to flow. First we shall examine the sequence of stanzas passed between server and client in each of these scenarios.</p>
<section3 topic='Outbound Call' anchor='session-establishment-outbound'>
<p>In order for a client to establish a new outbound call, it MUST first send a <link url="#def-dial">dial command</link> to the server, indicating the proposed target for the call, its apparent source, and any metadata to send to the target as headers.</p>
<example caption="Client requests establishment of a new outbound session"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='shakespeare.lit'
type='set'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
</iq>
]]></example>
<p>On successfully receiving and parsing the dial command, the server SHOULD perform its own proprietary authorization measures to ensure that only desirable outbound sessions are created. If it is established that the command should not be allowed, the server MUST return an error giving an authorization reason.</p>
<p>If a 'uri' attribute is set on the dial command, the server MUST attempt to create the call at the requested URI. This allows clients to know the URI of the call prior to it coming into existence, for clients where this distinction might be important. Such a URI MUST be a valid Rayo call address.</p>
<p>The specified metadata in the form of the 'from' attribute and any &lt;header/&gt; elements SHOULD be mapped to the underlying signalling protocol for communication to the remote party.</p>
<section4 topic='Errors' anchor='session-establishment-outbound-errors'>
<p>There are several reasons why the server might immediately return an error instead of acknowledging the creation of a new call:</p>
<ul>
<li>The client is unknown to the server and the server does not permit session creation by unknown clients.</li>
<li>The client is not authorized to create this new session.</li>
<li>The server does not support outbound calls.</li>
<li>The server does not have sufficient resources to create a new session.</li>
<li>The dial command was malformed.</li>
<li>The requested URI conflicts with an existing call.</li>
</ul>
<p>If the client is unknown to the server and the server does not permit session creation by unknown clients, the server MUST return a &lt;registration-required/&gt; error with a type of 'auth'.</p>
<example caption="Server indicates client is unknown and the server does not permit session creation by unknown clients"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='auth'>
<registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the client is not authorized (as determined by an implementation/deployment-specific algorithm) to create a new outbound session given the parameters provided, the server MUST return a &lt;not-authorized/&gt; error with a type of 'auth'.</p>
<example caption="Server indicates client is not authorized to create a new outbound session given the parameters provided"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='auth'>
<not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server does not support outbound calls, the server MUST return a &lt;feature-not-implemented/&gt; error with a type of 'cancel'.</p>
<example caption="Server indicates that it does not support outbound calls"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server does not have sufficient resources to create a new session, the server MUST return a &lt;resource-constraint/&gt; error with a type of 'wait'.</p>
<example caption="Server indicates that it does not have sufficient resources to create a new session"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='wait'>
<resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the dial command was malformed, the server MUST return a &lt;bad-request/&gt; error with a type of 'modify'.</p>
<example caption="Server indicates the dial command was malformed"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='foo:bar'
from='tel:+14152226789'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the requested URI conflicts with an existing call, the server MUST return a &lt;conflict/&gt; error with a type of 'modify'.</p>
<example caption="Server indicates the requested URI conflicts with an existing call"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='foo:bar'
from='tel:+14152226789'
uri='xmpp:somecall@capulet.lit'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</dial>
<error type='modify'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
<p>If the command is successful and the call is queued, however, confirmation of such should be sent to the client, including a reference to the unique ID of the call. This call ID may be used to execute commands and filter events for the duration of the session.</p>
<example caption="Confirmation of successful dial request and call ID"><![CDATA[
<iq from='shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:9f00061@call.shakespeare.lit'/>
</iq>
]]></example>
<p>Once the server receives notification that the session has been accepted by the remote party, it should send a ringing event to the client to indicate such:</p>
<example caption="Call announces its ringing state (accepted by 3rd party but not yet answered)."><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<ringing xmlns='urn:xmpp:rayo:1'/>
</presence>
]]></example>
<p>Similarly, once the server receives notification that the session has been answered, it should negotiate media between the remote party and its local media server. Once media negotiation is complete, it should send an answered event to the client to indicate such:</p>
<example caption="Call announces its answered state (media connected)."><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<answered xmlns='urn:xmpp:rayo:1'/>
</presence>
]]></example>
<section4 topic='Nested join' anchor='session-establishment-outbound-nested-join'>
<p>When sending a dial request, a client MAY specify a join target within the dial element:</p>
<example caption="Client requests establishment of a new outbound session, with a nested join"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='shakespeare.lit'
type='set'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<join call-uri='xmpp:e8u398d902i90@call.shakespeare.lit' />
</dial>
</iq>
]]></example>
<p>In this case, the server MUST negotiate media as specified by the join element, in accordance with the rules defined in <link url='#session-joining'>joining calls</link>. Media MUST NOT be negotiated with the local media server, unless the join specifies so. The join operation MUST behave as described in <link url='#session-joining'>joining calls</link>.</p>
</section4>
</section3>
<section3 topic='Inbound Call' anchor='session-establishment-inbound'>
<p>When the Server receives a call from one of its connected networks, it MUST then expose that requested session to Rayo clients. It SHOULD use an implementation-specific routing mechanism to map incoming calls to some set of registered JIDs which are considered appropriate controlling parties. From this set, it SHOULD then remove any parties whom it can identify as being temporarily inappropriate for control (either unavailable based on presence, under too much load, or any other metric which the server has available). If, as a result, the set of Potentially Controlling Parties is empty, the server MUST reject the call indicating that the requested service was unavailable.</p>
<p>If the server can identify active Potential Controlling Parties, it MUST offer them control of the call according to its particular distribution method, which MAY be simultaneous or staged. The server must broadcast an offer on behalf of the call to all Potential Controlling Parties, using applicable to/from/header data from the incoming session. The server MUST also include entity capabilities information in the presence stanza containing the offer, in order to advertise the fact that the entity is a call, qualified by the node name "urn:xmpp:rayo:call:1".</p>
<example caption="New call announces itself to a potential controlling party"><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:call:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
<offer xmlns='urn:xmpp:rayo:1'
to='tel:+18003211212'
from='tel:+13058881212'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</offer>
</presence>
]]></example>
<p>Once the server has offered control, it MUST wait for a response from a PCP or for the remote party to end the call. The server SHOULD monitor the availability of PCPs to whom offers have been sent. If they all cease to be PCPs (eg by going offline) then the call should be rejected in the same way as if there had not been any available PCPs to begin with.</p>
<p>If an offered PCP executes a command against the call, by sending a command node to the call's JID inside an IQ 'set', the server should execute the following routine:</p>
<ol>
<li>If the call does not have a DCP, set it to the PCP from which the command originated.</li>
<li>If the call has a DCP, and the command did not originate from the DCP, return a conflict (cancel) error in response to the command of the following format:
<example caption="Server indicates that the call already has another DCP and that control of the call is no longer available."><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<accept xmlns='urn:xmpp:rayo:1'/>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
otherwise;
</li>
<li>If the command is an accept command, notify the remote calling party that the call has been accepted. Return an empty IQ result to the command issuing party to confirm successful execution.</li>
<li>If the command is an answer command, notify the remote calling party that the call has been answered and negotiate media between the calling party and the server's local media server. Return an empty IQ result to the command issuing party to confirm successful execution.</li>
<li>If the command is any other, handle it in the manner detailed in the following sections.</li>
</ol>
</section3>
</section2>
<section2 topic='Joining Calls' anchor='session-joining'>
<p>Calls on a Rayo Server are capable of having their media streams moved/manipulated. Once such manipulation is to join the media streams of two calls. In a scenario where callA and callB should be joined, the client MUST send a join command to either call (not both) specifying the call ID of the other call, and optionally media attributes (direction and media) specified in the schema, like so:</p>
<example caption="Client instructs callA to join to callB and the server acknowledges the join was completed"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<p>If the calls to be joined to each other are in the same security zone, the server MUST join the media streams of the two calls and return an empty IQ result to confirm that the operation has been successful. If the parties to be joined are not within the same security zone, an error should be returned as detailed below.</p>
<p>When calls are joined to each other by any mechanism, each call MUST dispatch a joined event specifying who they have been joined to:</p>
<example caption="Call A and B were joined, both calls emit joined events"><![CDATA[
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='callB@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
]]></example>
<p>By default, the server MUST join the calls by bridging their audio through its local media server, with bidirectional media. In order to specify alternative behaviour, the client MAY specify a media option (either 'bridge' or 'direct') and/or a direction option (either 'duplex', 'send' or 'recv'), and the server MUST bridge accordingly.</p>
<section3 topic='Errors' anchor='session-joining-errors'>
<p>There are several reasons why the call might return an error instead of acknowledging a join:</p>
<ul>
<li>The specified join party does not exist or cannot be found.</li>
<li>The specified join party is inaccessible for the purposes of being joined due to security restrictions.</li>
<li>The server does not have sufficient resources to complete the join.</li>
<li>The join command was malformed.</li>
<li>The specified media/direction options or their combination are not possible/supported.</li>
</ul>
<p>If the specified join party does not exist or cannot be found, the server MUST return a &lt;service-unavailable/&gt; error with a type of 'cancel'.</p>
<example caption="Call indicates that the specified join party does not exist or cannot be found"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the specified join party is inaccessible for the purposes of being joined due to security restrictions, the server MUST return a &lt;not-allowed/&gt; error with a type of 'cancel'.</p>
<example caption="Call indicates that the specified join party is inaccessible for the purposes of being joined due to security restrictionss"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server does not have sufficient resources to complete the join, the server MUST return a &lt;resource-constraint/&gt; error with a type of 'wait'.</p>
<example caption="Call indicates that there are not sufficient resources to complete the join"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
<error type='wait'>
<resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the join command was malformed (eg no call URI specified), the server MUST return a &lt;bad-request/&gt; error with a type of 'modify'.</p>
<example caption="Call indicates that the join command was malformed"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:'/>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the specified media/direction options or their combination are not possible/supported, the server MUST return a &lt;feature-not-implemented/&gt; error with a type of 'modify'.</p>
<example caption="Call indicates that the specified media/direction options or their combination are not possible/supported."><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit' media='direct' direction='recv'/>
<error type='modify'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
<section3 topic='Unjoin Command' anchor='session-joining-unjoin-command'>
<p>When the client wishes to terminate an existing join, it MUST send an unjoin command specifying the join to break (call-id).</p>
<example caption="Client instructs callA to unjoin from callB"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<unjoin xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</iq>
]]></example>
<p>The server MUST unjoin the media streams of the two calls, rejoin both to the media server and return an empty IQ result to confirm that the operation has been successful:</p>
<example caption="CallA acknowledges unjoin from callB"><![CDATA[
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<p>Optionally, if no join is specified on the unjoin command, all existing joins must be broken:</p>
<example caption="Client instructs callA to unjoin from every existing join"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<unjoin xmlns='urn:xmpp:rayo:1'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<section4 topic='Errors' anchor='session-joining-unjoin-command-errors'>
<p>There are several reasons why the call might return an error instead of acknowledging an unjoin command:</p>
<ul>
<li>The specified join does not exist.</li>
<li>The unjoin command was malformed.</li>
</ul>
<p>If the specified join does not exist, the server MUST return a &lt;service-unavailable/&gt; error with a type of 'cancel'.</p>
<example caption="Call indicates that the specified join does not exist"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
<error type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the unjoin command was malformed (eg an empty call URI specified), the server MUST return a &lt;bad-request/&gt; error with a type of 'modify'.</p>
<example caption="Call indicates that the join command was malformed"><![CDATA[
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<unjoin xmlns='urn:xmpp:rayo:1' call-uri='xmpp:'/>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section4>
</section3>
<section3 topic='Unjoined Event' anchor='session-joining-unjoined-event'>
<p>Calls may be unjoined from other calls either in response to an unjoin command, as the result of one of the calls disconnecting, or as the result of an error. The server MUST monitor calls for being unjoined from another call, and emit an unjoined event when this is detected.</p>
<example caption="CallA announces that it has been unjoined from callB, and vice versa"><![CDATA[
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<unjoined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='callB@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<unjoined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
]]></example>
</section3>
<section3 topic='Multiple Joins' anchor='session-joining-multiple'>
<p>If a client wishes to modify the parameters of a join, it MUST send a new join command to the target call with the new parameters. The server MUST renegotiate media using the new parameters, and acknowledge the command's completion. The server MUST NOT re-send joined events.</p>
<example caption="Client joins callA to callB in receive-only mode, and then 'upgrades' the join to full-duplex"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit' direction='recv'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='callB@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed3'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit' direction='duplex'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed3'/>
]]></example>
<p>Rayo calls SHOULD support being joined to more than one other call at a time, each join having different parameters. Creating a new join MUST NOT destroy existing joins. If a join is requested but cannot be created without destroying existing joins, the call MUST return a conflict (cancel) error.</p>
<example caption="Call indicates that the requested joins cannot be created in parallel"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</iq>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='callB@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed3'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
</iq>
<iq from='callA@shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed3'>
<join xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callC@call.shakespeare.lit'/>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
</section2>
<section2 topic='Mixers' anchor='session-mixers'>
<p>While calls may generally be joined peer-to-peer in any desirable combination, such an implementation is not necessarily scalable or practical to manage. Rayo, therefore, includes the concept of mixers, which are entities like calls, to which calls or other mixers may be joined in the same way as joining multiple calls directly. A mixer MUST be implicitly created the first time a call attempts to join it, MUST immediately broadcast presence to all controlling parties who have calls joined to it, and must respond to the join command with a reference to the mixer. If a mixer cannot be created, an error similar to those specified for &lt;dial/&gt; should be returned in response to the &lt;join/&gt; command. The server MUST include entity capabilities information in the first presence stanza it sends, in order to advertise the fact that the entity is a mixer, qualified by the node name "urn:xmpp:rayo:mixer:1". A mixer MUST emit events (joined, unjoined) to all controlling parties who have calls joined to it, using the same semantics as joining calls.</p>
<p>In order to support friendly-named mixers without causing naming collisions between security zones, a server SHOULD represent a mixer internally using some alternative name scoped to the client's security zone and mapped to the friendly name/URI presented to the client for the emission of events and processing of commands. A server MUST NOT allow clients to interact with mixers allocated within other security zones either by observing their status or media.</p>
<example caption="Client instructs call to join a mixer"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='callA@call.shakespeare.lit'
type='set'
id='h7ed2'>
<join xmlns='urn:xmpp:rayo:1' mixer-name='myMixer'/>
</iq>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<c xmlns='http://jabber.org/protocol/caps'
hash='sha-1'
node='urn:xmpp:rayo:mixer:1'
ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
</presence>
<iq from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:myMixer@mixer.shakespeare.lit'/>
</iq>
<presence from='callA@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' mixer-name='myMixer'/>
</presence>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<joined xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
]]></example>
<p>Mixers MUST respect the normal rules of XMPP presence subscriptions, and presence subscriptions from clients within the same security zone as the mixer must be implicitly permitted.</p>
<p>The error conditions on joining a mixer are the same as for calls, as are the unjoin and join modification semantics. Additionally, mixers SHOULD be able to host components just like calls, following the rules defined for each component.</p>
<example caption="Client renders output to a mixer"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='myMixer@mixer.shakespeare.lit'
type='set'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='text/plain'>
Thanks for calling, goodbye!
</document>
</output>
</iq>
<iq from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:myMixer@mixer.shakespeare.lit/d38d3'/>
</iq>
]]></example>
<p>If the media server providing the mixer supports active speaker detection, it MUST emit active speaker events to all clients with a presence subscription. Such events MUST indicate the start and end of speaking for a particular call ID joined to the mixer.</p>
<example caption="Mixer indicates overlapping speaking status of two joined calls"><![CDATA[
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<started-speaking xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<started-speaking xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<stopped-speaking xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callB@call.shakespeare.lit'/>
</presence>
<presence from='myMixer@mixer.shakespeare.lit'
to='juliet@capulet.lit/balcony'>
<stopped-speaking xmlns='urn:xmpp:rayo:1' call-uri='xmpp:callA@call.shakespeare.lit'/>
</presence>
]]></example>
</section2>
<p>Once the last participant unjoins from the mixer, the mixer SHOULD be destroyed. When a mixer is destroyed, it MUST send unavailable presence to all entities which have a presence subscription.</p>
<section2 topic='Component Execution' anchor='session-component-execution'>
<p>Components are long-lived elements of a call or mixer which may execute in parallel, have a lifecycle (may send events and/or process commands during their execution, indicate their completion asynchronously) and typically implement media operations. A server SHOULD implement components in such a way that it is acceptable to execute multiple components of the same type or of differing types simultaneously. A server SHOULD implement all core components.</p>
<p>In the event that a call or mixer receives a command which triggers the execution of a component, it MUST use the normal command handling routine, schedule the component for immediate execution and return a reference to the requesting client as confirmation of the component's creation:</p>
<example caption="Client requests execution of an output component"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='text/plain'>
Thanks for calling, goodbye!
</document>
</output>
</iq>
]]></example>
<example caption="Server provides reference to output component"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'>
<ref xmlns='urn:xmpp:rayo:1' uri='xmpp:9f00061@call.shakespeare.lit/eh3u82'/>
</iq>
]]></example>
<p>If a component execution command is received prior to the call being answered, the server MUST NOT answer the call, and SHOULD attempt to use early-media techniques to perform the relevant operation without answering the call. If such early-media is not possible, it MUST return an error indicating that the call state is incorrect (unexpected-request).</p>
<p>The whole command MUST be parsed up-front, and any applicable validation performed before acknowledgement of the command.</p>
<section3 topic='Initial Errors' anchor='session-component-initial-errors'>
<p>There are several reasons why the server might immediately return an error instead of acknowledging the creation of a new component:</p>
<ul>
<li>The server does not implement the component.</li>
<li>The server does not implement a particular option value for the component.</li>
<li>Some aspect of the component does not comply with this specification.</li>
<li>The server does not have sufficient resources to create a new component on this call/mixer.</li>
<li>The component would cause a resource conflict with another component on this call/mixer.</li>
<li>The call/mixer is not in the correct state to begin executing the component.</li>
</ul>
<p>If the server does not implement the command/component, it should return a feature-not-implemented (cancel) error:</p>
<example caption="Server indicates a lack of support for the requested component/command"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='text/plain'>
Thanks for calling, goodbye!
</document>
</output>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server does not implement a particular option value for the command/component, it should return a feature-not-implemented (modify) error:</p>
<example caption="Server indicates a lack of support for some aspect of the requested component/command"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'
repeat-times='4'/>
<error type='modify'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the command does not meet the specification, the server should return a bad-request (modify) error:</p>
<example caption="Server indicates the requested component/command does not meet the specification"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'
repeat-times='foo'/>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server does not have sufficient resources to create the component, it should return a resource-constraint (wait) error:</p>
<example caption="Server indicates a lack of resources to create the requested component"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='text/plain'>
Thanks for calling, goodbye!
</document>
</output>
<error type='wait'>
<resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server is not able to create the component due to a resource conflict with another component, it should return a resource-constraint (wait) error:</p>
<example caption="Server indicates a resource conflict with another component"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='text/plain'>
Thanks for calling, goodbye!
</document>
</output>
<error type='wait'>
<resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the server is not able to create the component due to the call being in an incorrect state, it should return an unexpected-request (wait) error:</p>
<example caption="Server indicates incorrect call state"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='text/plain'>
Thanks for calling, goodbye!
</document>
</output>
<error type='wait'>
<unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
<p>Once acknowleged, the component MUST begin execution according to its particular specification. During its execution, it MAY emit events relevant to its progress, and an implementation MUST be capable of emitting events specified for each component. Any events should be sent inside a directed presence element to the executing party.</p>
<p>During execution, the component MUST respond to commands addressed to it. Each component has its own set of commands, but all components have the 'stop' command in common. On receipt of the stop command, the component MUST acknowledge that it has been instructed to stop and gracefully cease its execution in whatever way is appropriate to the particular component.</p>
<example caption="Client requests component stop, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<stop xmlns='urn:xmpp:rayo:ext:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<section3 topic='Command Errors' anchor='session-component-command-errors'>
<p>There are several reasons why a component might return an error instead of acknowledging a command:</p>
<ul>
<li>The component does not implement the command.</li>
<li>The component does not implement a particular option value for the command.</li>
<li>Some aspect of the command does not comply with the components specification.</li>
<li>The command is not appropriate for the component at its current stage of execution.</li>
<li>The command is issued by a party other than that which created the component.</li>
</ul>
<p>If the component does not implement the command, it should return a feature-not-implemented (cancel) error:</p>
<example caption="Component indicates a lack of support for the requested command"><![CDATA[
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<stop xmlns='urn:xmpp:rayo:ext:1'/>
<error type='cancel'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the component does not implement a particular option/value for the command, it should return a feature-not-implemented (modify) error:</p>
<example caption="Component indicates a lack of support for some option/value on the command"><![CDATA[
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<stop xmlns='urn:xmpp:rayo:ext:1'/>
<error type='modify'>
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If some aspect of the command does not comply with the component's spec, it should return a bad-request (modify) error:</p>
<example caption="Component indicates some aspect of the command is not spec compliant"><![CDATA[
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<stop xmlns='urn:xmpp:rayo:ext:1'/>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the command is not appropriate for the component's current stage of execution, it should return a unexpected-request (wait) error:</p>
<example caption="Component indicates that the command is not appropriate for the component's current stage of execution"><![CDATA[
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<stop xmlns='urn:xmpp:rayo:ext:1'/>
<error type='wait'>
<unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<p>If the command is issued by a party other than the component creator, it should return a conflict (cancel) error:</p>
<example caption="Component indicates command cannot be executed by anyone other than the component owner"><![CDATA[
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/courtyard'
type='error'
id='h7ed2'>
<stop xmlns='urn:xmpp:rayo:ext:1'/>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
<p>When the component ceases to execute, it MUST send a <link url='#def-components-complete'>complete event</link> with a valid reason to the requesting party as directed presence with a type of 'unavailable'.</p>
<example caption="Component indicates it has completed due to being stopped"><![CDATA[
<presence from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/courtyard'
type='unavailable'>
<complete xmlns='urn:xmpp:rayo:ext:1'>
<stop xmlns='urn:xmpp:rayo:ext:complete:1'/>
</complete>
</presence>
]]></example>
<p>Once a component is completed, or if it did not exist, the server should return an item-not-found (cancel) error as response to any commands:</p>
<example caption="Non-existant component receives a command"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<stop xmlns='urn:xmpp:rayo:ext:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<stop xmlns='urn:xmpp:rayo:ext:1'/>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
<section3 topic='Output Component' anchor='session-component-execution-output'>
<p>Media output is a core concept in Rayo, and is provided by the output component. The component allows media to be rendered to a call or a mixer, using the server's local media server. A server MUST support audio file playback and MUST support the text/uri-list document format. A server MAY support speech synthesis and MAY support <link url='http://www.w3.org/TR/speech-synthesis/'>SSML</link> (in which case the document should be escaped or enclosed in CDATA). The component is created using an <link url='def-component-output'>&lt;output/&gt; command</link>, containing one or more documents to render, along with a set of options to determine the nature of the rendering.</p>
<example caption='Client renders a simple SSML document to a call'><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='application/ssml+xml'>
<![CDATA[
<?xml version="1.0"?>
<!DOCTYPE speak PUBLIC "-//W3C//DTD SYNTHESIS 1.0//EN"
"http://www.w3.org/TR/speech-synthesis/synthesis.dtd">
<speak version="1.0"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/10/synthesis
http://www.w3.org/TR/speech-synthesis/synthesis.xsd"
xml:lang="en-US">
<p>
<s>You have 4 new messages.</s>
<s>The first is from Stephanie Williams and arrived at <break/> 3:45pm.</s>
<s>
The subject is <prosody rate="-20%">ski trip</prosody>
</s>
</p>
</speak>
]]]]><![CDATA[>
</document>
</output>
</iq>
]]></example>
<example caption='Client renders a plain text document to a call'><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='text/plain'>
Thanks for calling, goodbye!
</document>
</output>
</iq>
]]></example>
<p>The server MUST validate that it has apropriate resources/mechanisms to render the requested document before acknowledging the component creation.</p>
<section4 topic='Join considerations' anchor='session-component-exection-output-joins'>
<p>In the case that an output component is executed on a call joined to other calls or mixers, the output MUST be rendered only to the call and not the joined parties (also known as 'whisper'). In the case that an output component is executed on a mixer, the output should be rendered into the mixer, such that all participants receive the output (also known as 'announce').</p>
</section4>
<section4 topic='Commands' anchor='session-component-execution-output-commands'>
<p>The output component implements several commands for manipulating the output during its execution.</p>
<section5 topic='Pause' anchor='session-component-execution-output-pause'>
<p>A client may instruct an output component to pause by sending a pause command. The server MUST cause the media server to pause rendering, maintaining position within the document and allowing for later resumption.</p>
<example caption="Client requests output component pause, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<pause xmlns='urn:xmpp:rayo:output:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
<section5 topic='Resume' anchor='session-component-execution-output-resume'>
<p>A client may instruct an output component to resume rendering if it has previously been paused. The server MUST cause the media server to resume rendering at the last pause marker.</p>
<example caption="Client requests output component resume, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<resume xmlns='urn:xmpp:rayo:output:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
<section5 topic='SpeedUp' anchor='session-component-execution-output-speedup'>
<p>A client may instruct an output component to increase the rendering rate by a unit amount, defined by the media server. The server MUST cause the media server to perform the rate increase and acknowledge the command.</p>
<example caption="Client requests output component speed up, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<speed-up xmlns='urn:xmpp:rayo:output:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
<section5 topic='SpeedDown' anchor='session-component-execution-output-speeddown'>
<p>A client may instruct an output component to decrease the rendering rate by a unit amount, defined by the media server. The server MUST cause the media server to perform the rate decrease and acknowledge the command.</p>
<example caption="Client requests output component speed down, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<speed-down xmlns='urn:xmpp:rayo:output:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
<section5 topic='VolumeUp' anchor='session-component-execution-output-volumeup'>
<p>A client may instruct an output component to increase the rendering volume by a unit amount, defined by the media server. The server MUST cause the media server to perform the volume increase and acknowledge the command.</p>
<example caption="Client requests output component volume up, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<volume-up xmlns='urn:xmpp:rayo:output:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
<section5 topic='VolumeDown' anchor='session-component-execution-output-volumedown'>
<p>A client may instruct an output component to decrease the rendering volume by a unit amount, defined by the media server. The server MUST cause the media server to perform the volume decrease and acknowledge the command.</p>
<example caption="Client requests output component volume down, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<volume-down xmlns='urn:xmpp:rayo:output:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
<section5 topic='Seek' anchor='session-component-execution-output-seek'>
<p>A client may instruct an output component to move the play marker forward or back in time by a specified amount before resuming output. The server MUST cause the media to seek as instructed and acknowledge the command.</p>
<p>The attributes of the &lt;seek/&gt; element are as follows.</p>
<example caption="Client requests output seek forward by 20s, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<seek xmlns='urn:xmpp:rayo:output:1' direction='forward' amount='20000'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
</section4>
<section4 topic='Events' anchor='session-component-execution-output-events'>
<p>The output component does not provide any intermediate events.</p>
</section4>
<section4 topic='Completion' anchor='session-component-execution-output-completion'>
<p>The output completion reason MUST be one of the <link url='#def-components-complete-reason'>core Rayo reasons</link>, <link url='#def-component-output-finish'>finish</link> (indicating that the document finished rendering naturally) or <link url='#def-component-output-maxtime'>max-time</link> (indicating that the maximum time was exceeded). Output component completion does not provide any metadata.</p>
<example caption="Component indicates it has completed due to reaching the end of the document"><![CDATA[
<presence from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/courtyard'
type='unavailable'>
<complete xmlns='urn:xmpp:rayo:ext:1'>
<finish xmlns='urn:xmpp:rayo:output:complete:1'/>
</complete>
</presence>
]]></example>
</section4>
</section3>
<section3 topic='Input Component' anchor='session-component-execution-input'>
<p>Media input is a core concept in Rayo, and is provided by the input component. The component allows input to be collected from a call by way of either <link url='http://www.itu.int/rec/T-REC-Q.23-198811-I/en'>DTMF</link> (dual-tone multi-frequency) or ASR (automatic speech recognition), using the server's local media server. A Rayo server MUST support DTMF input and MUST support <link url='http://www.w3.org/TR/speech-grammar/'>SRGS</link> XML grammars (application/srgs+xml). A server MAY suport speech input, and MAY support other grammar formats. The component is created using an <link url='def-component-input'>&lt;input/&gt; command</link>, containing one or more grammar documents by which to control input, along with a set of options to determine the nature of the collection.</p>
<example caption='Client requests DTMF input collection from a call'><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<input xmlns='urn:xmpp:rayo:input:1' mode='dtmf'>
<grammar content-type='application/srgs+xml'>
<![CDATA[
<?xml version="1.0"?>
<grammar mode="dtmf" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/06/grammar
http://www.w3.org/TR/speech-grammar/grammar.xsd"
xmlns="http://www.w3.org/2001/06/grammar">
<rule id="digit">
<one-of>
<item> 0 </item>
<item> 1 </item>
<item> 2 </item>
<item> 3 </item>
<item> 4 </item>
<item> 5 </item>
<item> 6 </item>
<item> 7 </item>
<item> 8 </item>
<item> 9 </item>
</one-of>
</rule>
<rule id="pin" scope="public">
<one-of>
<item>
<item repeat="4"><ruleref uri="#digit"/></item>
#
</item>
<item>
* 9
</item>
</one-of>
</rule>
</grammar>
]]]]><![CDATA[>
</grammar>
</input>
</iq>
]]></example>
<p>The server MUST validate that it has appropriate resources/mechanisms to collect the requested input before acknowledging the component creation.</p>
<section4 topic='Join considerations' anchor='session-component-exection-input-joins'>
<p>In the case that an input component is executed on a call joined to other calls or mixers, the input MUST be collected only from the call and not the joined parties. Input components executed on a mixer MUST collect and combine input from all participants joined to the mixer.</p>
</section4>
<section4 topic='Commands' anchor='session-component-execution-input-commands'>
<p>The input component does not implement any intermediate commands, other than those specified for all components.</p>
</section4>
<section4 topic='Events' anchor='session-component-execution-input-events'>
<p>The input component does not provide any intermediate events.</p>
</section4>
<section4 topic='Completion' anchor='session-component-execution-input-completion'>
<p>The input completion reason MUST be one of the <link url='#def-components-complete-reason'>core Rayo reasons</link>, or one of the following reasons. Input component completion provides match metadata for the &lt;finish/&gt; reason only.</p>
<ul>
<li>
<link url='#def-component-input-match'>match</link> (indicating that one of the grammars matched the received input).
</li>
<li>
<link url='#def-component-input-noinput'>noinput</link> (indicating that no input was received before a timeout was encountered).
</li>
<li>
<link url='#def-component-input-nomatch'>nomatch</link> (indicating that input was received which did not match any of the specified grammars).
</li>
</ul>
<p>If the media server reports a match to one of the provided grammars, the server MUST present the results of the match to the client by way of a match document in the format requested by the client. A server MUST be capable of supporting NLSML, and may support other formats.</p>
<example caption="Component indicates it has completed due to one of the grammars returning a match"><![CDATA[
<presence from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/courtyard'
type='unavailable'>
<complete xmlns='urn:xmpp:rayo:ext:1'>
<match xmlns='urn:xmpp:rayo:input:complete:1' content-type="application/nlsml+xml">
<![CDATA[
<result xmlns="http://www.ietf.org/xml/ns/mrcpv2" grammar="http://foodorder">
<interpretation>
<input mode="dtmf" confidence="100">1 2 3 4</input>
</interpretation>
</result>
]]]]><![CDATA[>
</match>
</complete>
</presence>
]]></example>
</section4>
</section3>
<section3 topic='Prompt Component' anchor='session-component-execution-prompt'>
<p>Prompt is a convenience component to wrap input and output components, combine their lifecycles, and allow input to barge-in on an output component in the standard sense.</p>
<example caption='Client requests DTMF input collection from a call'><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<prompt xmlns='urn:xmpp:rayo:prompt:1'>
<output xmlns='urn:xmpp:rayo:output:1'>
<document content-type='application/ssml+xml'>
<![CDATA[
<?xml version="1.0"?>
<!DOCTYPE speak PUBLIC "-//W3C//DTD SYNTHESIS 1.0//EN"
"http://www.w3.org/TR/speech-synthesis/synthesis.dtd">
<speak version="1.0"
xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/10/synthesis
http://www.w3.org/TR/speech-synthesis/synthesis.xsd"
xml:lang="en-US">
<p>
<s>Please enter your pin number now.</s>
</p>
</speak>
]]]]><![CDATA[>
</document>
</output>
<input xmlns='urn:xmpp:rayo:input:1' mode='dtmf'>
<grammar content-type='application/srgs+xml'>
<![CDATA[
<?xml version="1.0"?>
<grammar mode="dtmf" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/06/grammar
http://www.w3.org/TR/speech-grammar/grammar.xsd"
xmlns="http://www.w3.org/2001/06/grammar">
<rule id="digit">
<one-of>
<item> 0 </item>
<item> 1 </item>
<item> 2 </item>
<item> 3 </item>
<item> 4 </item>
<item> 5 </item>
<item> 6 </item>
<item> 7 </item>
<item> 8 </item>
<item> 9 </item>
</one-of>
</rule>
<rule id="pin" scope="public">
<one-of>
<item>
<item repeat="4"><ruleref uri="#digit"/></item>
#
</item>
<item>
* 9
</item>
</one-of>
</rule>
</grammar>
]]]]><![CDATA[>
</grammar>
</input>
</prompt>
</iq>
]]></example>
<p>The server MUST validate that it has appropriate resources/mechanisms to render the requested output and collect the requested input before acknowledging the component creation.</p>
<section4 topic='Join considerations' anchor='session-component-exection-prompt-joins'>
<p>The prompt component follows the same combined join considerations as output and input components.</p>
</section4>
<section4 topic='Commands' anchor='session-component-execution-prompt-commands'>
<p>The prompt component implements implements all intermediate commands from output and input and behaves the same. If output component commands are executed after the output component has ceased executing, a &lt;unexpected-request&gt; error MUST be returned.</p>
</section4>
<section4 topic='Events' anchor='session-component-execution-prompt-events'>
<p>The prompt component emits intermediate events from the nested output and input components.</p>
<p>It also emits an 'input-timers-started' event when the input component's timers are started, which corresponds to the completion of the output sub-component.</p>
<example caption='Prompt component announces that the input timers have started'><![CDATA[
<presence from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/courtyard'>
<input-timers-started xmlns='urn:xmpp:rayo:prompt:1'/>
</presence>
]]></example>
</section4>
<section4 topic='Completion' anchor='session-component-execution-prompt-completion'>
<p>The input completion reason MUST be one of the <link url='#def-components-complete-reason'>core Rayo reasons</link>, or one of the <link url='#session-component-execution-input-completion'>Input component reasons</link>. Events signalling completion of the output components are suppressed.</p>
</section4>
</section3>
<section3 topic='Record Component' anchor='session-component-execution-record'>
<p>Call recording is a core concept in Rayo, and is provided by the record component. The component allows media to be captured from a call or a mixer, using the server's local media server, stored, and made available to clients. The component is created using a <link url='def-component-record'>&lt;record/&gt; command</link>, potentially with a set of options to determine the nature of the recording.</p>
<example caption='Client requests a simple recording'><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<record xmlns='urn:xmpp:rayo:record:1'/>
</iq>
]]></example>
<p>The server MUST validate that it has apropriate resources/mechanisms to make the recording before acknowledging the component creation. The component MUST ignore any hints that it does not understand.</p>
<section4 topic='Join considerations' anchor='session-component-exection-record-joins'>
<p>In the case that a record component is executed on a call joined to other calls or mixers, the direction attibute will specify if the sent audio, received audio, or both will be present in the recording.</p>
<p>In send mode, only the audio sent by the caller is recorded.</p>
<p>In recv mode, when just joined to the media server, should record TTS, audio playback, etc; when joined to another call, should record that other call's sending audio (probably a human talking) also. When joined to a mixer, should record the audio send from the mixer (other people talking) also.</p>
<p>Duplex mode is a combination of send and recv. The platform may mix these or record them as separate channels.</p>
<p>When executing a record against a mixer, send mode is not supported. Recv mode records audio from all mixer participants. Duplex is a clone of recv.</p>
</section4>
<section4 topic='Commands' anchor='session-component-execution-record-commands'>
<p>The record component implements several commands for manipulating the recording during its execution.</p>
<section5 topic='Pause' anchor='session-component-execution-record-pause'>
<p>A client may instruct a record component to pause by sending a pause command. The server MUST cause the media server to pause recording, allowing for later appending.</p>
<example caption="Client requests record component pause, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<pause xmlns='urn:xmpp:rayo:record:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
<section5 topic='Resume' anchor='session-component-execution-record-resume'>
<p>A client may instruct a record component to resume recording if it has previously been paused. The server MUST cause the media server to resume recording, appending to the original file.</p>
<example caption="Client requests record component resume, server confirms"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit/eh3u28'
type='set'
id='h7ed2'>
<resume xmlns='urn:xmpp:rayo:record:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
</section5>
</section4>
<section4 topic='Events' anchor='session-component-execution-record-events'>
<p>The record component does not provide any intermediate events.</p>
</section4>
<section4 topic='Completion' anchor='session-component-execution-record-completion'>
<p>The record completion reason MUST be one of the <link url='#def-components-complete-reason'>core Rayo reasons</link>, or one of the following reasons. Record component completion provides recording metadata in all cases.</p>
<ul>
<li>
<link url='#def-component-record-max-duration'>max-duration</link> (indicating that the max duration was reached).
</li>
<li>
<link url='#def-component-record-initial-timeout'>initial-timeout</link> (indicating that the initial timeout was triggered).
</li>
<li>
<link url='#def-component-record-final-timeout'>final-timeout</link> (indicating that the final timeout was triggered).
</li>
</ul>
<p>The server MUST present the recording for consumption by the client by way of recording metadata on the complete reason, including a URI at which the recording may be fetched. It MUST provide uri, duration &amp; size data as specified on the <link url='#def-component-record-recording'>recording element</link>.</p>
<example caption="Component indicates it has completed due to being stopped, providing the recording"><![CDATA[
<presence from='9f00061@call.shakespeare.lit/eh3u28'
to='juliet@capulet.lit/courtyard'
type='unavailable'>
<complete xmlns='urn:xmpp:rayo:ext:1'>
<stop xmlns='urn:xmpp:rayo:ext:complete:1'/>
<recording xmlns='urn:xmpp:rayo:record:complete:1' uri='xmpp:http://rayo.io/recordings/foo.wav' duration='20000' size='12287492817'/>
</complete>
</presence>
]]></example>
</section4>
</section3>
</section2>
<section2 topic='Session Termination' anchor='session-termination'>
<p>Session termination may occur by one of several methods:</p>
<ul>
<li>An inbound call may be <link url='#session-termination-redirection'>redirected</link> by a PCP to some other target.</li>
<li>An inbound call may be <link url='#session-termination-rejection'>rejected</link> by a PCP.</li>
<li>An active call, whether inbound or outbound, may be <link url='#session-termination-hangup'>hung up</link> (gracefully ended) by a DCP.</li>
<li>An active call may be hung up (gracefully ended) by the remote party.</li>
<li>An outbound call may be rejected by the remote party.</li>
</ul>
<p>A <link url='#session-termination-end'>call end notification</link> will be dispatched to the PCP if one of the following conditions is met:</p>
<ul>
<li>The call has been accepted and has a PCP.</li>
<li>The call is outbound and implicitly has a PCP (the requesting party).</li>
</ul>
<section3 topic='Call Redirection' anchor='session-termination-redirection'>
<p>If a client can determine a more appropriate target for an incoming call, it may wish to relay this information to the caller in the form of a URI (eg SIP). The target URI must be specified in the 'to' attribute of the redirect element.</p>
<example caption="Client instructs a call to redirect, with some headers"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<redirect xmlns='urn:xmpp:rayo:1'
to='sip:other@there.com'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</redirect>
</iq>
]]></example>
<p>The server should send an appropriate redirection instruction to the underlying session.</p>
<p>If the server is able to successfully relay the redirection to the calling party, it should send an empty IQ result to confirm the command has completed execution:</p>
<example caption="Server acknowledges successful redirect"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<p>If the server is unable to perform the redirect because the call is in a state where a redirect is not possible, it should return an unexpected-request (wait) error indicating such:</p>
<example caption="Server indicates that the call is in a state where a redirect is not possible."><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<redirect xmlns='urn:xmpp:rayo:1'
to='sip:other@there.com'>
<header name="x-skill" value="agent" />
<header name="x-customer-id" value="8877" />
</redirect>
<error type='wait'>
<unexpected-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
<section3 topic='Call Rejection' anchor='session-termination-rejection'>
<p>If a client cannot handle an incoming call, it MAY reject it. The client MUST do this before accepting the call. The target URI must be specified in the 'to' attribute of the redirect element.</p>
<example caption="Client instructs a call to reject, with some headers"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<reject xmlns='urn:xmpp:rayo:1'>
<header name="x-reject-description" value="Sorry, she cannae take it!" />
</reject>
</iq>
]]></example>
<p>The server should reject the underlying session. If the server is able to do so successfully, it should send an empty IQ result to confirm the command has completed execution:</p>
<example caption="Server acknowledges successful rejection"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<p>If the server is unable to perform the rejection because the call has already been accepted, it should return a not-allowed (cancel) error indicating such:</p>
<example caption="Server indicates that the call already has another DCP and that control of the call is no longer available."><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<reject xmlns='urn:xmpp:rayo:1'>
<header name="x-reject-description" value="Sorry, she cannae take it!" />
</reject>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
<section3 topic='Call Hangup' anchor='session-termination-hangup'>
<p>If a client wishes to end a call it should send a hangup command to the call instructing it to do so:</p>
<example caption="Client instructs a call to hangup, with some headers"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<hangup xmlns='urn:xmpp:rayo:1'>
<header name="x-call-result" value="4" />
</hangup>
</iq>
]]></example>
<p>The server should queue the call for immediate hangup and return a response indicating success of the command:</p>
<example caption="Server acknowledges hangup queueing"><![CDATA[
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='result'
id='h7ed2'/>
]]></example>
<p>The server MUST follow this sequence to hang up a call:</p>
<ul>
<li>Terminate all components of the call, and components MUST send a complete event indicating hangup as the cause.</li>
<li>Terminate all joins on the call, sending unjoined events.</li>
<li>Terminate the underlying session.</li>
</ul>
</section3>
<section3 topic='Call End Notification' anchor='session-termination-end'>
<p>The server MUST monitor a call's underlying session and react appropriately in the case that it comes to an end:</p>
<ul>
<li>The server MUST determine the reason for the call ending to be one of <link url='#def-end-reason'>the appropriate end reasons</link>.</li>
<li>If the call ending was not a result of a hangup command from a client, the server MUST terminate all components on the call, which MUST send a complete event indicating hangup as the cause. The server MUST additionally terminate all joins on the call, sending unjoined events.</li>
<li>The server MUST send an end event (of type unavailable) on behalf of the call, specifying the above determined reason as a child element, to all JIDs to which an offer was sent or from which a command was received.</li>
<li>The server MUST NOT send any more events from a call which has ended and declared itself unavailable.</li>
<li>The server MUST respond to any commands sent to an ended call (or one which never existed) with an item-not-found (cancel) error.</li>
</ul>
<example caption="Controlling party receives notification of the call being terminated due to a remote party hangup"><![CDATA[
<presence from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='unavailable'>
<end xmlns='urn:xmpp:rayo:1'>
<hangup/>
</end>
</presence>
]]></example>
<example caption="Non-existant call receives a command"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='set'
id='h7ed2'>
<answer xmlns='urn:xmpp:rayo:1'/>
</iq>
<iq from='9f00061@call.shakespeare.lit'
to='juliet@capulet.lit/balcony'
type='error'
id='h7ed2'>
<answer xmlns='urn:xmpp:rayo:1'/>
<error type='cancel'>
<item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
]]></example>
</section3>
</section2>
<section2 topic='Headers' anchor='session-headers'>
<p>In elements which may carry child &lt;header/&gt; elements, a server or client MAY specify several header elements with the same name. In such cases, these MUST be considered to form a collection of ordered values for the key provided.</p>
<example caption="Client requests establishment of a new outbound session with multiple values for the SIP Route header"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
to='shakespeare.lit'
type='set'
id='h7ed2'>
<dial xmlns='urn:xmpp:rayo:1'
to='tel:+13055195825'
from='tel:+14152226789'>
<header name="Route" value="foo" />
<header name="Route" value="bar" />
</dial>
</iq>
]]></example>
</section2>
<section2 topic='Instant Messages' anchor='session-im'>
<section3 topic='Call-bound Messages' anchor='session-im-call-bound'>
<p>XMPP message stanzas directed to the call's JID with a type of 'normal' MAY be forwarded to the calling party by translating the message into the calling party's protocol. In the case of SIP, this SHOULD follow the conventions set out in <link url="http://tools.ietf.org/html/draft-ietf-stox-im-06">draft-ietf-stox-im-06</link> with the exception of the &lt;thread/&gt; to Call-ID mapping, as the Call-ID will always be that of the calling party.</p>
<p>If a message is directed to the call's JID with a type other than 'normal' then the server MUST return a &lt;feature-not-implemented/&gt; error with a type of 'modify'. If no translation is possible then the server SHOULD return the same error but with a type of 'cancel'.</p>
<example caption="Translation of a XMPP message into a SIP MESSAGE"><![CDATA[
<message
from='juliet@capulet.lit/balcony'
to='9f00061@call.shakespeare.lit'
type='normal'>
<body>Art thou not Romeo, and a Montague?</body>
</message>
MESSAGE sip:romeo@montague.lit SIP/2.0
Via: SIP/2.0/UDP call.shakespeare.lit;branch=AmRHlGRD0WD7BHgM5fKc
Max-Forwards: 70
From: <sip:call.shakespeare.lit>;tag=78aBN3CgAB8MK
To: <sip:romeo@montague.lit>;tag=Z7nlVUbvTOmV6
Call-ID: 2819297471
CSeq: 55119460 MESSAGE
Content-Type: text/plain
Content-Length: 35
Art thou not Romeo, and a Montague?
]]></example>
</section3>
</section2>
</section1>
<section1 topic='Formal Definition' anchor='def'>
<section2 topic='Header Element' anchor='def-header'>
<p>The &lt;header/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;header/&gt; element are as follows.</p>
<table caption='Attributes of Header Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>name</td>
<td>A token giving the name by which the header may be known.</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>value</td>
<td>The string value of the named header.</td>
<td>REQUIRED</td>
</tr>
</table>
</section2>
<section2 topic='Offer Element' anchor='def-offer'>
<p>Informs the recipient that a new call is available for control and invites it to take control using progress commands below.</p>
<p>The &lt;offer/&gt; element MAY contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The attributes of the &lt;offer/&gt; element are as follows.</p>
<table caption='Attributes of Offer Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>to</td>
<td>The target URI for the call. May me a tel URI, SIP URI, a JID (for Jingle) or some other platform-specific addressing mechanism.</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>from</td>
<td>The caller ID URI for the call. May be a tel URI, SIP URI, a JID (for Jingle) or some other platform-specific addressing mechanism.</td>
<td>OPTIONAL</td>
</tr>
</table>
</section2>
<section2 topic='Ringing Element' anchor='def-ringing'>
<p>Indication that an outbound call has begun ringing, or accepted by the remote party.</p>
<p>The &lt;ringing/&gt; element MAY contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The &lt;ringing/&gt; element has no attributes.</p>
</section2>
<section2 topic='Answered Element' anchor='def-answered'>
<p>Indication that an outbound call has been answered and that the 3rd party negotiation has completed. At this point, the media stream should be open.</p>
<p>The &lt;answered/&gt; element MAY contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The &lt;answered/&gt; element has no attributes.</p>
</section2>
<section2 topic='End Element' anchor='def-end'>
<p>Indication that the call has come to an end, giving the reason.</p>
<p>The &lt;end/&gt; element MUST contain a single <link url='#def-end-reason'>end reason element</link>. It MAY also contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The &lt;end/&gt; element has no attributes.</p>
<section3 topic='End Reason Element' anchor='def-end-reason'>
<p>The following are valid end reason elements. Unless otherwise stated, they all MUST be empty.</p>
<p>The attributes of the end reason element are as follows.</p>
<table caption='Attributes of End Reason Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>platform-code</td>
<td>A platform-specific end code. This could be a SIP code, ITU-T Q.850 or some other system. The code may be an arbitrary string.</td>
<td>OPTIONAL</td>
</tr>
</table>
<dl>
<di>
<dt>&lt;hungup/&gt;</dt>
<dd>Indication that the call ended due to a normal hangup by the remote party.</dd>
</di>
<di>
<dt>&lt;hangup-command/&gt;</dt>
<dd>Indication that the call ended due to a normal hangup triggered by a hangup command.</dd>
</di>
<di>
<dt>&lt;timeout/&gt;</dt>
<dd>Indication that the call ended due to a timeout in contacting the remote party.</dd>
</di>
<di>
<dt>&lt;busy/&gt;</dt>
<dd>Indication that the call ended due to being rejected by the remote party subsequent to being accepted.</dd>
</di>
<di>
<dt>&lt;rejected/&gt;</dt>
<dd>Indication that the call ended due to being rejected by the remote party before being accepted.</dd>
</di>
<di>
<dt>&lt;error/&gt;</dt>
<dd>Indication that the call ended due to a system error.</dd>
</di>
</dl>
</section3>
</section2>
<section2 topic='Accept Element' anchor='def-accept'>
<p>Instructs the server to send notification to the calling party that the call will be dealt with and that ringing may begin.</p>
<p>The &lt;accept/&gt; element MAY contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The &lt;accept/&gt; element has no attributes.</p>
</section2>
<section2 topic='Answer Element' anchor='def-answer'>
<p>Instructs the server to pick up an incoming call and connect the media stream.</p>
<p>The &lt;answer/&gt; element MAY contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The &lt;answer/&gt; element has no attributes.</p>
</section2>
<section2 topic='Redirect Element' anchor='def-redirect'>
<p>Instructs the calling party that the call will not be accepted and that instead it should try to call the URI indicated in the command.</p>
<p>The &lt;redirect/&gt; element MAY contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The attributes of the &lt;redirect/&gt; element are as follows.</p>
<table caption='Attributes of Offer Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>to</td>
<td>The new target URI for the call to be redirected to.</td>
<td>REQUIRED</td>
</tr>
</table>
</section2>
<section2 topic='Reject Element' anchor='def-reject'>
<p>Instructs the server to reject the call with a given reason.</p>
<p>The &lt;reject/&gt; element MUST contain a single <link url='#def-reject-reason'>reject reason element</link>. It MAY also contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The &lt;reject/&gt; element has no attributes.</p>
<section3 topic='Reject Reason Element' anchor='def-reject-reason'>
<p>The following are valid reject reason elements. Unless otherwise stated, they all MUST be empty, and they do not have any attributes.</p>
<dl>
<di>
<dt>&lt;decline/&gt;</dt>
<dd>Indicates that the controlling party refused the call for an unspecified reason, such as access control.</dd>
</di>
<di>
<dt>&lt;busy/&gt;</dt>
<dd>Indicates that the controlling party refused the call due to excess load.</dd>
</di>
<di>
<dt>&lt;error/&gt;</dt>
<dd>Indicates that the controlling party refused the call because some error occurred.</dd>
</di>
</dl>
</section3>
</section2>
<section2 topic='Hangup Element' anchor='def-hangup'>
<p>Instructs the server to bring the call to an end naturally.</p>
<p>The &lt;hangup/&gt; element MAY contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>.</p>
<p>The &lt;hangup/&gt; element has no attributes.</p>
</section2>
<section2 topic='Dial Element' anchor='def-dial'>
<p>Instructs the server to create a new call and surrender control of it to the requesting party.</p>
<p>The &lt;dial/&gt; element MAY contain one or more <link url='#def-header'>&lt;header/&gt; elements</link>. It MAY contain one or more <link url='#def-join'>&lt;join/&gt; elements</link>, instructing the server to join the new call in the indicated manner rather than the default (join to the local media server).</p>
<p>The attributes of the &lt;dial/&gt; element are as follows.</p>
<table caption='Attributes of Dial Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
<th>Default</th>
</tr>
<tr>
<td>to</td>
<td>Indicates the party to whom the call should be directed.</td>
<td>REQUIRED</td>
<td></td>
</tr>
<tr>
<td>from</td>
<td>Indicates the caller ID with which the call should appear to originate.</td>
<td>OPTIONAL</td>
<td></td>
</tr>
<tr>
<td>uri</td>
<td>Indicates the URI at which the client wishes the call to be presented.</td>
<td>OPTIONAL</td>
<td></td>
</tr>
<tr>
<td>timeout</td>
<td>Indicates the maximum time allowed for a response to be provided by the remote party before the call should be considered to have come to an end.</td>
<td>OPTIONAL</td>
<td>-1</td>
</tr>
</table>
</section2>
<section2 topic='Join Element' anchor='def-join'>
<p>Instructs the server to join the media streams of the call and the specified party, given direction and media negotiation parameters.</p>
<p>The &lt;join/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;join/&gt; element are as follows.</p>
<table caption='Attributes of Join Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
<th>Default</th>
</tr>
<tr>
<td>direction</td>
<td>
<p>Indicates the direction in which the media should flow between the call and the 3rd party. Must be one of the following values:</p>
<ul>
<li><strong>"duplex"</strong> - Indicates that media should flow in both directions between the parties.</li>
<li><strong>"send"</strong> - Indicates that media should only flow from the target call to the third party.</li>
<li><strong>"recv"</strong> - Indicates that media should only flow from the third party to the target call.</li>
</ul>
</td>
<td>OPTIONAL</td>
<td>duplex</td>
</tr>
<tr>
<td>media</td>
<td>
<p>Indicates the manner in which the server should negotiate media between the two parties. Must be one of the following values:</p>
<ul>
<li><strong>"bridge"</strong> - Instructs the server to bridge the parties media streams via its local media server.</li>
<li><strong>"direct"</strong> - Instructs the server to have the parties negotiate media directly with one another.</li>
</ul>
</td>
<td>OPTIONAL</td>
<td>bridge</td>
</tr>
<tr>
<td>call-uri</td>
<td>Indicates the 3rd party call URI to which the target call should be joined.</td>
<td>REQUIRED unless mixer-name is set. MUST NOT be set if mixer-name is set.</td>
<td></td>
</tr>
<tr>
<td>mixer-name</td>
<td>Indicates the mixer name to which the target call should be joined.</td>
<td>REQUIRED unless call-uri is set. MUST NOT be set if call-uri is set.</td>
<td></td>
</tr>
</table>
</section2>
<section2 topic='Unjoin Element' anchor='def-unjoin'>
<p>Instructs the server to unjoin the media streams of the call and the specified party.</p>
<p>The &lt;unjoin/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;unjoin/&gt; element are as follows.</p>
<table caption='Attributes of Unjoin Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>call-uri</td>
<td>Indicates the 3rd party call URI from which the target call should be unjoined.</td>
<td>OPTIONAL. MUST NOT be set if mixer-name is set.</td>
</tr>
<tr>
<td>mixer-name</td>
<td>Indicates the mixer name from which the target call should be unjoined.</td>
<td>OPTIONAL. MUST NOT be set if call-uri is set.</td>
</tr>
</table>
</section2>
<section2 topic='Joined Element' anchor='def-joined'>
<p>Indicates that the call was successfully joined to the specified party.</p>
<p>The &lt;joined/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;joined/&gt; element are as follows.</p>
<table caption='Attributes of Joined Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>call-uri</td>
<td>Indicates the 3rd party call URI to which the target call was joined.</td>
<td>REQUIRED unless mixer-name is set. MUST NOT be set if mixer-name is set.</td>
</tr>
<tr>
<td>mixer-name</td>
<td>Indicates the mixer name to which the target call was joined.</td>
<td>REQUIRED unless call-uri is set. MUST NOT be set if call-uri is set.</td>
</tr>
</table>
</section2>
<section2 topic='Unjoined Element' anchor='def-unjoined'>
<p>Indicates that the call ceased to be joined to the specified party.</p>
<p>The &lt;unjoined/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;unjoined/&gt; element are as follows.</p>
<table caption='Attributes of Unjoined Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>call-uri</td>
<td>Indicates the 3rd party call URI from which the target call was unjoined.</td>
<td>REQUIRED unless mixer-name is set. MUST NOT be set if mixer-name is set.</td>
</tr>
<tr>
<td>mixer-name</td>
<td>Indicates the mixer name from which the target call was unjoined.</td>
<td>REQUIRED unless call-uri is set. MUST NOT be set if call-uri is set.</td>
</tr>
</table>
</section2>
<section2 topic='Started Speaking Element' anchor='def-started-speaking'>
<p>Indicates that a call joined to a mixer with which the controlling party has an events subscription has activated a speech detector, providing its URI.</p>
<p>The &lt;started-speaking/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;started-speaking/&gt; element are as follows.</p>
<table caption='Attributes of Started Speaking Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>call-uri</td>
<td>Indicates the URI of the call which has triggered the speech detector.</td>
<td>REQUIRED</td>
</tr>
</table>
</section2>
<section2 topic='Stopped Speaking Element' anchor='def-stopped-speaking'>
<p>Indicates that a call joined to a mixer with which the controlling party has an events subscription has ceased activation of a speech detector, providing its URI.</p>
<p>The &lt;stopped-speaking/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;stopped-speaking/&gt; element are as follows.</p>
<table caption='Attributes of Stopped Speaking Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>call-uri</td>
<td>Indicates the URI of the call which has triggered the speech detector.</td>
<td>REQUIRED</td>
</tr>
</table>
</section2>
<section2 topic='Ref Element' anchor='def-ref'>
<p>Used to give the address of a newly created resource, either a call or a component.</p>
<p>The &lt;ref/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;ref/&gt; element are as follows.</p>
<table caption='Attributes of Ref Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>uri</td>
<td>Gives the URI of the new resource.</td>
<td>REQUIRED</td>
</tr>
</table>
</section2>
<section2 topic='Components' anchor='def-components'>
<section3 topic='Stop Element' anchor='def-components-stop'>
<p>Instructs a component to come to an end before it completes naturally.</p>
<p>The &lt;stop/&gt; element MUST be empty.</p>
<p>The &lt;stop/&gt; element has no attributes.</p>
</section3>
<section3 topic='Complete Element' anchor='def-components-complete'>
<p>Indicates that the component has come to an end and no further processing will occurr. Gives the reason for the termination.</p>
<p>The &lt;complete/&gt; element MUST contain exactly one child element, indicating the reason for the complete event being raised. The reason may be a <link url="#def-components-complete-reason">core complete reason</link> or a reason specific to a particular component.</p>
<p>The &lt;complete/&gt; element has no attributes.</p>
<section4 topic='Complete Reason Element' anchor='def-components-complete-reason'>
<p>The following are valid complete reason elements. They all MAY contain further component-specific metadata elements, but they do not have any attributes.</p>
<dl>
<di>
<dt>&lt;stop/&gt;</dt>
<dd>Indicates that the component came to an end because it was issued a stop command by the controlling party.</dd>
</di>
<di>
<dt>&lt;hangup/&gt;</dt>
<dd>Indicates that the component came to an end because the call ended.</dd>
</di>
<di>
<dt>&lt;error/&gt;</dt>
<dd>Indicates that the component came to an end because it encountered an error.</dd>
</di>
</dl>
</section4>
</section3>
<section3 topic='Media Output' anchor='def-component-output'>
<p>An output component is used to instruct the server to generate audible output to a call or mixer.</p>
<section4 topic='Output Element' anchor='def-component-output-output'>
<p>Instructs the server to begin an output component executing on the target call or mixer with the specified document and parameters.</p>
<p>The &lt;output/&gt; element MUST contain one or more <link url='#def-component-output-output-document'>&lt;document/&gt; elements</link>. A server MUST support the application/ssml+xml content type, but MAY additionally support others.</p>
<p>The attributes of the &lt;output/&gt; element are as follows.</p>
<table caption='Attributes of Output Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Default</th>
<th>Inclusion</th>
</tr>
<tr>
<td>start-offset</td>
<td>Indicates some offset through which the output should be skipped before rendering begins.</td>
<td>A positive integer in ms.</td>
<td>0</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>start-paused</td>
<td>Indicates wether or not the component should be started in a paused state to be resumed at a later time.</td>
<td>true|false</td>
<td>false</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>repeat-interval</td>
<td>Indicates the duration of silence that should space repeats of the rendered document.</td>
<td>A positive integer in ms.</td>
<td>0</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>repeat-times</td>
<td>Indicates the number of times the output should be played.</td>
<td>A positive integer or 0 to repeat forever.</td>
<td>1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>max-time</td>
<td>Indicates the maximum amount of time for which the output should be allowed to run before being terminated. Includes repeats.</td>
<td>A positive integer in ms or -1 to disable.</td>
<td>-1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>renderer</td>
<td>Indicates which media engine the server should use to render the Output. The server defines the possible values and falls back to the platform default if not specified.</td>
<td>An arbitrary string</td>
<td></td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>voice</td>
<td>The voice with which to speak the requested document</td>
<td>Any voice supported by the TTS engine.</td>
<td></td>
<td>OPTIONAL</td>
</tr>
</table>
<section5 topic='Document Element' anchor='def-component-output-output-document'>
<p>Presents a document for rendering by the output engine.</p>
<p>The &lt;document/&gt; element MUST have either a url attribute set OR a content type and a body, containing a document for output rendering enclosed within CDATA.</p>
<p>The attributes of the &lt;document/&gt; element are as follows.</p>
<table caption='Attributes of Document Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Default</th>
<th>Inclusion</th>
</tr>
<tr>
<td>url</td>
<td>Provides a URI at which the document is available.</td>
<td>Any valid URI scheme supported by the server (eg HTTP).</td>
<td>none</td>
<td>REQUIRED unless content-type and content are set</td>
</tr>
<tr>
<td>content-type</td>
<td>Indicates the content type of the document provided as CDATA.</td>
<td>A document content type token</td>
<td></td>
<td>REQUIRED unless url is set</td>
</tr>
</table>
</section5>
</section4>
<section4 topic='Pause Element' anchor='def-component-output-pause'>
<p>Instructs the server to pause the media output, but not terminate the component.</p>
<p>The &lt;pause/&gt; element MUST be empty.</p>
<p>The &lt;pause/&gt; element has no attributes.</p>
</section4>
<section4 topic='Resume Element' anchor='def-component-output-resume'>
<p>Instructs the server to continue rendering the output from the last pause marker.</p>
<p>The &lt;resume/&gt; element MUST be empty.</p>
<p>The &lt;resume/&gt; element has no attributes.</p>
</section4>
<section4 topic='SpeedUp Element' anchor='def-component-output-speedup'>
<p>Instructs the server to increase the rate of output by a unit amount.</p>
<p>The &lt;speed-up/&gt; element MUST be empty.</p>
<p>The &lt;speed-up/&gt; element has no attributes.</p>
</section4>
<section4 topic='SpeedDown Element' anchor='def-component-output-speeddown'>
<p>Instructs the server to decrease the rate of output by a unit amount.</p>
<p>The &lt;speed-down/&gt; element MUST be empty.</p>
<p>The &lt;speed-down/&gt; element has no attributes.</p>
</section4>
<section4 topic='VolumeUp Element' anchor='def-component-output-volumeup'>
<p>Instructs the server to increase the volume of output by a unit amount.</p>
<p>The &lt;volume-up/&gt; element MUST be empty.</p>
<p>The &lt;volume-up/&gt; element has no attributes.</p>
</section4>
<section4 topic='VolumeDown Element' anchor='def-component-output-volumedown'>
<p>Instructs the server to decrease the volume of output by a unit amount.</p>
<p>The &lt;volume-down/&gt; element MUST be empty.</p>
<p>The &lt;volume-down/&gt; element has no attributes.</p>
</section4>
<section4 topic='Seek Element' anchor='def-component-output-seek'>
<p>Instructs the server to move the play marker of the output forward or back in time before resuming output.</p>
<p>The &lt;seek/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;seek/&gt; element are as follows.</p>
<table caption='Attributes of Seek Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Inclusion</th>
</tr>
<tr>
<td>direction</td>
<td>Indicates the direction in time in which to move the play marker.</td>
<td>forward|back</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>amount</td>
<td>Indicates the duration by which to move the play marker.</td>
<td>A positive integer, in ms.</td>
<td>REQUIRED</td>
</tr>
</table>
</section4>
<section4 topic='Finish Element' anchor='def-component-output-finish'>
<p>Indicates that the output component came to an end as a result of reaching the end of the document to be rendered.</p>
<p>The &lt;finish/&gt; element MUST be empty.</p>
<p>The &lt;finish/&gt; element has no attributes.</p>
</section4>
<section4 topic='MaxTime Element' anchor='def-component-output-maxtime'>
<p>Indicates that the output component came to an end due to the maximum time limit being reached.</p>
<p>The &lt;max-time/&gt; element MUST be empty.</p>
<p>The &lt;max-time/&gt; element has no attributes.</p>
</section4>
</section3>
<section3 topic='Media Input' anchor='def-component-input'>
<p>An input component is used to instruct the server to gather media input from a call or mixer, using either DTMF or ASR.</p>
<section4 topic='Input Element' anchor='def-component-input-input'>
<p>Instructs the server to begin an input detector of the specified mode, with certain attributes, governed by the rules provided in one or more grammar documents.</p>
<p>The &lt;input/&gt; element MUST contain one or more <link url='#def-comoponent-input-input-grammar'>&lt;grammar/&gt; elements</link>.</p>
<p>The attributes of the &lt;input/&gt; element are as follows.</p>
<table caption='Attributes of Input Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Default</th>
<th>Inclusion</th>
</tr>
<tr>
<td>mode</td>
<td>The method by which to collect input.</td>
<td>any|dtmf|voice|cpa</td>
<td>any</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>terminator</td>
<td>Indicates a terminator token which, when encountered, should cause the input detection to cease.</td>
<td>A token string</td>
<td>none</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>recognizer</td>
<td>Indicates the name of the particular input processor to be engaged, used only for routing purposes (eg to choose which MRCP profile to invoke).</td>
<td>A token string</td>
<td>none</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>language</td>
<td>Specifies the recognition language to the recognizer.</td>
<td>Any valid ISO 6393 language code</td>
<td>en-US</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>initial-timeout</td>
<td>Indicates the amount of time preceding input which may expire before a timeout is triggered.</td>
<td>Any positive integer in miliseconds, or -1 to disable.</td>
<td>-1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>inter-digit-timeout</td>
<td>Indicates (in the case of DTMF input) the amount of time between input digits which may expire before a timeout is triggered.</td>
<td>Any positive integer in miliseconds, or -1 to disable.</td>
<td>-1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>recognition-timeout</td>
<td>Indicates the time (in milliseconds) for speech input, after speech has begun, to return a Match before triggering a Nomatch completion.</td>
<td>Integer value from 0 to MAXTIMEOUT, where MAXTIMEOUT is implementation specific, or -1 to disable.</td>
<td>-1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>sensitivity</td>
<td>Indicates how sensitive the interpreter should be to loud versus quiet input. Higher values represent greater sensitivity.</td>
<td>A decimal value between 0 and 1.</td>
<td>0.5</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>min-confidence</td>
<td>Indicates the confidence threshold, below which a match is to be considered unreliable.</td>
<td>A decimal value between 0 and 1.</td>
<td>0</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>max-silence</td>
<td>Indicates the maximum period of silence which may be encountered during input gathering before a timeout is triggered.</td>
<td>Any positive integer in miliseconds, or -1 to disable.</td>
<td>-1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>match-content-type</td>
<td>Indicates the required response document format.</td>
<td>Must support at least application/nlsml+xml, but may support others such as application/emma+xml.</td>
<td>application/nlsml+xml</td>
<td>OPTIONAL</td>
</tr>
</table>
<section5 topic='Grammar Element' anchor='def-component-input-input-grammar'>
<p>Provides the grammar document by which the input detection should be governed.</p>
<p>The &lt;grammar/&gt; element MUST have either a url attribute set OR a content type and a body.</p>
<p>The attributes of the &lt;grammar/&gt; element are as follows.</p>
<table caption='Attributes of Grammar Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Default</th>
<th>Inclusion</th>
</tr>
<tr>
<td>url</td>
<td>Provides a URI at which the grammar document is available.</td>
<td>Any valid URI scheme supported by the server (eg HTTP).</td>
<td>none</td>
<td>REQUIRED unless content-type and content are set</td>
</tr>
<tr>
<td>content-type</td>
<td>Indicates the content type of the grammar document provided as CDATA.</td>
<td>A grammar content type token</td>
<td>none</td>
<td>REQUIRED unless url is set</td>
</tr>
</table>
</section5>
</section4>
<section4 topic='Match' anchor='def-component-input-match'>
<p>Indicates that the component came to an end due to one of its grammars matching the received input.</p>
<p>The &lt;match/&gt; element MUST contain a valid response document within CDATA.</p>
<p>The attributes of the &lt;match/&gt; element are as follows.</p>
<table caption='Attributes of Match Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Default</th>
<th>Inclusion</th>
</tr>
<tr>
<td>content-type</td>
<td>Indicates the content type of the result document provided as CDATA.</td>
<td>A result document content type token</td>
<td>application/nlsml+xml</td>
<td>REQUIRED</td>
</tr>
</table>
</section4>
<section4 topic='Noinput' anchor='def-component-input-noinput'>
<p>Indicates that the component came to an end because a timeout was triggered before input was received.</p>
<p>The &lt;noinput/&gt; element MUST be empty.</p>
<p>The &lt;noinput/&gt; element has no attributes.</p>
</section4>
<section4 topic='Nomatch' anchor='def-component-input-nomatch'>
<p>Indicates that the component came to an end because input was received which did not match any of the specified grammars.</p>
<p>The &lt;nomatch/&gt; element MUST be empty.</p>
<p>The &lt;nomatch/&gt; element has no attributes.</p>
</section4>
</section3>
<section3 topic='Prompt' anchor='def-component-prompt'>
<p>An prompt component is a mixture of audio output and input, and is used to link the lifecycle of both such input may interrupt output via an arbitrary grammar.</p>
<section4 topic='Prompt Element' anchor='def-component-input-input'>
<p>Instructs the server to begin an input detector of the specified mode, with certain attributes, governed by the rules provided in one or more grammar documents, while simultaneously rendering output.</p>
<p>The &lt;prompt/&gt; element MUST contain an <link url='#def-comoponent-input-input'>&lt;input/&gt; element</link> and an <link url='#def-comoponent-output-output'>&lt;output/&gt; element</link>.</p>
<p>The attributes of the &lt;prompt/&gt; element are as follows.</p>
<table caption='Attributes of Prompt Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Default</th>
<th>Inclusion</th>
</tr>
<tr>
<td>barge-in</td>
<td>Whether or not the input detector is permitted to interrupt the output.</td>
<td>true|false</td>
<td>true</td>
<td>OPTIONAL</td>
</tr>
</table>
</section4>
<section4 topic='Input Timers Started Element' anchor='def-component-prompt-input-timers-started'>
<p>Indicates that the component's input timers have started.</p>
<p>The &lt;input-timers-started/&gt; element MUST be empty.</p>
<p>The &lt;input-timers-started/&gt; element has no attributes.</p>
</section4>
</section3>
<section3 topic='Media Recording' anchor='def-component-record'>
<p>A record component is used to instruct the server to record audible or visual media for temporary or permanent storage.</p>
<section4 topic='Record Element' anchor='def-component-record-record'>
<p>Instructs the server to begin recording input to the call to a file.</p>
<p>The &lt;record/&gt; element MAY contain one or more <link url='#def-comoponent-record-record-hint'>&lt;hint/&gt; elements</link>.</p>
<p>The attributes of the &lt;record/&gt; element are as follows.</p>
<table caption='Attributes of Record Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Default</th>
<th>Inclusion</th>
</tr>
<tr>
<td>format</td>
<td>File format used during recording.</td>
<td>A valid format token, such as 'mp3', 'wav', 'h264'. Implementation specific.</td>
<td>wav</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>start-beep</td>
<td>Indicates whether subsequent record will be preceded with a beep.</td>
<td>true|false</td>
<td>false</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>stop-beep</td>
<td>Indicates whether subsequent record stop will be preceded with a beep.</td>
<td>true|false</td>
<td>false</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>start-paused</td>
<td>Whether subsequent record will start in PAUSE mode.</td>
<td>true|false</td>
<td>false</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>max-duration</td>
<td>Indicates the maximum duration for the recording.</td>
<td>Any positive integer in miliseconds, or -1 to disable.</td>
<td>-1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>initial-timeout</td>
<td>Controls how long the recognizer should wait after the end of the prompt for the caller to speak before sending a Recorder event.</td>
<td>Any positive integer in miliseconds, or -1 to disable.</td>
<td>-1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>final-timeout</td>
<td>Controls the length of a period of silence after callers have spoken to conclude they finished.</td>
<td>Any positive integer in miliseconds, or -1 to disable.</td>
<td>-1</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>direction</td>
<td>
<p>Indicates the direction of the call to record, meaning which call legs(s) are included in the resulting file, in case the call is joined to another or a mixer.</p>
</td>
<td>
<ul>
<li><strong>"duplex"</strong> - Records both sent and received audio.</li>
<li><strong>"send"</strong> - Indicates that only the audio sent from the caller is to be recorded. Not supported when Record is executed against a mixer.</li>
<li><strong>"recv"</strong> - Indicates that only and all audio received by the caller is recorded.</li>
</ul>
</td>
<td>duplex</td>
<td>OPTIONAL</td>
</tr>
<tr>
<td>mix</td>
<td>Whether all channels (call legs) should be mixed into a single recording channel.</td>
<td>true|false</td>
<td>false</td>
<td>OPTIONAL</td>
</tr>
</table>
<section5 topic='Hint Element' anchor='def-component-record-record-hint'>
<p>Optional format-specific encoding hint</p>
<p>The &lt;hint/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;hint/&gt; element are as follows.</p>
<table caption='Attributes of Hint Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Inclusion</th>
</tr>
<tr>
<td>name</td>
<td>The name of the hint value as expected by the recorder.</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>value</td>
<td>The value of the hint provided.</td>
<td>REQUIRED</td>
</tr>
</table>
</section5>
</section4>
<section4 topic='Pause Element' anchor='def-component-record-pause'>
<p>Instructs the server to cease recording input but to leave the destination open for appending to permit resumption from the same point.</p>
<p>The &lt;pause/&gt; element MUST be empty.</p>
<p>The &lt;pause/&gt; element has no attributes.</p>
</section4>
<section4 topic='Resume Element' anchor='def-component-record-resume'>
<p>Instructs the server to continue recording input, appending to the same destination.</p>
<p>The &lt;resume/&gt; element MUST be empty.</p>
<p>The &lt;resume/&gt; element has no attributes.</p>
</section4>
<section4 topic='Recording Element' anchor='def-component-record-recording'>
<p>Provides the result of a recording, as a reference to its location.</p>
<p>The &lt;recording/&gt; element MUST be empty.</p>
<p>The attributes of the &lt;recording/&gt; element are as follows.</p>
<table caption='Attributes of Recording Element'>
<tr>
<th>Attribute</th>
<th>Definition</th>
<th>Possible Values</th>
<th>Inclusion</th>
</tr>
<tr>
<td>uri</td>
<td>Indicates the URI at which the recording is made available.</td>
<td>A valid URI</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>duration</td>
<td>Indicates the duration of the completed recording.</td>
<td>A positive integer in milliseconds.</td>
<td>REQUIRED</td>
</tr>
<tr>
<td>size</td>
<td>Indicates the filesize of the completed recording.</td>
<td>A positive integer in bytes.</td>
<td>REQUIRED</td>
</tr>
</table>
</section4>
<section4 topic='Max Duration Element' anchor='def-component-record-max-duration'>
<p>Indicates that the component came to an end due to the max duration being reached.</p>
<p>The &lt;max-duration/&gt; element MUST be empty.</p>
<p>The &lt;max-duration/&gt; element has no attributes.</p>
</section4>
<section4 topic='Initial Timeout Element' anchor='def-component-record-initial-timeout'>
<p>Indicates that the component came to an end due to no input being detected before the initial-timeout.</p>
<p>The &lt;initial-timeout/&gt; element MUST be empty.</p>
<p>The &lt;initial-timeout/&gt; element has no attributes.</p>
</section4>
<section4 topic='Final Timeout Element' anchor='def-component-record-final-timeout'>
<p>Indicates that the component came to an end because no input had been detected for the final timeout duration.</p>
<p>The &lt;final-timeout/&gt; element MUST be empty.</p>
<p>The &lt;final-timeout/&gt; element has no attributes.</p>
</section4>
</section3>
</section2>
</section1>
<section1 topic='Determining Support' anchor='support'>
<p>If an entity supports Rayo, it MUST advertise that fact by returning a feature of "urn:xmpp:rayo:1" &VNOTE; in response to a &xep0030; information request. The response MUST also include features for the application formats and transport methods supported by the responding entity, as described in the relevant specifications.</p>
<example caption="Service Discovery Information Request - Client to Server"><![CDATA[
<iq from='kingclaudius@shakespeare.lit/castle'
id='disco1'
to='call.rayo.org'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<example caption="Service Discovery Information Response - Client to Server"><![CDATA[
<iq from='call.rayo.org'
id='disco1'
to='kingclaudius@shakespeare.lit/castle'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<feature var='urn:xmpp:rayo:1'/>
</query>
</iq>
]]></example>
<example caption="Service Discovery Information Request - Server to Client"><![CDATA[
<iq from='call.rayo.org'
id='disco1'
to='laertes@shakespeare.lit/castle'
type='get'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>
<example caption="Service Discovery Information Response - Server to Client"><![CDATA[
<iq from='laertes@shakespeare.lit/castle'
id='disco1'
to='call.rayo.org'
type='result'>
<query xmlns='http://jabber.org/protocol/disco#info'>
<feature var='urn:xmpp:rayo:client:1'/>
</query>
</iq>
]]></example>
<p>In order for an application to determine whether an entity supports this protocol, where possible it SHOULD use the dynamic, presence-based profile of service discovery defined in &xep0115;. However, if an application has not received entity capabilities information from an entity, it SHOULD use explicit service discovery instead.</p>
</section1>
<section1 topic='Extending Rayo' anchor='extensions'>
<p>Rayo is a protocol designed for extensibility. Rayo implementations and deployments have great flexibility in the way they map the Rayo protocol to their underlying transport and media layers, and the functionality they provide around the Rayo interface to the system.</p>
<p>Further commands and components may also be added to the Rayo protocol in order to extend its capabilities. Such extensions should be submitted to the XSF as ProtoXEPs and use namespaces aligning with the core component namespaces.</p>
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
<p>A server MUST document any cases where its behaviour differs from that in this specification (such as lack of support for particular options/components/etc) and return an error whenever a command is not understood. A server MUST NOT silently ignore any instructions.</p>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<section2 topic='Denial of Service' anchor='security-dos'>
<p>Rayo sessions can be resource-intensive. Therefore, it is possible to launch a denial-of-service attack against an entity by burdening it with too many Rayo sessions. Care must be taken to accept sessions only from known entities and only if the entity's device is able to process such sessions.</p>
</section2>
<section2 topic='Communication Through Gateways' anchor='security-gateways'>
<p>Rayo communications can be enabled through gateways to non-XMPP networks, whose security characteristics can be quite different from those of XMPP networks. For example, on some SIP networks authentication is optional and "from" addresses can be easily forged. Care must be taken in communicating through such gateways.</p>
</section2>
<section2 topic='Information Exposure' anchor='security-info'>
<p>Mere negotiation of a Rayo session can expose sensitive information about the parties (e.g. IP addresses). Care must be taken in communicating such information, and end-to-end encryption should be used if the parties do not trust the intermediate servers or gateways.</p>
</section2>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with &IANA;.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<section2 topic='Protocol Namespaces' anchor='registrar-ns'>
<p>This specification defines the following XML namespaces:</p>
<ul>
<li>urn:xmpp:rayo:1</li>
<li>urn:xmpp:rayo:client:1</li>
<li>urn:xmpp:rayo:call:1</li>
<li>urn:xmpp:rayo:mixer:1</li>
<li>urn:xmpp:rayo:ext:1</li>
<li>urn:xmpp:rayo:ext:complete:1</li>
<li>urn:xmpp:rayo:output:1</li>
<li>urn:xmpp:rayo:output:complete:1</li>
<li>urn:xmpp:rayo:input:1</li>
<li>urn:xmpp:rayo:input:complete:1</li>
<li>urn:xmpp:rayo:prompt:1</li>
<li>urn:xmpp:rayo:record:1</li>
<li>urn:xmpp:rayo:record:complete:1</li>
</ul>
<p>The &REGISTRAR; includes the foregoing namespaces in its registry at &NAMESPACES;, as governed by &xep0053;.</p>
</section2>
<section2 topic='Namespace Versioning' anchor='registrar-versioning'>
<p>If the protocol defined in this specification undergoes a major revision that is not fully backward-compatible with an older version, or that contains significant new features, the XMPP Registrar shall increment the protocol version number found at the end of the XML namespaces defined herein, as described in Section 4 of <cite>XEP-0053</cite>.</p>
</section2>
<section2 topic='Rayo Components Registry' anchor='registrar-components'>
<p>The XMPP Registrar maintains a registry of Rayo components. All component registrations with the exception of those defined above shall be defined in separate specifications (not in this document). Components defined within the XEP series MUST be registered with the XMPP Registrar, resulting in protocol URNs of the form "urn:xmpp:rayo:component_name:X" (where "component_name" is the registered name of the component and "X" is a non-negative integer).</p>
&REGPROCESS;
<code><![CDATA[
<component>
<name>The name of the component.</name>
<desc>A natural-language summary of the component.</desc>
<doc>The document in which the component is specified.</doc>
</component>
]]></code>
</section2>
</section1>
<section1 topic='XML Schema' anchor='schema'>
<section2 topic='Rayo' anchor='schema-rayo'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:1"
xmlns:tns="urn:xmpp:rayo:1"
elementFormDefault="qualified">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<!-- Header elements -->
<complexType name="headerType">
<attribute name="name" type="token" use="required">
<annotation>
<documentation>
A token giving the name by which the header may be known.
</documentation>
</annotation>
</attribute>
<attribute name="value" type="string" use="required">
<annotation>
<documentation>
The string value of the named header.
</documentation>
</annotation>
</attribute>
</complexType>
<!-- Offer Event -->
<element name="offer">
<annotation>
<documentation>
Informs the recipient that a new call is available for control and invites it to take control using progress commands below.
</documentation>
</annotation>
<complexType>
<attribute name="to" type="anyURI" use="required">
<annotation>
<documentation>
The target URI for the call. May be a tel URI, SIP URI, a JID (for Jingle) or some other platform-specific addressing mechanism.
</documentation>
</annotation>
</attribute>
<attribute name="from" type="anyURI" use="optional">
<annotation>
<documentation>
The caller ID URI for the call. May be a tel URI, SIP URI, a JID (for Jingle) or some other platform-specific addressing mechanism.
</documentation>
</annotation>
</attribute>
<sequence>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>
Set of header variables sent by the originating party (eg SIP INVITE headers).
</documentation>
</annotation>
</element>
</sequence>
</complexType>
</element>
<complexType name="callProgressType">
<sequence>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<!-- Ringing Event -->
<element name="ringing" type="tns:callProgressType">
<annotation>
<documentation>
Indication that an outbound call has begun ringing, or accepted by the remote party.
</documentation>
</annotation>
</element>
<!-- Answered Event -->
<element name="answered" type="tns:callProgressType">
<annotation>
<documentation>
Indication that an outbound call has been answered and that the 3rd party negotiation has completed. At this point, the media stream should be open.
</documentation>
</annotation>
</element>
<complexType name="endReasonType">
<attribute name="platform-code" type="string" use="optional">
<annotation>
<documentation>
A platform-specific end code. This could be a SIP code, ITU-T Q.850 or some other system. The code may be an arbitrary string.
</documentation>
</annotation>
</attribute>
</complexType>
<!-- End Event -->
<element name="end">
<annotation>
<documentation>
Indication that the call has come to an end, giving the reason.
</documentation>
</annotation>
<complexType>
<sequence>
<choice>
<element name="hungup" type="tns:endReasonType">
<annotation>
<documentation>
Indication that the call ended due to a normal hangup by the remote party.
</documentation>
</annotation>
</element>
<element name="hangup-command" type="tns:endReasonType">
<annotation>
<documentation>
Indication that the call ended due to a normal hangup triggered by a hangup command.
</documentation>
</annotation>
</element>
<element name="timeout" type="tns:endReasonType">
<annotation>
<documentation>
Indication that the call ended due to a timeout in contacting the remote party.
</documentation>
</annotation>
</element>
<element name="busy" type="tns:endReasonType">
<annotation>
<documentation>
Indication that the call ended due to being rejected by the remote party subsequent to being accepted.
</documentation>
</annotation>
</element>
<element name="rejected" type="tns:endReasonType">
<annotation>
<documentation>
Indication that the call ended due to being rejected by the remote party before being accepted.
</documentation>
</annotation>
</element>
<element name="error" type="tns:endReasonType">
<annotation>
<documentation>
Indication that the call ended due to a system error.
</documentation>
</annotation>
</element>
</choice>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>
Set of header variables sent by the remote party along with the indication of the call ending.
</documentation>
</annotation>
</element>
</sequence>
</complexType>
</element>
<!-- Accept Command -->
<element name="accept">
<annotation>
<documentation>
Instructs the server to send notification to the calling party that the call will be dealt with and that ringing may begin.
</documentation>
</annotation>
<complexType>
<sequence>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<!-- Answer Command -->
<element name="answer">
<annotation>
<documentation>
Instructs the server to pick up an incoming call and connect the media stream.
</documentation>
</annotation>
<complexType>
<sequence>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<!-- Redirect Command -->
<element name="redirect">
<annotation>
<documentation>
Instructs the calling party that the call will not be accepted and that instead it should try to call the URI indicated in the command.
</documentation>
</annotation>
<complexType>
<attribute name="to" type="anyURI" use="required">
<annotation>
<documentation>
The new target URI for the call to be redirected to.
</documentation>
</annotation>
</attribute>
<sequence>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<!-- Reject Command -->
<element name="reject">
<annotation>
<documentation>
Instructs the server to reject the call with a given reason.
</documentation>
</annotation>
<complexType mixed="true">
<sequence>
<choice>
<element name="decline" type="tns:empty">
<annotation>
<documentation>
Indicates that the controlling party refused the call for an unspecified reason, such as access control.
</documentation>
</annotation>
</element>
<element name="busy" type="tns:empty">
<annotation>
<documentation>
Indicates that the controlling party refused the call due to excess load.
</documentation>
</annotation>
</element>
<element name="error" type="tns:empty">
<annotation>
<documentation>
Indicates that the controlling party refused the call because some error occurred.
</documentation>
</annotation>
</element>
</choice>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<!-- Hangup Command -->
<element name="hangup">
<annotation>
<documentation>
Instructs the server to bring the call to an end naturally.
</documentation>
</annotation>
<complexType>
<sequence>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<!-- Dial Command -->
<element name="dial">
<annotation>
<documentation>
Instructs the server to create a new call and surrender control of it to the requesting party.
</documentation>
</annotation>
<complexType>
<attribute name="to" type="anyURI" use="required">
<annotation>
<documentation>
Indicates the party to whom the call should be directed.
</documentation>
</annotation>
</attribute>
<attribute name="from" type="anyURI" use="optional">
<annotation>
<documentation>
Indicates the caller ID with which the call should appear to originate.
</documentation>
</annotation>
</attribute>
<attribute name="uri" type="anyURI" use="optional">
<annotation>
<documentation>
Indicates the URI at which the client wishes the call to be presented.
</documentation>
</annotation>
</attribute>
<attribute name="timeout" type="tns:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Indicates the maximum time allowed for a response to be provided by the remote party before the call should be considered to have come to an end.
</documentation>
</annotation>
</attribute>
<sequence>
<element name="header" type="tns:headerType" minOccurs="0" maxOccurs="unbounded" />
<element name="join" type="tns:joinCommandType" minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>
Instructs the server to join the new call in the indicated manner rather than the default (join to the local media server).
</documentation>
</annotation>
</element>
</sequence>
</complexType>
</element>
<!-- Join Command -->
<element name="join">
<annotation>
<documentation>
Instructs the server to join the media streams of the call and the specified party, given direction and media negotiation parameters.
</documentation>
</annotation>
<complexType>
<complexContent>
<extension base="tns:joinType">
<attribute name="direction" use="optional" default="duplex">
<annotation>
<documentation>
Indicates the direction in which the media should flow between the call and the 3rd party.
</documentation>
</annotation>
<simpleType>
<restriction base="token">
<enumeration value="duplex">
<annotation>
<documentation>
Indicates that media should flow in both directions between the parties.
</documentation>
</annotation>
</enumeration>
<enumeration value="send">
<annotation>
<documentation>
Indicates that media should only flow from the target call to the third party.
</documentation>
</annotation>
</enumeration>
<enumeration value="recv">
<annotation>
<documentation>
Indicates that media should only flow from the third party to the target call.
</documentation>
</annotation>
</enumeration>
</restriction>
</simpleType>
</attribute>
<attribute name="media" use="optional" default="bridge">
<annotation>
<documentation>
Indicates the manner in which the server should negotiate media between the two parties.
</documentation>
</annotation>
<simpleType>
<restriction base="token">
<enumeration value="bridge">
<annotation>
<documentation>
Instructs the server to bridge the parties media streams via its local media server.
</documentation>
</annotation>
</enumeration>
<enumeration value="direct">
<annotation>
<documentation>
Instructs the server to have the parties negotiate media directly with one another.
</documentation>
</annotation>
</enumeration>
</restriction>
</simpleType>
</attribute>
</extension>
</complexContent>
</complexType>
</element>
<!-- Unjoin Command -->
<element name="unjoin" type="tns:joinType">
<annotation>
<documentation>
Instructs the server to unjoin the media streams of the call and the specified party.
</documentation>
</annotation>
</element>
<!-- Joined Event -->
<element name="joined" type="tns:joinType">
<annotation>
<documentation>
Indicates that the call was successfully joined to the specified party.
</documentation>
</annotation>
</element>
<!-- Unjoined Event -->
<element name="unjoined" type="tns:joinType">
<annotation>
<documentation>
Indicates that the call ceased to be joined to the specified party.
</documentation>
</annotation>
</element>
<complexType name="joinType">
<attribute name="call-uri" type="anyURI" use="optional">
<annotation>
<documentation>
Indicates the 3rd party call URI to which the target call should be joined. May not be set if the mixer-name attribute is set.
</documentation>
</annotation>
</attribute>
<attribute name="mixer-name" type="token" use="optional">
<annotation>
<documentation>
Indicates the mixer name to which the target call should be joined. May not be set if the call-id attribute is set.
</documentation>
</annotation>
</attribute>
</complexType>
<!-- Started Speaking Event -->
<element name="started-speaking" type="tns:activeSpeakerType">
<annotation>
<documentation>
Indicates that a call joined to a mixer with which the controlling party has an events subscription has activated a speech detector, providing its ID.
</documentation>
</annotation>
</element>
<!-- Stopped Speaking Event -->
<element name="stopped-speaking" type="tns:activeSpeakerType">
<annotation>
<documentation>
Indicates that a call joined to a mixer with which the controlling party has an events subscription has ceased activation of a speech detector, providing its ID.
</documentation>
</annotation>
</element>
<complexType name="activeSpeakerType">
<attribute name="call-uri" type="anyURI" use="required">
<annotation>
<documentation>
Indicates the URI of the call which has triggered the speech detector.
</documentation>
</annotation>
</attribute>
</complexType>
<!-- Resource Reference -->
<element name="ref">
<annotation>
<documentation>
Used to give an indication of the identity of a newly created resource, either a call or a component.
</documentation>
</annotation>
<complexType>
<attribute name="uri" type="anyURI" use="required">
<annotation>
<documentation>
Gives the URI of the new resource.
</documentation>
</annotation>
</attribute>
</complexType>
</element>
<!-- Utility: Empty Type -->
<simpleType name="empty">
<restriction base="string">
<enumeration value='' />
</restriction>
</simpleType>
<!-- Utility: Duration Type -->
<simpleType name="durationType">
<restriction base="long">
<annotation>
<documentation>
Value is a duration in milleseconds
</documentation>
</annotation>
</restriction>
</simpleType>
<!-- Utility: Timeout Type -->
<simpleType name="timeoutType">
<annotation>
<documentation>
A value of -1 indicates no timeout
</documentation>
</annotation>
<restriction base="tns:durationType">
<minInclusive value="-1"/>
</restriction>
</simpleType>
<!-- Utility: Fraction Decimal Type -->
<simpleType name="fractionDecimalType">
<restriction base="decimal">
<minInclusive value="0"/>
<maxInclusive value="1"/>
</restriction>
</simpleType>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Ext' anchor='schema-rayo-ext'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:ext:1"
xmlns:tns="urn:xmpp:rayo:ext:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<!-- Stop Command -->
<element name="stop" type="core:empty">
<annotation>
<documentation>
Instructs a component to come to an end before it completes naturally.
</documentation>
</annotation>
</element>
<!-- Complete Event -->
<element name="complete">
<annotation>
<documentation>
Indicates that the component has come to an end and no further processing will occurr. Gives the reason for the termination.
</documentation>
</annotation>
<complexType mixed="true">
<choice minOccurs="1" maxOccurs="1">
<any>
<annotation>
<documentation>
The reason for component termination. May be either one of the core termination reasons (stop, hangup, error) or a component specific reason.
</documentation>
</annotation>
</any>
</choice>
<sequence>
<any minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>
May be any component specific metadata elements, such as <recording>.
</documentation>
</annotation>
</any>
</sequence>
</complexType>
</element>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Ext Complete' anchor='schema-rayo-ext-complete'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:ext:complete:1"
xmlns:tns="urn:xmpp:rayo:ext:complete:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<!-- Complete due to a <stop/> command -->
<element name="stop" type="core:empty">
<annotation>
<documentation>
Indicates that the component came to an end because it was issued a stop command by the controlling party.
</documentation>
</annotation>
</element>
<!-- Complete due to a hangup -->
<element name="hangup" type="core:empty">
<annotation>
<documentation>
Indicates that the component came to an end because the call ended.
</documentation>
</annotation>
</element>
<!-- Complete due to a system error -->
<element name="error" type="string">
<annotation>
<documentation>
Indicates that the component came to an end because it encountered an error.
</documentation>
</annotation>
</element>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Output' anchor='schema-rayo-output'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:output:1"
xmlns:tns="urn:xmpp:rayo:output:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<complexType name="documentType">
<simpleContent>
<attribute name="url" type="anyURI" use="optional">
<annotation>
<documentation>
Provides a URI at which the document is available. Must not be provided if the content-type attribute is set or the element contains a document as CDATA.
</documentation>
</annotation>
</attribute>
<attribute name="content-type" type="string" use="optional">
<annotation>
<documentation>
Indicates the content type of the document provided as CDATA. Must not be set if the url attribute is set.
</documentation>
</annotation>
</attribute>
<restriction base="CDATA" />
</simpleContent>
</complexType>
<!-- Main output command -->
<element name="output">
<annotation>
<documentation>
Instructs the server to begin an output component executing on the target call or mixer with the specified document and parameters.
</documentation>
</annotation>
<complexType>
<attribute name="start-offset" type="core:durationType" use="optional" default="0">
<annotation>
<documentation>
Indicates some offset through which the output should be skipped before rendering begins.
</documentation>
</annotation>
</attribute>
<attribute name="start-paused" type="boolean" use="optional" default="false">
<annotation>
<documentation>
Indicates wether or not the component should be started in a paused state to be resumed at a later time.
</documentation>
</annotation>
</attribute>
<attribute name="repeat-interval" type="core:durationType" use="optional" default="0">
<annotation>
<documentation>
Indicates the duration of silence that should space repeats of the rendered document.
</documentation>
</annotation>
</attribute>
<attribute name="repeat-times" type="nonNegativeInteger" use="optional" default="1">
<annotation>
<documentation>
Indicates the number of times the output should be played.
</documentation>
</annotation>
</attribute>
<attribute name="max-time" type="core:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Indicates the maximum amount of time for which the output should be allowed to run before being terminated. Includes repeats.
</documentation>
</annotation>
</attribute>
<attribute name="renderer" type="string" use="optional">
<annotation>
<documentation>
Indicates which media engine the server should use to render the Output.
</documentation>
</annotation>
</attribute>
<attribute name="voice" type="string" use="optional">
<annotation>
<documentation>
The voice with which to speak the requested document.
</documentation>
</annotation>
</attribute>
<sequence>
<element name="document" type="tns:documentType" minOccurs="1" maxOccurs="unbounded">
<annotation>
<documentation>
Provides the document for rendering.
</documentation>
</annotation>
</element>
</sequence>
</complexType>
</element>
<!-- Pause command -->
<element name="pause" type="core:empty">
<annotation>
<documentation>
Instructs the server to cease rendering output at the current marker and permit resumption from the same point.
</documentation>
</annotation>
</element>
<!-- Resume command -->
<element name="resume" type="core:empty">
<annotation>
<documentation>
Instructs the server to continue rendering the output from the last pause marker.
</documentation>
</annotation>
</element>
<!-- Speed up command -->
<element name="speed-up" type="core:empty">
<annotation>
<documentation>
Instructs the server to increase the rate of output by a unit amount.
</documentation>
</annotation>
</element>
<!-- Speed down command -->
<element name="speed-down" type="core:empty">
<annotation>
<documentation>
Instructs the server to decrease the rate of output by a unit amount.
</documentation>
</annotation>
</element>
<!-- Volume up command -->
<element name="volume-up" type="core:empty">
<annotation>
<documentation>
Instructs the server to increase the volume of output by a unit amount.
</documentation>
</annotation>
</element>
<!-- Volume down command -->
<element name="volume-down" type="core:empty">
<annotation>
<documentation>
Instructs the server to decrease the volume of output by a unit amount.
</documentation>
</annotation>
</element>
<!-- Seek command -->
<element name="seek">
<annotation>
<documentation>
Instructs the server to move the play marker of the output forward or back in time before resuming output.
</documentation>
</annotation>
<complexType>
<attribute name="direction" type="token" use="required">
<annotation>
<documentation>
Indicates the direction in time in which to move the play marker.
</documentation>
</annotation>
<simpleType>
<restriction base="token">
<enumeration value="forward"/>
<enumeration value="back"/>
</restriction>
</simpleType>
</attribute>
<attribute name="amount" use="required">
<annotation>
<documentation>
Indicates the duration by which to move the play marker.
</documentation>
</annotation>
<simpleType>
<restriction base="core:durationType">
<minInclusive value="0"/>
</restriction>
</simpleType>
</attribute>
</complexType>
</element>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Output Complete' anchor='schema-rayo-output-complete'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:output:complete:1"
xmlns:tns="urn:xmpp:rayo:output:complete:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<!-- Finish reason -->
<element name="finish" type="core:empty">
<annotation>
<documentation>
Indicates that the output component came to an end as a result of reaching the end of the document to be rendered.
</documentation>
</annotation>
</element>
<!-- MaxTime reason -->
<element name="max-time" type="core:empty">
<annotation>
<documentation>
Indicates that the output component came to an end due to the maximum time limit being reached.
</documentation>
</annotation>
</element>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Input' anchor='schema-rayo-input'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:input:1"
xmlns:tns="urn:xmpp:rayo:input:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<complexType name="grammarType">
<simpleContent>
<attribute name="url" type="anyURI" use="optional">
<annotation>
<documentation>
Provides a URI at which the grammar document is available. Must not be provided if the content-type attribute is set or the element contains a grammar document as CDATA.
</documentation>
</annotation>
</attribute>
<attribute name="content-type" type="string" use="optional">
<annotation>
<documentation>
Indicates the content type of the grammar document provided as CDATA. Must not be set if the url attribute is set.
</documentation>
</annotation>
</attribute>
<restriction base="CDATA" />
</simpleContent>
</complexType>
<!-- Main Input command -->
<element name="input">
<annotation>
<documentation>
Instructs the server to begin an input detector of the specified mode, with certain attributes, governed by the rules provided in one or more grammar documents.
</documentation>
</annotation>
<complexType>
<simpleContent>
<attribute name="mode" use="optional" default="dtmf">
<annotation>
<documentation>
The method by which to collect input.
</documentation>
</annotation>
<simpleType>
<restriction base="token">
<enumeration value="any" />
<enumeration value="voice" />
<enumeration value="dtmf" />
<enumeration value="cpa" />
</restriction>
</simpleType>
</attribute>
<attribute name="terminator" type="token" use="optional" default="">
<annotation>
<documentation>
Indicates a terminator token which, when encountered, should cause the input detection to cease.
</documentation>
</annotation>
</attribute>
<attribute name="recognizer" type="token" use="optional" default="">
<annotation>
<documentation>
Indicates the name of the particular input processor to be engaged, used only for routing purposes (eg to choose which MRCP profile to invoke).
</documentation>
</annotation>
</attribute>
<attribute name="language" type="token" use="optional" default="en-US">
<annotation>
<documentation>
Specifies the recognition language to the recognizer.
</documentation>
</annotation>
</attribute>
<attribute name="initial-timeout" type="core:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Indicates the amount of time preceding input which may expire before a timeout is triggered.
</documentation>
</annotation>
</attribute>
<attribute name="inter-digit-timeout" type="core:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Indicates (in the case of DTMF input) the amount of time between input digits which may expire before a timeout is triggered.
</documentation>
</annotation>
</attribute>
<attribute name="recognition-timeout" type="core:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Indicates the time (in milliseconds) for speech input, after speech has begun, to return a Match before triggering a Nomatch completion.
</documentation>
</annotation>
</attribute>
<attribute name="sensitivity" type="core:fractionDecimalType" use="optional" default="0.5">
<annotation>
<documentation>
Indicates how sensitive the interpreter should be to loud versus quiet input. Higher values represent greater sensitivity.
</documentation>
</annotation>
</attribute>
<attribute name="min-confidence" type="core:fractionDecimalType" use="optional" default="0">
<annotation>
<documentation>
Indicates the confidence threshold, below which a match is to be considered unreliable.
</documentation>
</annotation>
</attribute>
<attribute name="max-silence" type="core:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Indicates the maximum period of silence which may be encountered during input gathering before a timeout is triggered.
</documentation>
</annotation>
</attribute>
<attribute name="match-content-type" type="token" use="optional" default="application/nlsml+xml">
<annotation>
<documentation>
Indicates the required response document format.
</documentation>
</annotation>
</attribute>
<sequence>
<element name="grammar" type="tns:grammarType" minOccurs="1" maxOccurs="unbounded">
<annotation>
<documentation>
Provides the grammar document by which the input detection should be governed.
</documentation>
</annotation>
</element>
</sequence>
</simpleContent>
</complexType>
</element>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Input Complete' anchor='schema-rayo-input-complete'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:input:complete:1"
xmlns:tns="urn:xmpp:rayo:input:complete:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<!-- Finish reason -->
<element name="match">
<annotation>
<documentation>
Indicates that the component came to an end due to one of its grammars matching the received input. Provides the NLSML result of the grammar match after any symantic processing which may have been performed. See the NLSML spec for details.
</documentation>
</annotation>
<complexType>
<simpleContent>
<attribute name="content-type" type="token" use="required" default="application/nlsml+xml">
<annotation>
<documentation>
Indicates the content type of the result document provided as CDATA.
</documentation>
</annotation>
</attribute>
</simpleContent>
</complexType>
</element>
<!-- Initial timeout reason -->
<element name="noinput" type="core:empty">
<annotation>
<documentation>
Indicates that the component came to an end because a timeout was triggered before input was received.
</documentation>
</annotation>
</element>
<!-- NoMatch reason -->
<element name="nomatch" type="core:empty">
<annotation>
<documentation>
Indicates that the component came to an end because input was received which did not match any of the specified grammars.
</documentation>
</annotation>
</element>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Prompt' anchor='schema-rayo-prompt'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:prompt:1"
xmlns:tns="urn:xmpp:rayo:prompt:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1"
xmlns:output="urn:xmpp:rayo:output:1"
xmlns:input="urn:xmpp:rayo:input:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<!-- Main Prompt command -->
<element name="prompt">
<annotation>
<documentation>
Instructs the server to begin an input detector of the specified mode, with certain attributes, governed by the rules provided in one or more grammar documents, while simultaneously rendering output.
</documentation>
</annotation>
<complexType>
<simpleContent>
<attribute name="barge-in" type="boolean" use="optional" default="true">
<annotation>
<documentation>
Whether or not the input detector is permitted to interrupt the output.
</documentation>
</annotation>
</attribute>
<sequence>
<element name="output" type="output:outputType" minOccurs="1" maxOccurs="1">
<annotation>
<documentation>
Provides the output component to be executed
</documentation>
</annotation>
</element>
<element name="input" type="input:inputType" minOccurs="1" maxOccurs="1">
<annotation>
<documentation>
Provides the input component to be executed
</documentation>
</annotation>
</element>
</sequence>
</simpleContent>
</complexType>
</element>
<!-- Input Timers Started Event -->
<element name="input-timers-started">
<annotation>
<documentation>
Indicates that the component's input timers have started.
</documentation>
</annotation>
</element>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Record' anchor='schema-rayo-record'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:record:1"
xmlns:tns="urn:xmpp:rayo:record:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<!-- Main Record command -->
<element name="record">
<annotation>
<documentation>
Instructs the server to begin recording input to the call to a file.
</documentation>
</annotation>
<complexType>
<attribute name="format" type="token" use="optional" default="wav">
<annotation>
<documentation>
File format used during recording.
</documentation>
</annotation>
</attribute>
<attribute name="start-beep" type="boolean" use="optional" default="false">
<annotation>
<documentation>
Indicates whether subsequent record will be preceded with a beep.
</documentation>
</annotation>
</attribute>
<attribute name="stop-beep" type="boolean" use="optional" default="false">
<annotation>
<documentation>
Indicates whether subsequent record stop will be preceded with a beep.
</documentation>
</annotation>
</attribute>
<attribute name="start-paused" type="boolean" use="optional" default="false">
<annotation>
<documentation>
Whether subsequent record will start in PAUSE mode.
</documentation>
</annotation>
</attribute>
<attribute name="max-duration" type="core:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Indicates the maximum duration for the recording.
</documentation>
</annotation>
</attribute>
<attribute name="initial-timeout" type="core:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Controls how long the recognizer should wait after the end of the prompt for the caller to speak before sending a Recorder event.
</documentation>
</annotation>
</attribute>
<attribute name="final-timeout" type="core:timeoutType" use="optional" default="-1">
<annotation>
<documentation>
Controls the length of a period of silence after callers have spoken to conclude they finished.
</documentation>
</annotation>
</attribute>
<attribute name="direction" use="optional" default="duplex">
<annotation>
<documentation>
Indicates the direction of the call to record, as in media produced or received by the calling party.
</documentation>
</annotation>
<simpleType>
<restriction base="token">
<enumeration value="duplex">
<annotation>
<documentation>
Records both sent and received audio.
</documentation>
</annotation>
</enumeration>
<enumeration value="send">
<annotation>
<documentation>
Indicates that only the audio sent from the caller is to be recorded. Not supported when Record is executed against a mixer.
</documentation>
</annotation>
</enumeration>
<enumeration value="recv">
<annotation>
<documentation>
Indicates that only and all audio received by the caller is recorded.
</documentation>
</annotation>
</enumeration>
</restriction>
</simpleType>
</attribute>
<attribute name="mix" type="boolean" use="optional" default="false">
<annotation>
<documentation>
Whether all channels (call legs) should be mixed into a single recording channel.
</documentation>
</annotation>
</attribute>
<sequence>
<element name="hint" minOccurs="0" maxOccurs="unbounded">
<annotation>
<documentation>
Optional format-specific encoding hints
</documentation>
</annotation>
<complexType>
<attribute name="name" type="string" use="required">
<annotation>
<documentation>
The name of the hint value as expected by the recorder.
</documentation>
</annotation>
</attribute>
<attribute name="value" type="string" use="required">
<annotation>
<documentation>
The value of the hint provided.
</documentation>
</annotation>
</attribute>
</complexType>
</element>
</sequence>
</complexType>
</element>
<!-- Pause command -->
<element name="pause" type="core:empty">
<annotation>
<documentation>
Instructs the server to cease recording input but to leave the destination open for appending to permit resumption from the same point.
</documentation>
</annotation>
</element>
<!-- Resume command -->
<element name="resume" type="core:empty">
<annotation>
<documentation>
Instructs the server to continue recording input, appending to the same destination.
</documentation>
</annotation>
</element>
</schema>
]]></code>
</section2>
<section2 topic='Rayo Record Complete' anchor='schema-rayo-record-complete'>
<code><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:xmpp:rayo:record:complete:1"
xmlns:tns="urn:xmpp:rayo:record:complete:1"
elementFormDefault="qualified"
xmlns:core="urn:xmpp:rayo:1">
<annotation>
<documentation>
The protocol documented by this schema is defined at http://rayo.org/xep
</documentation>
</annotation>
<!-- Recording data -->
<element name="recording" type="core:empty">
<attribute name="uri" type="anyURI" use="required">
<annotation>
<documentation>
Indicates the URI at which the recording is made available.
</documentation>
</annotation>
</attribute>
<attribute name="duration" type="core:durationType" use="required">
<annotation>
<documentation>
Indicates the duration of the completed recording.
</documentation>
</annotation>
</attribute>
<attribute name="size" type="long" use="required">
<annotation>
<documentation>
Indicates the filesize (in bytes) of the completed recording.
</documentation>
</annotation>
</attribute>
</complexType>
<!-- Max Duration reason -->
<element name="max-duration" type="core:empty">
<annotation>
<documentation>
Indicates that the component came to an end due to the max duration being reached.
</documentation>
</annotation>
</element>
<!-- Initial Timeout reason -->
<element name="initial-timeout" type="core:empty">
<annotation>
<documentation>
Indicates that the component came to an end due to no input being detected before the initial-timeout.
</documentation>
</annotation>
</element>
<!-- Final Timeout reason -->
<element name="final-timeout" type="core:empty">
<annotation>
<documentation>
Indicates that the component came to an end because no input had been detected for the final timeout duration.
</documentation>
</annotation>
</element>
</schema>
]]></code>
</section2>
</section1>
<section1 topic='History' anchor='history'>
<p>Prior to the development of the Rayo protocol, the most widely-used 3PCC protocols were Asterisk's AGI and AMI. Unfortunately, these protocols have many drawbacks, not least in their inconsistency and relatively poor documentation, but also in that they are poorly secured and lacking in attributes required for significant scalability. Much 3PCC activity is also done using process-internal APIs rather than a wire protocol like XMPP.</p>
<p>Rayo was developed to satisfy three main desires:</p>
<ul>
<li>To separate the application logic from the back-end call processing infrastructure for large-scale scripting-based hosted voice application platforms. This helps to ensure that the performance of the back-end infrastructure cannot be impacted by the applications controling it, and specifically to allow sandboxing the applications.</li>
<li>To create a platform-agnostic protocol for the control of live media sessions that has been designed from the start for such use.</li>
<li>To enable authenticated, federated, web-scale 3PCC on platforms with APIs only suitable for trusted internal use (Asterisk, FreeSWITCH, etc).</li>
</ul>
<p>Initial development of the Rayo specification and its reference implementation was sponsored by Tropo (formerly Voxeo Labs) and Telefónica, with Punchblock being the first client library implementation, as part of the Adhearsion project. Since the beginning of the development process, further implementation efforts have begun on top of Asterisk's AGI/AMI protocols and FreeSWITCH EventSocket, native to FreeSWITCH (mod_rayo), as well as client library implementations in Node/CoffeeScript and Python.</p>
</section1>
<section1 topic='Acknowledgements' anchor='acknowledgements'>
<p>The authors would like to acknowledge the input of teams at Tropo (formerly Voxeo Labs), Mojo Lingo and Telefónica in the development of the initial specification, and Grasshopper in expanding the implementation landscape.</p>
<p>Specific individuals who have contributed to the specification or to software significant to its completion include:</p>
<ul>
<li>Ben Langfeld</li>
<li>Ben Klang</li>
<li>Chris Rienzo</li>
<li>Jason Goecke</li>
<li>John Dyer</li>
<li>Jose de Castro</li>
<li>Juan de Bravo</li>
<li>Luca Pradovera</li>
<li>Martín Pérez</li>
</ul>
</section1>
</xep>