<?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>Whitespace Keepalive Negotiation</title>
  <abstract>This specification defines a method for negotiating how to send keepalives in XMPP.</abstract>
  &LEGALNOTICE;
  <number>0304</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>Ming</firstname>
    <surname>Ji</surname>
    <email>mingj@cisco.com</email>
    <jid>mingj@cisco.com</jid>
  </author>
  <revision>
    <version>0.1</version>
    <date>2011-08-18</date>
    <initials>psa</initials>
    <remark><p>Initial published version.</p></remark>
  </revision>
  <revision>
    <version>0.0.1</version>
    <date>2011-07-19</date>
    <initials>mj</initials>
    <remark><p>First draft.</p></remark>
  </revision>
</header>

<section1 topic='Introduction' anchor='intro'>
  <p>&rfc6120; specifies that XMPP servers and clients can send whitespace characters between first-level elements of an XML stream as a way to maintain the state of the stream. These "whitespace keepalives" are widely used on the XMPP network. However, currently it is not possible to negotiate the frequency of sending keepalives, or even whether to send keepalives at all (the server simply sends them according to its own schedule). Because certain kinds of devices might not want to use keepalives, or might wish to receive keepalives more frequently or less frequently than the server's default, this specification defines a method for negotiating how to send whitespace keepalives between an XMPP server and an XMPP client (this method could also be used between two servers, although that usage is expected to be rare).</p>
</section1>
<section1 topic='Protocol' anchor='protocol'>
  <p>The protocol defined in this document enables a client negotiate the time interval between whitespace keepalives, within a range determined by the server. Normally, the client starts the negotiation since not all kinds of the client support the feature.</p>
  <p>The protocol defines a keepalive element and the normal negotaition process is quite simple, demonstrated as following:</p>
  <ol start='1'>
    <li>Server announces keepalive feature with a range of time intervals.</li>
    <li>Client starts the keepalive negotiation by specifying a time interval. </li>
    <li>Server checks the value and relpies with success or failure.</li>
  </ol>
  <p>Then server and client send whitespace keepalive to each other at the agreed time interval.</p>
</section1>

<section1 topic='Use Cases' anchor='usecases'>
  <section2 topic='Stream Feature' anchor='feature'>
    <p>During the stream negotiation process, the server can advertise this feature. The feature is negotiated after the resource binding. (See &xep0170; regarding the recommended order of stream feature negotiation.)</p>
    <example caption='Server lists feature in the stream negotiation stage'><![CDATA[
C: <stream:stream
           to='example.com'
           version='1.0'
           xmlns='jabber:client'
           xmlns:stream='http://etherx.jabber.org/streams'>

C: <stream:stream
           from='example.com'
           id='KskA2O2BEn5mL7mABTq9X3DTPHO44vAMaIg1nG9O1vo'
           version='1.0'
           xmlns='jabber:client'
           xmlns:stream='http://etherx.jabber.org/streams'>
S:  <stream:features>
        <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
        <keepalive xmlns='urn:xmpp:keepalive:0'>
          <interval min='60' max='300'/>
        </keepalive>
    </stream:features>
]]></example>
  </section2>

  <section2 topic='Negotiate Keepalive' anchor='negotiate'>
    <p>Client negotiates the keepalive feature by providing an interval value based on server limits and its own condition. The interval SHOULD be a positive interger, and zero is invalid.</p>
    <example caption='Client sends its negotiating keepalive time interval'><![CDATA[
<iq from='client@example.com/foo' id='p03ns61g' to='example.com' type='set'>
  <keepalive xmlns='urn:xmpp:keepalive:0'>
    <interval>60</interval>
  </keepalive>
</iq>
]]></example>
    <p>The server checks the keepalive interval value and returns a success:</p>
    <example caption='Server returns success of keepalive negotiation'><![CDATA[
<iq from='example.com' id='p03ns61g' to='client@example.com/foo' type='result'/>
]]></example>
    <p>If a problem occurs, the server returns an error (in this example, the client sent a value outside the range of the server's preferences):</p>
    <example caption='Server returns failure of keepalive negotiation'><![CDATA[
<iq from='example.com' id='p03ns61g' to='client@example.com/foo' type='error'>
  <error type='cancel'>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>
]]></example>
    <p>Then both the server and the client send whitespace keepalives at the interval of the negotiated value. The server SHOULD check to see if has received keepalives and MAY drop the connection if it has not received a keepalive for a period of time significantly longer than the negotiated value (the client MAY also implement this behavior).</p>
  </section2>
</section1>

<section1 topic='Implementation Notes' anchor='impl'>
  <p>Several things need to be noted:</p>
  <ol start='1'>
    <li>Both parties SHOULD keep a record of the keepalive status and honor the negotiated value when allowing stream resumption and session recreation. See &xep0198;</li>
    <li>The length of the keepalive interval depends on the service type and network environment. Implementations are encouraged to use appropriate values based on implementation and deployment experience.</li>
  </ol>
</section1>

<section1 topic='Security Considerations' anchor='security'>
  <p>During negotiation, the server MUST check the keepalive interval value and reject any invalid values.</p>
</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>The &REGISTRAR; is requested to issue an initial namespace 'urn:xmpp:keepalive:0'</p>
  </section2>
  <section2 topic='Stream Features' anchor='registrar-stream'>
    <p>The &REGISTRAR; is requested to issue an initial stream feature namespace 'urn:xmpp:keepalive:0'.</p>
  </section2>
</section1>

<section1 topic='XML Schema' anchor='schema'>
  <code><![CDATA[
<?xml version='1.0' encoding='utf-8'?>

<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'
            targetNamespace='urn:xmpp:keepalive:0'
            xmlns='urn:xmpp:keepalive:0'
            elementFormDefault='unqualified'>

  <xsd:element name='keepalive'>
    <xsd:complexType>
      <xsd:attribute name='min' type='positiveShort' use='optional'/>
      <xsd:attribute name='max' type='positiveShort' use='optional'/>
      <xsd:assert test='@min le @max'/>
      <xsd:element name='interval' type='positiveShort' minOccurs='0' maxOccurs='1'/>
    </xsd:complexType>
  </xsd:element>

  <xsd:simpleType name='positiveShort'>
    <xsd:restriction base='xsd:unsignedShort'>
      <xsd:minExclusive value='0'/>
    </xsd:restriction>
  </xsd:simpleType>

</xsd:schema>

]]></code>
</section1>

<section1 topic='Acknowledgements' anchor='ack'>
  <p>Thanks to Matt Miller and Peter Saint-Andre for their feedback.</p>
</section1>

</xep>
