mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-24 10:12:19 -05:00
2ac91f50c8
git-svn-id: file:///home/ksmith/gitmigration/svn/xmpp/trunk@2 4b5297f7-1745-476d-ba37-a9c6900126ab
827 lines
49 KiB
XML
827 lines
49 KiB
XML
<?xml version='1.0' encoding='UTF-8'?>
|
|
<!DOCTYPE jep SYSTEM '../jep.dtd' [
|
|
<!ENTITY % ents SYSTEM '../jep.ent'>
|
|
%ents;
|
|
]>
|
|
<?xml-stylesheet type='text/xsl' href='../jep.xsl'?>
|
|
<jep>
|
|
<header>
|
|
<title>Jingle</title>
|
|
<abstract>This document defines a framework for initiating and managing peer-to-peer sessions (e.g., voice and video exchanges) between Jabber/XMPP clients in a way that is interoperable with existing Internet standards.</abstract>
|
|
&LEGALNOTICE;
|
|
<number>0166</number>
|
|
<status>Experimental</status>
|
|
<type>Standards Track</type>
|
|
<jig>Standards JIG</jig>
|
|
<approver>Council</approver>
|
|
<dependencies>
|
|
<spec>XMPP Core</spec>
|
|
</dependencies>
|
|
<supersedes/>
|
|
<supersededby/>
|
|
<shortname>jingle</shortname>
|
|
&scottlu;
|
|
&joebeda;
|
|
&stpeter;
|
|
&hildjj;
|
|
&seanegan;
|
|
&robmcqueen;
|
|
<revision>
|
|
<version>0.10</version>
|
|
<date>2006-09-29</date>
|
|
<initials>ram/psa</initials>
|
|
<remark><p>Made several corrections to the state machines and examples.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.9</version>
|
|
<date>2006-09-08</date>
|
|
<initials>ram/psa</initials>
|
|
<remark><p>Further cleaned up state machines and state-related actions.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.8</version>
|
|
<date>2006-08-23</date>
|
|
<initials>ram/psa</initials>
|
|
<remark><p>Changed channels to components in line with ICE; changed various action names for consistency; added session-extend and session-reduce actions to add and remove description/transport pairs; added description-modify action; added sender attribute to specify directionality.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.7</version>
|
|
<date>2006-07-17</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Added implementation note about handling multiple content types.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.6</version>
|
|
<date>2006-07-12</date>
|
|
<initials>se/psa</initials>
|
|
<remark><p>Changed media type to content type.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.5</version>
|
|
<date>2006-03-20</date>
|
|
<initials>psa/jb</initials>
|
|
<remark><p>Further clarified state machine diagrams; specified that session accept must include agreed-upon media format and transport description; moved deployment notes to appropriate transport spec.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.4</version>
|
|
<date>2006-03-01</date>
|
|
<initials>psa/jb</initials>
|
|
<remark><p>Added glossary; clarified state machines; updated to reflect publication of JEP-0176 and JEP-0177.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.3</version>
|
|
<date>2006-02-24</date>
|
|
<initials>psa/jb</initials>
|
|
<remark><p>Provided more detail about modify scenarios; defined media-specific and transport-specific actions and adjusted state machine accordingly.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.2</version>
|
|
<date>2006-02-13</date>
|
|
<initials>psa/jb</initials>
|
|
<remark><p>Per agreement among the co-authors, moved transport definition to separate specification, simplified state machine, and made other associated changes to the text, examples, and schemas; also harmonized redirect, decline, and terminate processes.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.1</version>
|
|
<date>2005-12-15</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Initial JEP version.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.10</version>
|
|
<date>2005-12-11</date>
|
|
<initials>psa</initials>
|
|
<remark><p>More fully documented burst mode, connectivity checks, error cases, etc.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.9</version>
|
|
<date>2005-12-08</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Restructured document flow; provided example of burst mode.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.8</version>
|
|
<date>2005-12-05</date>
|
|
<initials>psa/sl/jb</initials>
|
|
<remark><p>Distinguished between dribble mode and burst mode, including mode attribute, service discovery features, and implementation notes; provided detailed resource discovery examples; corrected state chart; specified session termination; specified error conditions; specified semantics of informational messages; began to define security considerations; added Joe Beda as co-author.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.7</version>
|
|
<date>2005-11-08</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Added more detail to basic session flow; harmonized candidate negotiation process with ICE.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.6</version>
|
|
<date>2005-10-27</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Added Jabber Registrar considerations; defined schema; completed slight syntax cleanup.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.5</version>
|
|
<date>2005-10-21</date>
|
|
<initials>psa/sl</initials>
|
|
<remark><p>Separated methoddescription formats from signalling protocol.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.4</version>
|
|
<date>2005-10-19</date>
|
|
<initials>psa/sl</initials>
|
|
<remark><p>Harmonized basic session flow with Google Talk protocol; added Scott Ludwig as co-author.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.3</version>
|
|
<date>2005-10-10</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Added more detail to basic session flow.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.2</version>
|
|
<date>2005-10-07</date>
|
|
<initials>psa/jjh</initials>
|
|
<remark><p>Protocol cleanup.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.1</version>
|
|
<date>2005-10-06</date>
|
|
<initials>psa/jjh</initials>
|
|
<remark><p>First draft.</p></remark>
|
|
</revision>
|
|
</header>
|
|
<section1 topic='Introduction' anchor='intro'>
|
|
<p>There exists no widely-adopted standard for initiating and managing peer-to-peer (p2p) interactions (such as voice, video, or file sharing exchanges) from within Jabber/XMPP clients. Although several large service providers and Jabber/XMPP clients have written and implemented their own proprietary XMPP extensions for p2p signalling (usually only for voice), those technologies are not open and do not always take into account requirements to interoperate with the Public Switched Telephone Network (PSTN) or emerging SIP-based Internet voice networks. By contrast, the only existing open protocol has been &jep0111;, which made it possible to initiate and manage p2p sessions, but which did not provide enough of the key signalling semantics to be easily implemented in Jabber/XMPP clients. <note>It is true that TINS made it relatively easy to implement an XMPP-to-SIP gateway; however, in line with the long-time Jabber philosophy of "simple clients, complex servers", it would be better to force complexity onto the server-side gateway and to keep the client as simple as possible.</note></p>
|
|
<p>The result has been an unfortunate fragmentation within the XMPP community regarding signalling protocols. There are, essentially, two approaches to solving the problem:</p>
|
|
<ol>
|
|
<li>Recommend that all client developers implement a dual-stack (XMPP + SIP) solution.</li>
|
|
<li>Define a full-featured protocol for XMPP signalling.</li>
|
|
</ol>
|
|
<p>Implementation experience indicates that a dual-stack approach may not be feasible on all the computing platforms for which Jabber clients have been written, or even desirable on platforms where it is feasible. <note>For example, one large ISP recently decided to switch to a pure XMPP approach after having implemented and deployed a dual-stack client for several years.</note> Therefore, it seems reasonable to define an XMPP signalling protocol that can provide the necessary signalling semantics while also making it possible to interoperate with existing Internet standards.</p>
|
|
<p>As a result of feedback received on <cite>JEP-0111</cite>, the second and fourth authors of this document began to define such a signalling protocol, code-named Jingle. Upon communication with members of the Google Talk team, <note>Google Talk is a messaging and voice chat service and client provided by Google; see <<link url='http://www.google.com/talk/'>http://www.google.com/talk/</link>>.</note> it was discovered that the emerging Jingle approach was conceptually (and even syntactically) quite similar to the signalling protocol used in the Google Talk application. Therefore, in the interest of interoperability and adoption, we decided to harmonize the two approaches. The signalling protocol specified therein is, therefore, substantially equivalent to the existing Google Talk protocol, with several adjustments based on feedback received from implementors as well as for publication within the Jabber Software Foundation's standards process.</p>
|
|
</section1>
|
|
<section1 topic='Requirements' anchor='reqs'>
|
|
<p>The protocol defined herein is designed to meet the following requirements:</p>
|
|
<ol>
|
|
<li>Make it possible to manage a wide variety of peer-to-peer sessions (not limited to voice and video) within XMPP. <note>Possible other content description formats include file sharing, application casting, application sharing, whiteboarding, torrent broadcasting, shared real-time editing, and distributed musical performance, to name but a few.</note></li>
|
|
<li>Make it possible to add, modify, and remove content types from an existing session.</li>
|
|
<li>Make it relatively easy to implement support for the protocol in standard Jabber/XMPP clients.</li>
|
|
<li>Where communication with non-XMPP entities is needed, push as much complexity as possible onto server-side gateways between the XMPP network and the non-XMPP network.</li>
|
|
</ol>
|
|
<p>This document defines the signalling protocol only. Additional documents specify the following:</p>
|
|
<ul>
|
|
<li><p>Various content description formats (audio, video, etc.) and, where possible, mapping those types to the Session Description Protocol (SDP; see &rfc4566;); one example is &jep0167;.</p></li>
|
|
<li><p>Various content transport methods.</p></li>
|
|
<li><p>Procedures for mapping the Jingle signalling protocol to existing signalling standards such as the IETF's Session Initiation Protocol (SIP; see &rfc3261;) and the ITU's H.323 protocol (see &h323;).</p></li>
|
|
</ul>
|
|
</section1>
|
|
<section1 topic='Glossary' anchor='glossary'>
|
|
<table caption='Glossary'>
|
|
<tr>
|
|
<th>Term</th>
|
|
<th>Definition</th>
|
|
</tr>
|
|
<tr>
|
|
<td>Session</td>
|
|
<td>A number of pairs of negotiated content transport methods and content description formats connecting two entities. It is delimited in time by an initiate request and session ending events. During the lifetime of a session, pairs of content descriptions and content transport methods can be added or removed.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Content Type</td>
|
|
<td>A formal declaration of the purpose(s) of the session. Common sessions might include types such as "voice", both "voice" and "video", and "file sharing". A session consists of at least one active negotiated content type at a time. Depending on the content type and the content description, one content description may require multiple components to be communicated by the transport. This is the 'what' of the session. In Jingle XML syntax the content type is the namespace of the &DESCRIPTION; element.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Content Description</td>
|
|
<td>The details of the content type being established. For instance, this might describe the acceptable codecs when establishing a voice conversation. The XML elements for the content description are qualified by the namespace of the content type. The content description defines the bits to be transferred.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Transport Method</td>
|
|
<td>The method for establishing data stream(s) between entities. Possible transports might include &jep0176;, &jep0177;, inband data, etc. This is the 'how' of the session. In Jingle XML syntax this is the namespace of the &TRANSPORT; element. The content transport method defines how to transfer bits from one host to another.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Component</td>
|
|
<td>A component is a numbered stream of data which needs to be transmitted between the endpoints for a given content type in the context of a given session. It is up to the transport to negotiate the details of each component. For instance, the voice content type might use two components, one to transmit an RTP stream, and another to transmit RTCP timing information.</td>
|
|
</tr>
|
|
</table>
|
|
</section1>
|
|
<section1 topic='Concepts and Approach' anchor='concepts'>
|
|
<p>Jingle consists of three parts, each with its own syntax, semantics, and state machine:</p>
|
|
<ol>
|
|
<li>Overall session management</li>
|
|
<li>Content description formats (the "what")</li>
|
|
<li>Content transport methods (the "how")</li>
|
|
</ol>
|
|
<p>This document defines the semantics and syntax for overall session management, and provides pluggable "slots" for content description formats and content transport methods, which are specified in separate documents.</p>
|
|
<section2 topic='Overall Session Management' anchor='concepts-session'>
|
|
<p>The state machine for overall session management (i.e., the state per Session ID) is as follows:</p>
|
|
<code>
|
|
o
|
|
|
|
|
| session-initiate
|
|
|
|
|
| +-----------------------+
|
|
|/ |
|
|
PENDING o---------------------+ |
|
|
| | session-info, | |
|
|
| | content-remove, | |
|
|
| | content-modify, | |
|
|
| | content-accept, | |
|
|
| | content-decline, | |
|
|
| +------------------+ |
|
|
| |
|
|
| session-accept |
|
|
| |
|
|
ACTIVE o---------------------+ |
|
|
| | session-info, | |
|
|
| | content-add, | |
|
|
| | content-remove, | |
|
|
| | content-modify, | |
|
|
| | content-accept, | |
|
|
| | content-decline, | |
|
|
| +------------------+ |
|
|
| |
|
|
+-------------------------+
|
|
|
|
|
| session-redirect,
|
|
| session-terminate
|
|
|
|
|
o ENDED
|
|
</code>
|
|
<p>There are three overall session states:</p>
|
|
<ol>
|
|
<li>PENDING</li>
|
|
<li>ACTIVE</li>
|
|
<li>ENDED</li>
|
|
</ol>
|
|
<p>The actions related to management of the overall Jingle session are:</p>
|
|
<ol start='1'>
|
|
<li>content-accept (accept a content-add, content-modify, or content-remove; implicitly also serves as a description-accept and transport-accept)</li>
|
|
<li>content-add (add one or more new content types to the session; this MUST NOT be sent while the session is in the PENDING state)</li>
|
|
<li>content-decline (reject a content-add or content-modify)</li>
|
|
<li>content-modify (change an existing content type, mainly the directionality)</li>
|
|
<li>content-remove (remove one or more content types from the session)</li>
|
|
<li>session-accept (definitively accept a session request; implicitly also serves as a description-accept and transport-accept)</li>
|
|
<li>session-initiate (request a new Jingle session)</li>
|
|
<li>session-info (session-level information / messages)</li>
|
|
<li>session-redirect (redirect an initiate request to another address)</li>
|
|
<li>session-terminate (end an existing session)</li>
|
|
</ol>
|
|
</section2>
|
|
<section2 topic='Session Content' anchor='concepts-content'>
|
|
<p>The content type of a session is made up of two aspects:</p>
|
|
<ol start='1'>
|
|
<li>The content description format specifies the "what" of the session (e.g., audio).</li>
|
|
<li>The content transport method defines "how" the data shall be exchanged (e.g., raw UDP).</li>
|
|
</ol>
|
|
<p>The &CONTENT; element also specifies who will be sending content (the initiator, the recipient, or both).</p>
|
|
<section3 topic='Content Description Formats' anchor='concepts-description'>
|
|
<p>When negotiating the session and its content type, the entities involved in the session need to exchange content description formats. The approach taken herein is to specify pure session description information in separate specifications, one for each content description format (audio, video, etc.). <note>While it is possible to send raw Session Description Protocol (SDP) data for the session descriptions (the approach that was taken in <cite>JEP-0111</cite>), this is not necessarily helpful, since SDP is not structured data, not all SDP data is needed or used in the most common use cases, and SDP has been heavily extended in several useful directions that are not captured in the core SDP specification.</note> The session negotiation must contain some content description format(s), which are defined in separate specifications. Those specifications also define the state chart for the content description format in question.</p>
|
|
<p>The generic state machine for management of any given content description format is as follows:</p>
|
|
<code>
|
|
START
|
|
o
|
|
|
|
|
| session-initiate
|
|
| content-add
|
|
|
|
|
[PENDING] o-------------+
|
|
| | | description-info
|
|
| |_________| description-modify
|
|
|
|
|
| content-accept
|
|
| description-accept
|
|
| session-accept
|
|
|
|
|
| _____________________o [MODIFYING]
|
|
| / description-modify / \
|
|
|/ / |
|
|
[ACTIVE] o--------------------/ |
|
|
|\ description-decline |
|
|
| \______________________/
|
|
| description-accept
|
|
|
|
|
| content-remove
|
|
| session-terminate
|
|
|
|
|
o [ENDED]
|
|
</code>
|
|
<p>The states related to management of content description formats are:</p>
|
|
<ol>
|
|
<li>PENDING</li>
|
|
<li>ACTIVE</li>
|
|
<li>MODIFYING</li>
|
|
<li>ENDED</li>
|
|
</ol>
|
|
<p>The actions related to management of content description formats are:</p>
|
|
<ol>
|
|
<li>description-info (description-level information / messages)</li>
|
|
<li>description-modify (request a change to a content description format)</li>
|
|
<li>description-accept (accept a proposed content change)</li>
|
|
<li>description-decline (decline a proposed content change)</li>
|
|
</ol>
|
|
</section3>
|
|
<section3 topic='Content Transport Methods' anchor='concepts-transport'>
|
|
<p>As with the content description formats, the content transport methods are specified in separate specifications. Possible content transport methods include Real-time Transport Protocol (RTP) with Interactive Connectivity Establishment (ICE) and raw UDP. Those specifications will also define the state chart for the content transport method in question.</p>
|
|
<p>The generic state machine for any given content transport method is as follows:</p>
|
|
<code>
|
|
START
|
|
o
|
|
|
|
|
| session-initiate
|
|
| content-add
|
|
|
|
|
[PENDING] o-------------+
|
|
| | | transport-info
|
|
| |_________| transport-modify
|
|
|
|
|
| content-accept
|
|
| session-accept
|
|
| transport-accept
|
|
|
|
|
| ___________________o [MODIFYING]
|
|
| / transport-modify / \
|
|
|/ / |
|
|
[ACTIVE] o------------------/ |
|
|
|\ transport-decline |
|
|
| \____________________/
|
|
| transport-accept
|
|
|
|
|
| content-remove
|
|
| session-terminate
|
|
|
|
|
o [ENDED]
|
|
</code>
|
|
<p>The states related to management of content transport methods are:</p>
|
|
<ol>
|
|
<li>PENDING</li>
|
|
<li>ACTIVE</li>
|
|
<li>MODIFYING</li>
|
|
<li>ENDED</li>
|
|
</ol>
|
|
<p>The actions related to management of content transport methods are:</p>
|
|
<ol>
|
|
<li>transport-info (transport-level information / messages)</li>
|
|
<li>transport-modify (request a change to the content transport methods)</li>
|
|
<li>transport-accept (accept a proposed transport change)</li>
|
|
<li>transport-decline (decline a proposed transport change)</li>
|
|
</ol>
|
|
</section3>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='Protocol' anchor='protocol'>
|
|
<section2 topic='Resource Determination' anchor='protocol-resource'>
|
|
<p>In order to initiate a Jingle session, the initiating entity must determine which of the target entity's XMPP resources is best for the desired content description format. If a contact has only one XMPP resource, this task MUST be completed using &jep0030; or the presence-based profile of service discovery specified in &jep0115;.</p>
|
|
<p>Naturally, instead of sending service discovery requests to every contact in a user's roster, it is more efficient to use <cite>Entity Capabilities</cite>, whereby support for Jingle and various Jingle content description formats and content transport methods is determined for a client version in general (rather than on a per-JID basis) and then cached. Refer to <cite>JEP-0115</cite> for details.</p>
|
|
<p>If a contact has more than one XMPP resource, it may be that only one of the resources supports Jingle and the desired content description format, in which case the user MUST initiate the Jingle signalling with that resource.</p>
|
|
<p>If a contact has more than one XMPP resource that supports Jingle and the desired content description format, it is RECOMMENDED for a client to use &jep0168; in order to determine which is the best resource with which to initiate the desired Jingle session.</p>
|
|
</section2>
|
|
<section2 topic='Initiation' anchor='protocol-initiate'>
|
|
<p>Once the initiating entity has discovered which of the target entity's XMPP resources is ideal for the desired content description format, it sends a session initiation request to the target entity. This request is an IQ-set containing a &JINGLE; element qualified by the 'http://jabber.org/protocol/jingle' namespace. The &JINGLE; element MUST possess the 'action', 'initiator', and 'sid' attributes (the latter two uniquely identify the session). For initiation, the 'action' attribute MUST have a value of "session-initiate" and the &JINGLE; element MUST contain one or more &CONTENT; elements, each of which defines a content type to be transferred during the session; each &CONTENT; element in turn contains one &DESCRIPTION; child element that specifies a desired content description format and one or more &TRANSPORT; child elements that specify potential content transport methods.</p>
|
|
<p>The following example shows a Jingle session initiation request for a session that contains both audio and video content:</p>
|
|
<example caption="Initiation Example"><![CDATA[
|
|
<iq to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard' id='jingle1' type='set'>
|
|
<jingle xmlns='http://jabber.org/protocol/jingle'
|
|
action='session-initiate'
|
|
initiator='romeo@montague.net/orchard'
|
|
sid='a73sjjvkla37jfea'>
|
|
<content name='this-is-the-audio-content'>
|
|
<description xmlns='http://jabber.org/protocol/jingle/description/audio'>
|
|
...
|
|
</description>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>
|
|
...
|
|
</transport>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/raw-udp'>
|
|
...
|
|
</transport>
|
|
</content>
|
|
<content name='this-is-the-video-content'>
|
|
<description xmlns='http://jabber.org/protocol/jingle/description/video'>
|
|
...
|
|
</description>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>
|
|
...
|
|
</transport>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/raw-udp'>
|
|
...
|
|
</transport>
|
|
</content>
|
|
</jingle>
|
|
</iq>
|
|
]]></example>
|
|
<p>Note: The syntax and semantics of the &DESCRIPTION; and &TRANSPORT; elements are out of scope for this specification, but are defined in related specifications.</p>
|
|
<p>The attributes of the &JINGLE; element are as follows:</p>
|
|
<ul>
|
|
<li>The 'action' attribute is REQUIRED; it specifies a Jingle action as listed in this document (e.g., "session-initiate").</li>
|
|
<li>The 'initiator' attribute is the full JID of the entity that has initiated the session flow (which may be different from the 'from' address on the IQ-set).</li>
|
|
<li>The 'responder' attribute (see examples below) is the full JID of the entity that has replied to the initiation (which may be different from the 'to' address on the IQ-set).</li>
|
|
<li>The 'sid' attribute is a random session identifier generated by the initiator; this SHOULD match the XML Nmtoken production <note>See <<link url='http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-Nmtoken'>http://www.w3.org/TR/2000/WD-xml-2e-20000814#NT-Nmtoken</link>></note> so that XML character escaping is not needed for characters such as &. (Note: the 'sid' attribute effectively maps to the SIP "Call-ID" parameter.)</li>
|
|
</ul>
|
|
<p>The attributes of the &CONTENT; element are as follows:</p>
|
|
<ul>
|
|
<li>The 'name' attribute is REQUIRED; it specifies a unique name or identifier for the content type (this identifier is opaque and does not have semantic meaning).</li>
|
|
<li>The 'senders' attribute specifies which entities in the session will be generating content; the allowable values are "initiator", "recipient", or "both" (where "both" is the default).</li>
|
|
</ul>
|
|
</section2>
|
|
<section2 topic='Target Entity Response' anchor='protocol-response'>
|
|
<p>Unless an error occurs, the target entity MUST acknowledge receipt of the initiation request:</p>
|
|
<example caption="Target Entity Acknowledges Receipt of Initiation Request"><![CDATA[
|
|
<iq type='result' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'/>
|
|
]]></example>
|
|
<p>If the target entity acknowledges receipt of the initation request, both parties must consider the session to be in the PENDING state.</p>
|
|
<p>There are several reasons why the target entity might return an error instead of acknowledging receipt of the initiation request:</p>
|
|
<ul>
|
|
<li>The initiating entity is unknown to the target entity (e.g., via presence subscription).</li>
|
|
<li>The target entity does not support Jingle.</li>
|
|
<li>The target entity does not support any of the specified content description formats.</li>
|
|
<li>The target entity does not support any of the specified content transport methods.</li>
|
|
<li>The initiation request was malformed.</li>
|
|
</ul>
|
|
<p>The initiating entity is unknown to the target entity (e.g., via presence subscription) and the target entity has a policy of not communicating via Jingle with unknown entities, it MUST return a &unavailable; error.</p>
|
|
<example caption="Initiating Entity Unknown to Target Entity"><![CDATA[
|
|
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
|
|
<error type='cancel'>
|
|
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
|
</error>
|
|
</iq>
|
|
]]></example>
|
|
<p>If the target entity does not support Jingle, it MUST return a &unavailable; error.</p>
|
|
<example caption="Target Entity Does Not Support Jingle"><![CDATA[
|
|
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
|
|
<error type='cancel'>
|
|
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
|
</error>
|
|
</iq>
|
|
]]></example>
|
|
<p>If the target entity does not support any of the specified content description formats, it MUST return a &feature; error with a Jingle-specific error condition of <unsupported-content/>.</p>
|
|
<example caption="Target Entity Does Not Support Any Content Description Formats"><![CDATA[
|
|
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
|
|
<error type='cancel'>
|
|
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
|
<unsupported-content xmlns='http://jabber.org/protocol/jingle#errors'/>
|
|
</error>
|
|
</iq>
|
|
]]></example>
|
|
<p>If the target entity does not support any of the specified content transport methods, it MUST return a &feature; error with a Jingle-specific error condition of <unsupported-transports/>.</p>
|
|
<example caption="Target Entity Does Not Support Any Transport Methods"><![CDATA[
|
|
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
|
|
<error type='cancel'>
|
|
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
|
<unsupported-transports xmlns='http://jabber.org/protocol/jingle#errors'/>
|
|
</error>
|
|
</iq>
|
|
]]></example>
|
|
<p>If the initiation request was malformed, the target entity MUST return a &badrequest; error.</p>
|
|
<example caption="Initiation Request Malformed"><![CDATA[
|
|
<iq type='error' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='jingle1'>
|
|
<error type='cancel'>
|
|
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
|
</error>
|
|
</iq>
|
|
]]></example>
|
|
</section2>
|
|
<section2 topic='Redirection' anchor='protocol-redirect'>
|
|
<p>After acknowledging receipt of the initiation request, the target entity MAY redirect the session to another address (e.g., because the principal is not answering at the original resource). This is done by sending a Jingle redirect action to the initiating entity:</p>
|
|
<example caption="Target Entity Redirects the Session"><![CDATA[
|
|
<iq from='juliet@capulet.com/balcony'
|
|
id='jingle2'
|
|
to='romeo@montague.net/orchard'
|
|
type='set'>
|
|
<jingle xmlns='http://jabber.org/protocol/jingle'
|
|
action='session-redirect'
|
|
initiator='romeo@montague.net/orchard'
|
|
responder='juliet@capulet.com/balcony'
|
|
sid='a73sjjvkla37jfea'>
|
|
<redirect>xmpp:voicemail@capulet.com</redirect>
|
|
</jingle>
|
|
</iq>
|
|
]]></example>
|
|
<p>The recipient then acknowledges the redirection:</p>
|
|
<example caption="Initiating Entity Acknowledges Redirection"><![CDATA[
|
|
<iq from='romeo@montague.net/orchard'
|
|
id='jingle2'
|
|
to='juliet@capulet.com/balcony'
|
|
type='result'/>
|
|
]]></example>
|
|
<p>Both entities MUST now consider the original session to be in the ENDED state, and if the initiating entity wishes to initiate a session with the redirected address it MUST do so by sending a session initiation request to that address with a new session ID.</p>
|
|
</section2>
|
|
<section2 topic='Decline' anchor='protocol-decline'>
|
|
<p>In order to decline the session initiation request, the target entity MUST acknowledge receipt of the session initiation request, then terminate the session as described in the <link url='#protocol-terminate'>Termination</link> section of this document.</p>
|
|
</section2>
|
|
<section2 topic='Negotiation' anchor='protocol-negotiation'>
|
|
<p>In general, negotiation will be necessary before the parties can agree on an acceptable set of content types, content description formats, and content transport methods. The potential combinations of parameters to be negotiated are many, and not all are shown herein (some are shown in the relevant specifications for various content description formats and content transport methods).</p>
|
|
<p>One session-level negotiation is to <em>remove</em> a content types. For example, let us imagine that Juliet is having a bad hair day. She certainly does not want to include video in her Jingle session with Romeo, so she sends a "content-remove" request to Romeo:</p>
|
|
<example caption="Content Type Removal"><![CDATA[
|
|
<iq to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard' id='reduce1' type='set'>
|
|
<jingle xmlns='http://jabber.org/protocol/jingle'
|
|
action='content-remove'
|
|
initiator='romeo@montague.net/orchard'
|
|
sid='a73sjjvkla37jfea'>
|
|
<content name='this-is-the-video-content'/>
|
|
</jingle>
|
|
</iq>
|
|
]]></example>
|
|
<p>The entity receiving the session reduction request then acknowledges the request:</p>
|
|
<example caption="Acknowledgement"><![CDATA[
|
|
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='reduce1' type='result'/>
|
|
]]></example>
|
|
<p>If the reduction results in no more content types for the session, the entity that receives the session-reduce SHOULD send a session-terminate action to the other party (since a session with no content types is void).</p>
|
|
<p>Another session-level negotiation is to <em>add</em> a content type; however, this MUST NOT be done during while the session is in the PENDING state and is allowed only while the session is in the ACTIVE state (see below).</p>
|
|
</section2>
|
|
<section2 topic='Acceptance' anchor='protocol-acceptance'>
|
|
<p>If (after negotiation of content transport methods and content description formats) the target entity determines that it will be able to establish a connection, it sends a definitive acceptance to the initiating entity:</p>
|
|
<example caption="Target Entity Definitively Accepts the Call"><![CDATA[
|
|
<iq type='set' from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='accept1'>
|
|
<jingle xmlns='http://jabber.org/protocol/jingle'
|
|
action='session-accept'
|
|
initiator='romeo@montague.net/orchard'
|
|
responder='juliet@capulet.com/balcony'
|
|
sid='a73sjjvkla37jfea'>
|
|
<content name='some-opaque-name'>
|
|
<description xmlns='http://jabber.org/protocol/jingle/description/audio'>
|
|
...
|
|
</description>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>
|
|
...
|
|
</transport>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/raw-udp'>
|
|
...
|
|
</transport>
|
|
</content>
|
|
<content name='another-opaque-name'>
|
|
<description xmlns='http://jabber.org/protocol/jingle/description/video'>
|
|
...
|
|
</description>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>
|
|
...
|
|
</transport>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/raw-udp'>
|
|
...
|
|
</transport>
|
|
</jingle>
|
|
</iq>
|
|
]]></example>
|
|
<p>The &JINGLE; element in the accept stanza MUST contain one or more <content/> elements, each of which MUST contain only one <description/> element and one or more <transport/> elements. The &JINGLE; element SHOULD possess a 'responder' attribute that explicitly specifies the full JID of the responding entity, and the initiating entity SHOULD send all future commmunications about this Jingle session to the JID provided in the 'responder' attribute.</p>
|
|
<p>The initiating entity then acknowledges the target entity's definitive acceptance:</p>
|
|
<example caption="Initiating Entity Acknowledges Definitive Acceptance"><![CDATA[
|
|
<iq type='result' to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard' id='accept1'/>
|
|
]]></example>
|
|
<p>Now the initiating entity and target entity can begin sending content over the negotiated connection.</p>
|
|
<p>If one of the parties cannot find a suitable content transport method, it SHOULD terminate the session as described below.</p>
|
|
</section2>
|
|
<section2 topic='Modifying an Active Session' anchor='protocol-modify'>
|
|
<p>In order to modify an active session, either party may send a "content-remove", "content-add", "content-modify", "description-modify", or "transport-modify" action to the other party. The receiving party then sends an appropriate "-accept" or "-decline" action, and may first send an appropriate "-info" action.</p>
|
|
<p>If both parties send modify messages at the same time, the modify message from the session initiator MUST trump the modify message from the recipient and the initiator SHOULD return an &unexpected; error to the other party.</p>
|
|
<p>One example of modifying an active session is to <em>add</em> a content type. For example, let us imagine that Juliet gets her hair in order and now wants to add video. She now sends a "content-add" request to Romeo:</p>
|
|
<example caption="Adding a Content Type"><![CDATA[
|
|
<iq to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard' id='add1' type='set'>
|
|
<jingle xmlns='http://jabber.org/protocol/jingle'
|
|
action='content-add'
|
|
initiator='romeo@montague.net/orchard'
|
|
sid='a73sjjvkla37jfea'>
|
|
<content name='video-is-back'>
|
|
<description xmlns='http://jabber.org/protocol/jingle/description/video'>
|
|
...
|
|
</description>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>
|
|
...
|
|
</transport>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/raw-udp'>
|
|
...
|
|
</transport>
|
|
</content>
|
|
</jingle>
|
|
</iq>
|
|
]]></example>
|
|
<p>The entity receiving the session extension request then acknowledges the request and, if it is acceptable, returns a content-accept:</p>
|
|
<example caption="Acknowledgement"><![CDATA[
|
|
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='add1' type='result'/>
|
|
]]></example>
|
|
<example caption="Content Acceptance"><![CDATA[
|
|
<iq from='romeo@montague.net/orchard' to='juliet@capulet.com/balcony' id='add2' type='set'/>
|
|
<jingle xmlns='http://jabber.org/protocol/jingle'
|
|
action='content-add'
|
|
initiator='romeo@montague.net/orchard'
|
|
sid='a73sjjvkla37jfea'>
|
|
<content name='video-is-back'>
|
|
<description xmlns='http://jabber.org/protocol/jingle/description/video'>
|
|
...
|
|
</description>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>
|
|
...
|
|
</transport>
|
|
<transport xmlns='http://jabber.org/protocol/jingle/transport/raw-udp'>
|
|
...
|
|
</transport>
|
|
</content>
|
|
</jingle>
|
|
</iq>
|
|
]]></example>
|
|
<p>The other party then acknowledges the acceptance.</p>
|
|
<example caption="Acknowledgement"><![CDATA[
|
|
<iq from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' id='add2' type='result'/>
|
|
]]></example>
|
|
</section2>
|
|
<section2 topic='Termination' anchor='protocol-terminate'>
|
|
<p>In order to gracefully end the session (which MAY be done at any point after acknowledging receipt of the initiation request, including immediately thereafter in order to decline the request), either the target entity or the initiating entity MUST a send a "terminate" action to the other party:</p>
|
|
<example caption="Target Entity Terminates the Session"><![CDATA[
|
|
<iq from='juliet@capulet.com/balcony'
|
|
id='term1'
|
|
to='romeo@montague.net/orchard'
|
|
type='set'>
|
|
<jingle xmlns='http://jabber.org/protocol/jingle'
|
|
action='session-terminate'
|
|
initiator='romeo@montague.net/orchard'
|
|
sid='a73sjjvkla37jfea'/>
|
|
</iq>
|
|
]]></example>
|
|
<p>The initiating entity MUST then acknowledge termination of the session:</p>
|
|
<example caption="Initiating Entity Acknowledges Termination"><![CDATA[
|
|
<iq type='result' to='juliet@capulet.com/balcony' from='romeo@montague.net/orchard' id='term1'/>
|
|
]]></example>
|
|
<p>Unfortunately, not all sessions end gracefully. The following events MUST be considered session-ending events, and any further Jingle communication for the negotiated content description format and content transport method MUST be completed through negotiation of a new session:</p>
|
|
<ul>
|
|
<li>Receipt of a 'session-redirect' or 'session-terminate' action from the other party.</li>
|
|
<li>Receipt of &UNAVAILABLE; from the other party.</li>
|
|
</ul>
|
|
<p>In particular, one party MUST consider the session to be in the ENDED state if it receives presence of type "unavailable" from the other party:</p>
|
|
<example caption="Target Entity Goes Offline"><![CDATA[
|
|
<presence from='juliet@capulet.com/balcony' to='romeo@montague.net/orchard' type='unavailable'/>
|
|
]]></example>
|
|
<p>Naturally, in this case there is nothing for the initiating entity to acknowledge.</p>
|
|
</section2>
|
|
<section2 topic='Informational Messages' anchor='protocol-info'>
|
|
<p>At any point after initiation of a Jingle session, either entity MAY send an informational message to the other party, for example to change a content transport method or content description format parameter, inform the other party that a session initiation request is queued, that a device is ringing, or that a scheduled event has occurred or will occur. An information message MUST be an IQ-set containing a &JINGLE; element whose 'action' attribute is set to a value of "session-info", "description-info", or "transport-info"; the &JINGLE; element MUST further contain a payload child element (speciific to the session, content description format, or content transport method) that specifies the information being communicated. (A future version of this specification will define payloads related to the "session-info" action.)</p>
|
|
</section2>
|
|
</section1>
|
|
|
|
<section1 topic='Error Handling' anchor='errors'>
|
|
<p>The Jingle-specific error conditions are as follows.</p>
|
|
<table caption='Other Error Conditions'>
|
|
<tr>
|
|
<th>Jingle Condition</th>
|
|
<th>XMPP Condition</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td><out-of-order/></td>
|
|
<td>&unexpected;</td>
|
|
<td>The request cannot occur at this point in the state machine (e.g., initiate after accept).</td>
|
|
</tr>
|
|
<tr>
|
|
<td><unknown-session/></td>
|
|
<td>&badrequest;</td>
|
|
<td>The 'sid' attribute specifies a session that is unknown to the recipient.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><unsupported-content/></td>
|
|
<td>¬acceptable;</td>
|
|
<td>The recipient does not support any of the desired content description formats.</td>
|
|
</tr>
|
|
<tr>
|
|
<td><unsupported-transports/></td>
|
|
<td>¬acceptable;</td>
|
|
<td>The recipient does not support any of the desired content transport methods.</td>
|
|
</tr>
|
|
</table>
|
|
</section1>
|
|
|
|
<section1 topic='Implementation Notes' anchor='impl'>
|
|
<p>There is a one-to-one relationship between content types and sessions. This reduces the complexity of managing a given session, since it avoids the need to de-multiplex traffic for different content types sent over the same connection. However, it may be desirable to share different kinds of content at the same time (e.g., during a video chat one party may want to share a file); in order to do this, the parties must establish a separate session for each content type. Management of multiple sessions is a client implementation matter and is not discussed in this specification.</p>
|
|
</section1>
|
|
|
|
<section1 topic='Security Considerations' anchor='security'>
|
|
<p><em>Note: This section is not yet complete.</em></p>
|
|
<section2 topic='Denial of Service' anchor='security-dos'>
|
|
<p>Jingle sessions may be resource-intensive. Therefore, it is possible to launch a denial-of-service attack against an entity by burdening it with too many Jingle sessions. Care must be taken to accept content 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>Jingle communications may be enabled through gateways to non-XMPP networks, whose security characteristics may 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>
|
|
</section1>
|
|
|
|
<section1 topic='IANA Considerations' anchor='iana'>
|
|
<p>This JEP requires no interaction with &IANA;.</p>
|
|
</section1>
|
|
|
|
<section1 topic='Jabber Registrar Considerations' anchor='registrar'>
|
|
<section2 topic='Protocol Namespaces' anchor='registrar-ns'>
|
|
<p>The ®ISTRAR; shall include 'http://jabber.org/protocol/jingle' and 'http://jabber.org/protocol/jingle#errors' in its registry of protocol namespaces.</p>
|
|
</section2>
|
|
<section2 topic='Jingle Content Description Formats Registry' anchor='registrar-content'>
|
|
<p>The Jabber Registrar shall maintain a registry of Jingle content description formats. All content description format registrations shall be defined in separate documents (not in this JEP). Content description formats defined within the JEP series MUST be registered with the Jabber Registrar, resulting in protocol URIs of the form "http://jabber.org/protocol/jingle/description/name" (where "name" is the registered name of the content description format).</p>
|
|
®PROCESS;
|
|
<code><![CDATA[
|
|
<content>
|
|
<name>the name of the content description format (e.g., "audio")</name>
|
|
<desc>a natural-language summary of the content description format</desc>
|
|
<doc>the document in which this content description format is specified</doc>
|
|
</content>
|
|
]]></code>
|
|
</section2>
|
|
<section2 topic='Jingle Content Transport Methods Registry' anchor='registrar-transports'>
|
|
<p>The Jabber Registrar shall maintain a registry of Jingle content transport methods. All content transport method registrations shall be defined in separate documents (not in this JEP). Content transport methods defined within the JEP series MUST be registered with the Jabber Registrar, resulting in protocol URIs of the form "http://jabber.org/protocol/jingle/transport/name" (where "name" is the registered name of the content transport method).</p>
|
|
®PROCESS;
|
|
<code><![CDATA[
|
|
<transport>
|
|
<name>the name of the content transport method (e.g., "raw-udp")</name>
|
|
<desc>a natural-language summary of the content transport method</desc>
|
|
<doc>the document in which this content transport method is specified</doc>
|
|
</transport>
|
|
]]></code>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='XML Schemas' anchor='schema'>
|
|
<section2 topic='Jingle' anchor='schema-jingle'>
|
|
<code><![CDATA[
|
|
<?xml version='1.0' encoding='UTF-8'?>
|
|
|
|
<xs:schema
|
|
xmlns:xs='http://www.w3.org/2001/XMLSchema'
|
|
targetNamespace='http://jabber.org/protocol/jingle'
|
|
xmlns='http://jabber.org/protocol/jingle'
|
|
elementFormDefault='qualified'>
|
|
|
|
<xs:element name='jingle'>
|
|
<xs:complexType>
|
|
<xs:sequence minOccurs='1' maxOccurs='unlimited'>
|
|
<xs:element ref='content'/>
|
|
</xs:sequence>
|
|
<xs:attribute name='action' use='required'>
|
|
<xs:simpleType>
|
|
<xs:restriction base='xs:NCName'>
|
|
<xs:enumeration value='content-accept'/>
|
|
<xs:enumeration value='content-add'/>
|
|
<xs:enumeration value='content-decline'/>
|
|
<xs:enumeration value='content-modify'/>
|
|
<xs:enumeration value='content-remove'/>
|
|
<xs:enumeration value='description-accept'/>
|
|
<xs:enumeration value='description-decline'/>
|
|
<xs:enumeration value='description-info'/>
|
|
<xs:enumeration value='description-modify'/>
|
|
<xs:enumeration value='session-accept'/>
|
|
<xs:enumeration value='session-info'/>
|
|
<xs:enumeration value='session-initiate'/>
|
|
<xs:enumeration value='session-redirect'/>
|
|
<xs:enumeration value='session-terminate'/>
|
|
<xs:enumeration value='transport-accept'/>
|
|
<xs:enumeration value='transport-decline'/>
|
|
<xs:enumeration value='transport-info'/>
|
|
<xs:enumeration value='transport-modify'/>
|
|
</xs:restriction>
|
|
</xs:simpleType>
|
|
</xs:attribute>
|
|
<xs:attribute name='initiator' type='xs:string' use='required'/>
|
|
<xs:attribute name='responder' type='xs:string' use='optional'/>
|
|
<xs:attribute name='sid' type='xs:NMTOKEN' use='required'/>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
<xs:element name='content'>
|
|
<xs:complexType>
|
|
<xs:choice minOccurs='0'>
|
|
<xs:sequence>
|
|
<xs:any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>
|
|
</xs:sequence>
|
|
</xs:choice>
|
|
<xs:attribute name='senders' use='optional' default='both'>
|
|
<xs:simpleType>
|
|
<xs:restriction base='xs:NCName'>
|
|
<xs:enumeration value='both'>
|
|
<xs:enumeration value='initiator'>
|
|
<xs:enumeration value='responder'/>
|
|
</xs:restriction>
|
|
</xs:simpleType>
|
|
</xs:attribute>
|
|
</xs:complexType>
|
|
</xs:element>
|
|
|
|
</xs:schema>
|
|
]]></code>
|
|
</section2>
|
|
<section2 topic='Jingle Errors' anchor='schema-errors'>
|
|
<code><![CDATA[
|
|
<?xml version='1.0' encoding='UTF-8'?>
|
|
|
|
<xs:schema
|
|
xmlns:xs='http://www.w3.org/2001/XMLSchema'
|
|
targetNamespace='http://jabber.org/protocol/jingle#errors'
|
|
xmlns='http://jabber.org/protocol/jingle#errors'
|
|
elementFormDefault='qualified'>
|
|
|
|
<xs:element name='out-of-order' type='empty'/>
|
|
<xs:element name='unknown-session' type='empty'/>
|
|
<xs:element name='unsupported-content' type='empty'/>
|
|
<xs:element name='unsupported-transports' type='empty'/>
|
|
|
|
<xs:simpleType name='empty'>
|
|
<xs:restriction base='xs:string'>
|
|
<xs:enumeration value=''/>
|
|
</xs:restriction>
|
|
</xs:simpleType>
|
|
|
|
</xs:schema>
|
|
]]></code>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='Acknowledgements' anchor='ack'>
|
|
<p>The authors would like to thank Rohan Mahy for his valuable input on early versions of this document. Rob Taylor, Dafydd Harries, Jussi Laako, Saku Vainio, Antti Ijäs, Brian West, Anthony Minessale, Matt O'Gorman, and others have also provided helpful input. Thanks also to those who have commented on the &SJIG; and (earlier) Jingle <note>Before this specification was accepted as a Jabber Enhancement Proposal, it was discussed on the semi-private <jingle@jabber.org> mailing list; although that list is no longer used (the Standards-JIG list is the preferred discussion venue), for historical purposes it is publicly archived at <<link url='http://mail.jabber.org/pipermail/jingle/'>http://mail.jabber.org/pipermail/jingle/</link>>.</note> mailing lists.</p>
|
|
</section1>
|
|
</jep>
|