<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
  <!ENTITY % ents SYSTEM 'xep.ent'>
  <!ENTITY CHANNEL "&lt;channel/&gt;">
  <!ENTITY RELAY "&lt;relay/&gt;">
  <!ENTITY SERVICES "&lt;services/&gt;">
  <!ENTITY TRACKER "&lt;tracker/&gt;">
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep>
  <header>
    <title>Jingle Relay Nodes</title>
    <abstract>This documents specifies how Jingle Clients can interact with Jingle Relay Nodes Services and how XMPP entities can provide, search and list available Jingle Relay Nodes.</abstract>
    &LEGALNOTICE;
    <number>0278</number>
    <status>Deferred</status>
    <type>Standards Track</type>
    <sig>Standards</sig>
    <approver>Council</approver>
    <dependencies>
      <spec>XMPP Core</spec>
      <spec>XEP-0166</spec>
      <spec>XEP-0177</spec>
    </dependencies>
    <supersedes/>
    <supersededby/>
    <shortname>jinglenodes</shortname>
    <author>
      <firstname>Thiago</firstname>
      <surname>Camargo</surname>
      <email>thiago@xmppjingle.com</email>
      <jid>barata7@gmail.com</jid>
    </author>
    <revision>
      <version>0.2</version>
      <date>2011-06-21</date>
      <initials>tc</initials>
      <remark><p>Added STUN Service Tracking Support. Removed Public IP requirement for Relay Service.</p></remark>
    </revision>
    <revision>
      <version>0.1</version>
      <date>2010-03-05</date>
      <initials>psa</initials>
      <remark><p>Initial published version.</p></remark>
    </revision>
    <revision>
      <version>0.0.1</version>
      <date>2009-12-17</date>
      <initials>tc</initials>
      <remark><p>First draft.</p></remark>
    </revision>
  </header>
  <section1 topic="Introduction" anchor="intro">
    <p>Jingle Nodes is an XMPP Based Relay Service providing standard UDP/TCP Relay, but negotiated via XMPP.  Jingle Relay Nodes are intend to provide easy to use Jingle Relay Type Candidates that can be used in ICE-UDP, RAW-UDP, TCP Jingle Sessions.  Relay Candidates can provide NAT Traversal for Jingle users with or without STUN/TURN Support.  The main benefits of Jingle Relay Nodes is the easy to use candidates, Jingle Clients can became a Node and Jingle Relay Nodes are published via XMPP, meaning every Client or Server can also act as a tracker of another Nodes and STUN Servers.</p>
  </section1>
  <section1 topic="Requirements" anchor="reqs">
    <p>Jingle Relay Nodes MUST be binded directly to a Public IP address without firewall for traffic on the port range reserved to be used by relay candidates. This is the main and unique requirement for a peer provide Relay Nodes Service.
All signalling, request, response and publishing is done via XMPP, not requiring any extra stack or protocol in the Client or Server, for usage and discoveral of Nodes.</p>
  </section1>
  <section1 topic="Terminology" anchor="terminology">
    <section2 topic="Glossary" anchor="terms-glossary">
      <dl>
        <di>
          <dt>Relay</dt>
          <dd>Relays are mainly used to transfer traffic to servers located on a NAT:ed (masqueraded) network, where the IP addresses on the NAT:ed network cannot be accessed from the outside. When you use an IP address that is for local use only, you must use NAT and relays because these IP addresses cannot be accessed in any other way. Relays can also be used for non-NAT:ed networks.</dd>
        </di>
        <di>
          <dt>Jingle Relay Node</dt>
          <dd>Is an instance of a Relay Service that is negotiable via XMPP, following the procedures described on this Extension.</dd>
        </di>
        <di>
          <dt>Tracker</dt>
          <dd>Is the entity that trackers Jingle Relay Nodes and also publishes the list upon request. Potentially all Jingle Clients might act as a Node Tracker.</dd>
        </di>
        <di>
          <dt>Channel</dt>
          <dd>Is the UDP/TCP Relay Channel, provided by the a Jingle Relay Node. The channel act as a NAT Traversal Channel in order to delivery and receive media.</dd>
        </di>
        <di>
          <dt>Requester</dt>
          <dd>Is the Jingle Client that makes requests and make use of a Channel. The Requester receives a relay <link url="#transports">Transport Candidate</link> that can be used with &xep0176; or &xep0177;.</dd>
        </di>
      </dl>
    </section2>
    <section2 topic="Conventions" anchor="terms-conventions">
      <p>In diagrams, the following conventions are used:</p>
      <ul>
        <li>Single-dashed lines (---) represent Jingle stanzas that are sent via the XMPP signalling channel.</li>
        <li>Double-dashed lines (===) represent media packets that are sent via the data channel, which typically is not an XMPP channel (although the <cite>Jingle In-Band Bytestreams Transport Method</cite> is an exception) but instead is a direct or mediated channel between the endpoints.</li>
      </ul>
    </section2>
  </section1>
  <section1 topic="Flow Example" anchor="rules">
<p>After the Jingle Clients gets succesfully connected to the XMPP Server, it MAY want to start discoverying available Relay Services in order to cache some entries. Having cached Relay Service Addresses is recommended as it speeds up the session setup time as the Client don't need to search for available Relay Services right before a session is started or received.</p>

<section2 topic="Jingle Client Checks for Tracker or Relay Services on its own Server Domain" anchor="clientcheckownserver">
      <p>A Jingle Client MAY start the search for Relay Services by querying his own XMPP Server Domain.</p>
      <p>
        <em>Note: This is a good implementation practice.</em>
      </p>
       <example caption="Service List Request"><![CDATA[
<iq from='romeo@montague.lit/orchard'
    id='uw72g176'
    to='montague.lit'
    type='get'>
  <services xmlns='http://jabber.org/protocol/jinglenodes'/>
</iq>
  ]]></example>
  <example caption="Tracker Returned Known Public Relay Services"><![CDATA[
  <iq from='montague.lit'
    id='uw72g176'
    to='romeo@montague.lit/orchard'
    type='result'>
 <services xmlns='http://jabber.org/protocol/jinglenodes'>
    <relay policy='public' address='montague.lit' protocol='udp'/>
    <tracker policy='public' address='capulet.lit' protocol='udp'/> 
    <stun policy='public' address='200.111.111.111' port='3857' protocol='udp'/>
 </services>
 </iq> ]]></example>
<em>In this example 'montague.lit' XMPP Domain a Relay Service and a Tracker Service. The Relay Service can be contacted in order to retrieve Relay Channels. The Tracker Service can be contacted in order to retrieve its known services.</em>
    </section2>        
<section2 topic="Jingle Client Searches for Services on a Retrieved Tracker Service" anchor="clientcheckownserver">
      <p>A Jingle Client MAY NOT be satisfied with only one Relay Service entry found. So it keeps the search on the known Tracker Services.</p>
       <example caption="Service List Request"><![CDATA[
<iq from='romeo@montague.lit/orchard'
    id='uw72g177'
    to='capulet.lit'
    type='get'>
  <services xmlns='http://jabber.org/protocol/jinglenodes'/>
</iq>
  ]]></example>
  <example caption="Tracker Returned Known Public Relay Services"><![CDATA[
  <iq from='capulet.lit'
    id='uw72g177'
    to='romeo@montague.lit/orchard'
    type='result'>
 <services xmlns='http://jabber.org/protocol/jinglenodes'/>
 </iq> ]]></example>
<em>In this example 'capulet.lit' returned an empty service list, meaning that it does NOT known ANY Relay or Tracker Services.</em>
    </section2>        
<section2 topic="Jingle Client Searches for Services on online Roster Entries" anchor="clientcheckownserver">
      <p>A Jingle Client MAY NOT be satisfied with only one Relay Service entry found. So it keeps the search on his Roster Items until find the desired amount of Relay Services, or while it does NOT exceed a search depth or ANY other Client implementation policy. The Client SHOULD keep a list of visited Tracker Services in order to avoid searching twice in same Service Entity.</p>
       <example caption="Service List Request"><![CDATA[
<iq from='romeo@montague.lit/orchard'
    id='uw72g177'
    to='juliet@capulet.lit/balcony'
    type='get'>
  <services xmlns='http://jabber.org/protocol/jinglenodes'/>
</iq>
  ]]></example>
  <example caption="Tracker Returned Known Public Relay Services"><![CDATA[
  <iq from='juliet@capulet.lit/balcony'
    id='uw72g177'
    to='romeo@montague.lit/orchard'
    type='result'>
 <services xmlns='http://jabber.org/protocol/jinglenodes'>
    <relay policy='roster' address='juliet@capulet.lit/balcony' protocol='udp'/>
 </services>
 </iq> ]]></example>
<p>In this example 'juliet@capulet.lit/balcony' returned a Relay Service entry that is restricted to its roster. This Service is usable as the requester has 'juliet@capulet.lit/balcony' on its roster. Although, services with policy 'roster' MUST NOT be listed in Tracker Responses expects in Tracker Responses that comes from the Service Entity itself, in this case 'juliet@capulet.lit/balcony'.</p>
<em>In the presented example 'romeo@montague.lit/orchard' knows that 'juliet@capulet.lit/balcony' provides Relay Service, but if another entity requests 'romeo@montague.lit/orchard' its known services, it MUST NOT include 'juliet@capulet.lit/balcony' as it is a roster restricted entry.</em>
    </section2>        
    <section2 topic="Jingle Client Consuming the Relay Service" anchor="clientconsumingrelay">
      <p>A Jingle Client with Internet connectivity wheter with direct access to a public IP or not, can potentially provide the Relay Service becaming itself a Jingle Relay Node. The service can intend to provide a public service, or a restricted services based on user preferences, like buddylist, whitelist, blacklist, domain, etc...</p>
      <p>
        <em>Note: It is NOT mandatory to became a Jingle Relay Node it is OPTIONAL and SHOULD be done ONLY under user awareness and concentiment.</em>
      </p>
       <example caption="UDP Relay Channel request"><![CDATA[
<iq from='romeo@montague.lit/orchard'
    id='uw72g176'
    to='juliet@capulet.lit/balcony'
    type='get'>
  <channel xmlns='http://jabber.org/protocol/jinglenodes#channel' protocol='udp'/>
</iq>
  ]]></example>
  <example caption="Candidate Returned by a Node with channel bandwidth throttle"><![CDATA[
  <iq from='juliet@capulet.lit/balcony'
    id='uw72g176'
    to='romeo@montague.lit/orchard'
    type='result'>
<channel component='1'
 id='el0747fg11'
 host='200.20.2.10'
 localport='35800'
 remoteport='35802'
 protocol='udp'
 maxkbps='120'
 expire='60'/>
 </iq> ]]></example>
<em><p>After receiving the &CHANNEL; the requester MUST send his stream to 'host' and 'localport' pair and send a &CANDIDATE; containing the 'host' and 'remoteport' values.</p></em>
    </section2>
  </section1>
    <section1 topic="Services Definitions" anchor="servicesdefinition">
    <section2 topic="Relay Channel Service" anchor="relaychannelservice">
      <p>A Relay Channel Service is responsible for providing the actual Relay Services. It will receive Channel Requests, allocate the Relay Channel and return the ready to use details. If a Jingle Client knows the service address of one valid and reliable Relay Service, that is enough for place and receive Jingle Calls and transmit both ways media streams based on UDP.</p>
      <p>Relay Channel Services support can be discovered by searching using <link url='#trackerservice'>Tracker Services</link>. It can also be discovered by <link url='#support'>service discovery described in this document</link>.</p>
            <p>
        <em>Note: Jingle Relay Channels can be used with RAW-UDP and ICE-UDP Jingle Transports.</em>
      </p>
    </section2>
    <section2 topic="Tracker Service" anchor="trackerservice">
      <p>A Tracker Service is responsible for providing addresses of known Relay Channel Services and other Tracker Services as well.</p>
            <section3 topic="Services Types" anchor="servicetypes">
            <p>Tracker entries MUST contain a 'type' attribute that represents the usage policy according to the table below:</p>
            <table caption="Types of Service Usage Policy">
        <tr>
          <th>Type</th>
          <th>Definition</th>
        </tr>
        <tr>
          <td>public</td>
          <td>Relays Services that are meant and opened for public usage, SHOULD use the type 'public'. Meaning that every user can make use of its services. This type SHOULD be published by Tracker Services.</td>
        </tr>
        <tr>
          <td>roster</td>
          <td>Relay Services that only provides Channels for users that are in it own roster, SHOULD use the type 'roster'. Meaning that only presence subscribed buddies can make use of its service. Common usage is XMPP Clients with Relay Services Capabilities. This type SHOULD NOT be published by Tracker Services as if it is roster only, the requester SHOULD have the entity already added to his roster, which also mean that it SHOULD be discoverable on roster level.</td>
        </tr>
      </table>
            </section3>
    </section2>
  </section1>
    <section1 topic="Formal Definition" anchor="def">
  <section2 topic="Channel Element" anchor="def-channel">
    <p>The &CHANNEL; element MUST be empty.</p>
    <p>The attributes of the &CHANNEL; element are as follows.</p>
    <table caption="Attributes of Channel Element">
      <tr>
        <th>Attribute</th>
        <th>Definition</th>
        <th>Inclusion</th>
      </tr>
      <tr>
        <td>id</td>
        <td>A random candidate identifier generated by the Relay Service, which effectively maps to the created Channel; this SHOULD match the XML Nmtoken production <note>See &lt;<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>&gt;</note> so that XML character escaping is not needed for characters such as '&amp;'. In some situations the Jingle session identifier might have security implications. See &rfc4086; regarding requirements for randomness.</td>
        <td>REQUIRED on response, NOT RECOMMENDED on requests</td>
      </tr>      
      <tr>
        <td>host</td>
        <td>The IP address or Host address of the Relay Channel.</td> 
        <td>REQUIRED on response</td>
      </tr>
      <tr>
        <td>localport</td>
        <td>The port number to be used by the channel requester.</td> 
        <td>REQUIRED on response</td>
      </tr>
      <tr>
        <td>remoteport</td>
        <td>The port number to be offered to the remote party.</td> 
        <td>REQUIRED on response</td>
      </tr>
      <tr>
        <td>protocol</td>
        <td>The protocol supported by the retrieved channel.</td> 
        <td>REQUIRED on response</td>
      </tr>
      <tr>
        <td>maxkbps</td>
        <td>The maximum bandwidth supported by the channel.</td> 
        <td>OPTIONAL on response, NOT RECOMMENDED on requests.</td>
      </tr>
      <tr>
        <td>expire</td>
        <td>The maximum amount of seconds that the channel can stay without receiving packets, without being deactivated and closed.</td> 
        <td>REQUIRED</td>
      </tr>
    </table>
  <section3 topic="Host Attribute" anchor="def-host">
    <p>The value of the 'host' attribute MUST be one IP address or a DNS resolvable address. That is the address to be used on candidate offering and also the IP to be used when sending out the media traffic.</p>
  </section3>
  <section3 topic="Localport Attribute" anchor="def-localport">
    <p>The value of the 'localport' attribute MUST be a valid IP Port number. This port MUST be used as the media traffic destination port of the channel requester. Session Initiator and responder MUST NOT offer this port.</p>
    <p>The rule is simple and unique, the requester of the channel MUST send the media streams to 'localport' and use 'remoteport' in the 'candidate' element to be offered in the Jingle Session.</p>
    <p>For transparent compatibility with major RTP Proxy Deployments, an RCTP Port is allocated and defined by default at Localport Attribute Value plus one. (Localport + 1)</p>
  </section3>
  <section3 topic='Remoteport Attribute' anchor='def-remoteport'>
    <p>The value of the 'remoteport' attribute MUST be a valid IP Port number. This port MUST be used as media traffic destination port of the other party. Channel requester MUST use this port value in the candidate offer in combination with the 'host' attribute. Channel requester MUST NOT send any media stream to this port.</p>
    <p>For transparent compatibility with major RTP Proxy Deployments, an RCTP Port is allocated and defined by default at Remoteport Attribute Value plus one. (Localport + 1)</p>
  </section3>  
  <section3 topic='Protocol Attribute' anchor='def-protocol'>
    <p>The value of the 'protocol' attribute MUST be a valid protocol value: 'udp' or 'tcp' as also defined in the <link url='#schema'>XML Schema</link></p>
  </section3>  
    <section3 topic='Maxkbps Attribute' anchor='def-maxkbps'>
    <p>The value of the 'maxkbps' attribute MUST be a valid integer value representing the maximum kilobits per seconds the channel supports. This attribute is optional and MAY be used in Relay Channel with bandwidth limitation.</p>
  </section3>
    <section3 topic='Expire Attribute' anchor='def-expire'>
    <p>The value of the 'expire' attribute MUST be a valid integer value representing the maximum seconds that the channel can stay without receiving any traffic without being deactivated and closed. This attribute is required and SHOULD be used in all Relay Channels.</p>
  </section3>
</section2>
  <section2 topic="Services Element" anchor="def-services">
    <p>The &SERVICES; element MAY be empty or contain &RELAY; and/or &TRACKER; elements.</p>
    <p>The attributes of the &RELAY; and &TRACKER; element are as follows.</p>
    <table caption="Attributes of Relay and Tracker Elements">
      <tr>
        <th>Attribute</th>
        <th>Definition</th>
        <th>Inclusion</th>
      </tr>
      <tr>
        <td>policy</td>
        <td>The policy of the service. If the service is public, MUST be 'public' if it is restricted to roster, MUST be 'roster'.</td>
        <td>REQUIRED</td>
      </tr>      
      <tr>
        <td>address</td>
        <td>For Relay and Tracker Services the JID. For STUN Service the IP or Host address.</td>
        <td>REQUIRED</td>
      </tr>
      <tr>
        <td>protocol</td>
        <td>The protocol supported by the retrieved service.</td> 
        <td>REQUIRED</td>
      </tr>
      <tr>
        <td>port</td>
        <td>The port number of the STUN service. This field is only used in STUN Service entries.</td>
        <td>REQUIRED for STUN entries</td>
      </tr>
    </table>
</section2>    
</section1>
  <section1 topic="Determining Support" anchor="support">
    <p>To advertise its support for the Jingle Nodes support, when replying to &xep0030; information requests an entity MUST return URNs for any version of this protocol that the entity supports -- e.g., "http://jabber.org/protocol/jinglenodes" for this version&VNOTE;.</p>
    <p>If the entity supports, Jingle Nodes as a Tracker, it MUST reply to &xep0030; with "http://jabber.org/protocol/jinglenodes". If it also provides the Jingle Nodes Relay Services, it MUST reply with the URN "http://jabber.org/protocol/jinglenodes#channel".</p>
    <p>For optimization purpose the Client SHOULD check for Jingle Nodes support based on entity presence capabilities &xep0115;, which SHOULD contain the keywork "jn-v0".</p>
  <example caption="Service discovery information request"><![CDATA[
<iq from='romeo@montague.lit/orchard'
    id='uw72g176'
    to='juliet@capulet.lit/balcony'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
  ]]></example>
  <example caption="Service discovery information response"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
    id='uw72g176'
    to='romeo@montague.lit/orchard'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
     <feature var='http://jabber.org/protocol/jinglenodes'/>
    <feature var='http://jabber.org/protocol/jinglenodes#channel'/>
  </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="Recommended Use Cases" anchor="usecases">
    <section2 topic="Jingle Client with RAW-UDP Transport without any NAT detection mechanism" anchor="rawudpnostun">
      <p>A Jingle Client with only RAW-UDP support and any NAT detection mechanism can make use of Jingle Nodes. Although the traversal is not guarantee due problem with NAT configuration or firewalls, this method is fairly efficient as most SIP legacy services still provides their services in a similar way, meaning that this has the exactly same accertivity and reliability than regular SIP Services. This method is extremelly useful specially for simple platforms like mobile and clients in early stage of development that still wants to offer voice and video support.</p>
      <p>
        <em>Note: This use case is also similar to a Jingle to SIP Interoperability Service.</em>
      </p>
    </section2>
    <section2 topic="Jingle Client with ICE-UDP Transport with STUN support but no TURN support" anchor="iceudpnoturn">
      <p>A Jingle Client with STUN support but no TURN support can use Relay Node Services as the fallback candidate instead of a TURN candidate. For instance, after a connectivity check proccess, none of the direct candidates worked. The Client can use the Relay Node Candidate as the fallback candidate(the lowest priority candidate).</p>
    </section2>
    <section2 topic="Jingle Client with ICE-UDP Transport with STUN and TURN support" anchor="iceudpstunturn">
      <p>A Jingle Client with STUN and TURN support still might need a Relay Candidate, specially as TURN servers are not widely deployed and don't have any mechanism to publish available services for users. TURN servers also requires specific UDP traffic in specific port ranges which can be blocked by users networks. In this case is very useful to have an extra fallback candidate that can be negotiated via XMPP rather than over UDP.</p>
      <p>
        <em>Note: Jingle Relay Nodes Services are much more likely to be found and be available than TURN servers, as users can also provide Jingle Relay Nodes services themselves or provide a list of known and available services, in this last case behaving a tracker. Is very likely that Jingle Relay Nodes will be available and discovered more easily and often than TURN servers.</em>
      </p>
    </section2>
    <section2 topic="XMPP Client or Component in a Public IP" anchor="clientonpublicip">
      <p>A XMPP Client or Component with direct access to a public IP can potentially provide the UDP Relay Service becaming itself a Jingle Relay Node. The service can intend to provide a public service, or a restricted services based on user preferences, like buddylist, whitelist, blacklist, domain, etc...</p>
      <p>
        <em>Note: It is NOT mandatory to became a Jingle Relay Node. This is OPTIONAL and SHOULD be done with user awareness and concentiment.</em>
      </p>
    </section2>
  </section1>
  <section1 topic="Implementation Notes" anchor="impl">
    <p>When using a candidate provided by a Jingle Relay Service, the Jingle Client MUST set the candidate attribute to 'relay'. In order to make sure the other client won't allocate another channel as well. Which would lead in audio connectivity issues. In brief, if the caller is using a Relay Candidate the calle MUST NOT use another Relay Candidate discovered by itself. If a caller is not using a Relay Candidate(which can be determined by the candidate 'type' attribute) the callee MAY use a Relay Candidate in order to ensure communication.</p>
  </section1>
  <section1 topic="Security Considerations" anchor="security">
          <p>Relay Channels auto expires MUST expire on traffic inactivity. The inactivity timeout recommended is 60 seconds.</p>
    <p>It is heavily recommended that the Super Node implements throttle:</p>
    <ul>
      <p>
        <li>Based on JID, allowing the control of how many concurrent channels an specific JID can have.</li>
      </p>
      <p>
        <li>Based on JID, allowing the control of how many channel requests an specific JID can request in a time period.</li>
      </p>
      <p>
        <li>Based on Bandwidth, allowing the control of how much bandwidth a channel can use. The maximum bandwidth SHOULD be included on the candidate element provided by a Super Node on the attribute maxkbps. If no attribute is present, it means that it has no bandwidth control.</li>
      </p>
      <example caption="Channel Returned by a Node with bandwidth throttle (stub)"><![CDATA[
<channel component='1'
 id='el0747fg11'
 host='200.20.2.10'
 localport='35800'
 remoteport='35802'
 protocol='udp'
 maxkbps='120'/>
  ]]></example>
    </ul>
  </section1>
  <section1 topic='XML Schema' anchor='schema'>
  <code><![CDATA[
<?xml version='1.0' encoding='UTF-8'?>

<xs:schema
    xmlns:xs='http://www.w3.org/2001/XMLSchema'
    targetNamespace='http://jabber.org/protocol/jinglenodes'
    xmlns='http://jabber.org/protocol/jinglenodes'
    elementFormDefault='qualified'>

  <xs:element name='channel'>
        <xs:attribute name='id' type='xs:string' use='required'/>
        <xs:attribute name='host' type='xs:string' use='required'/>
        <xs:attribute name='localport' type='xs:string' use='required'/>
        <xs:attribute name='remoteport' type='xs:string' use='required'/>
  <xs:attribute name='protocol' use='required'>
          <xs:simpleType>
            <xs:restriction base='xs:NCName'>
              <xs:enumeration value='udp'/>
              <xs:enumeration value='tcp'/>
            </xs:restriction>
          </xs:simpleType>
        </xs:attribute>
        <xs:attribute name='maxkbps' type='xs:string' use='optional'/>
        <xs:attribute name='expire' type='xs:string' use='required'/>
  </xs:element>

  <xs:element name='services'>
    <xs:complexType>
      <xs:sequence>
        <xs:element name='relay' 
                    type='serviceElementType'
                    minOccurs='0'
                    maxOccurs='unbounded'/>
        <xs:element name='tracker' 
                    type='serviceElementType'
                    minOccurs='0'
                    maxOccurs='unbounded'/>                    
        <xs:element name='stun' 
                    type='serviceElementType'
                    minOccurs='0'
                    maxOccurs='unbounded'/>                    
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name='serviceElementType'>
    <xs:simpleContent>
      <xs:extension base='empty'>
        <xs:attribute name='address' type='xs:string' use='required'/>
        <xs:attribute name='port' type='xs:string' use='optional'/>
        <xs:attribute name='policy' use='required'>
          <xs:simpleType>
            <xs:restriction base='xs:NCName'>
              <xs:enumeration value='public'/>
              <xs:enumeration value='roster'/>
            </xs:restriction>
          </xs:simpleType>
        </xs:attribute>
        <xs:attribute name='protocol' use='required'>
          <xs:simpleType>
            <xs:restriction base='xs:NCName'>
              <xs:enumeration value='udp'/>
              <xs:enumeration value='tcp'/>
            </xs:restriction>
          </xs:simpleType>
        </xs:attribute>
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:simpleType name='empty'>
    <xs:restriction base='xs:string'>
      <xs:enumeration value=''/>
    </xs:restriction>
  </xs:simpleType>

</xs:schema>
  ]]></code>
</section1>
</xep>
