<?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>Stream Compression</title>
    <abstract>This document defines an XMPP protocol extension for negotiating compression of XML streams, especially in situations where standard TLS compression cannot be negotiated. The protocol provides a modular framework that can accommodate a wide range of compression algorithms; the ZLIB compression algorithm is mandatory-to-implement, but implementations may support other algorithms in addition.</abstract>
    &LEGALNOTICE;
    <number>0138</number>
    <status>Final</status>
    <type>Standards Track</type>
    <sig>Standards</sig>
    <dependencies>
      <spec>XMPP Core</spec>
    </dependencies>
    <supersedes/>
    <supersededby/>
    <shortname>compress</shortname>
    <schemaloc>
      <ns>compress</ns>
      <url>http://www.xmpp.org/schemas/compress.xsd</url>
    </schemaloc>
    <schemaloc>
      <ns>feature</ns>
      <url>http://www.xmpp.org/schemas/compress-feature.xsd</url>
    </schemaloc>
    <registry/>
    &hildjj;
    &stpeter;
    <revision>
      <version>2.0</version>
      <date>2009-05-27</date>
      <initials>psa</initials>
      <remark><p>Per a vote of the XMPP Council, advanced status to Final.</p></remark>
    </revision>
    <revision>
      <version>1.3</version>
      <date>2007-09-26</date>
      <initials>psa</initials>
      <remark><p>Moved specification of LZW algorithm to XEP-0229.</p></remark>
    </revision>
    <revision>
      <version>1.2</version>
      <date>2007-08-22</date>
      <initials>psa</initials>
      <remark><p>Clarified when compression shall be considered to start; per XEP-0170, specified that compression should be negotiated after SASL.</p></remark>
    </revision>
    <revision>
      <version>1.1</version>
      <date>2005-12-14</date>
      <initials>psa</initials>
      <remark><p>More completely specified error handling; mentioned LZW (DCLZ) method.</p></remark>
    </revision>
    <revision>
      <version>1.0</version>
      <date>2005-06-16</date>
      <initials>psa</initials>
      <remark><p>Per a vote of the Jabber Council, advanced status to Draft.</p></remark>
    </revision>
    <revision>
      <version>0.5</version>
      <date>2005-05-18</date>
      <initials>psa</initials>
      <remark><p>Modifications to address Council feedback: used RFC 3920 terminology; specified error conditions; specified ZLIB as mandatory to implement.</p></remark>
    </revision>
    <revision>
      <version>0.4</version>
      <date>2005-05-11</date>
      <initials>psa</initials>
      <remark><p>Corrected several errors in the schemas.</p></remark>
    </revision>
    <revision>
      <version>0.3</version>
      <date>2005-03-28</date>
      <initials>psa</initials>
      <remark><p>Specified compression methods registry.</p></remark>
    </revision>
    <revision>
      <version>0.2</version>
      <date>2004-09-28</date>
      <initials>psa</initials>
      <remark><p>Fixed TLS text per list discussion.</p></remark>
    </revision>
    <revision>
      <version>0.1</version>
      <date>2004-07-16</date>
      <initials>jjh/psa</initials>
      <remark><p>Initial version.</p></remark>
    </revision>
  </header>

  <section1 topic='Introduction' anchor='intro'>
    <p>&xmppcore; specifies the use of Transport Layer Security (TLS; see &rfc4346;) for encryption of XML streams, and TLS includes the ability to compress encrypted traffic (see &rfc3749;). However, not all computing platforms are able to implement TLS, and traffic compression may be desirable for communication by applications on such computing platforms. This document defines a mechanism for negotiating the compression of XML streams outside the context of TLS.</p>
  </section1>

  <section1 topic='Use Case' anchor='usecase'>
    <p>The protocol flow is as follows:</p>
    <example caption='Receiving Entity Offers Stream Compression Feature'><![CDATA[
<stream:features>
  <starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
  <compression xmlns='http://jabber.org/features/compress'>
    <method>zlib</method>
    <method>lzw</method>
  </compression>
</stream:features>
    ]]></example>
    <p>Note: The &lt;compression/&gt; element MUST contain at least one &lt;method/&gt; child element. Each &lt;method/&gt; element MUST contain XML character data that specifies the name of a compression method, and such method names SHOULD be registered as described in the <link url='#registrar-methods'>Compression Methods Registry</link> section of this document. The methods SHOULD be provided in order of preference.</p>
    <p>The initiating entity then MAY request compression by specifying one of the methods advertised by the receiving entity:</p>
    <example caption='Initiating Entity Requests Stream Compression'><![CDATA[
<compress xmlns='http://jabber.org/protocol/compress'>
  <method>zlib</method>
</compress>
    ]]></example>
    <p>Note: If the initiating entity did not understand any of the advertised compression methods, it SHOULD ignore the compression option and proceed as if no compression methods were advertised.</p>
    <p>If the initiating entity requests a stream compression method that is not supported by the receiving entity, the receiving entity MUST return an &lt;unsupported-method/&gt; error:</p>
    <example caption='Receiving Entity Reports That Method is Unsupported'><![CDATA[
<failure xmlns='http://jabber.org/protocol/compress'>
  <unsupported-method/>
</failure>
    ]]></example>
    <p>If the receiving entity finds the requested method unacceptable or unworkable for any other reason, it MUST return a &lt;setup-failed/&gt; error:</p>
    <example caption='Receiving Entity Reports That Negotiation of Stream Compression Failed'><![CDATA[
<failure xmlns='http://jabber.org/protocol/compress'>
  <setup-failed/>
</failure>
    ]]></example>
    <p>Note: Failure of the negotiation SHOULD NOT be treated as an unrecoverable error and therefore SHOULD NOT result in a stream error. In particular, the initiating entity is free to retry the compression negotiation if it fails.</p>
    <p>If no error occurs, the receiving entity MUST inform the initiating entity that compression has been successfully negotiated:</p>
    <example caption='Receiving Entity Acknowledges Negotiation of Stream Compression'><![CDATA[
<compressed xmlns='http://jabber.org/protocol/compress'/>
    ]]></example>
    <p>Both entities MUST now consider the previous (uncompressed) stream to be null and void, just as with TLS negotiation and SASL negotiation (as specified in <cite>RFC 3920</cite>) and MUST begin compressed communications with a new (compressed) stream. Therefore the initiating entity MUST initiate a new stream to the receiving entity:</p>
    <example caption='Initiating Entity Initiates New (Compressed) Stream'><![CDATA[
<stream:stream
    xmlns='jabber:client'
    xmlns:stream='http://etherx.jabber.org/streams'
    to='shakespeare.lit'>
    ]]></example>
    <p>If compression processing fails after the new (compressed) stream has been established, the entity that detects the error SHOULD generate a stream error and close the stream:</p>
    <example caption='Entity Closes Stream Because of a Processing Error'><![CDATA[
<stream:error>
  <undefined-condition xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
  <failure xmlns='http://jabber.org/protocol/compress'/>
    <processing-failed/>
  </failure>
</stream:error>
</stream:stream>
    ]]></example>
  </section1>

<!--
  <section1 topic='Feature Negotiation (Optional)' anchor='negotiation'>
    <p>The initiating entity and receiving entity MAY support &xep0020; for more fine-grained negotiation of parameters (such as compression levels). Such support is OPTIONAL, and the initiating entity should expect that the receiving entity may not support feature negotiation. Because use of &xep0030; to discover negotiable features is inconvenient during stream negotiation, the initiating entity SHOULD negotiate only features that are registered for use with the 'http://jabber.org/protocol/compress' FORM_TYPE as described in the <link url="#registrar-formtype">Field Standardization</link> section of this document.</p>
    <p>The initiating entity MAY include a feature negotiation child within the initial &lt;compress/&gt; element requesting stream compression:</p>
    <example caption='Initiating Entity Requests Stream Compression (With Feature Negotiation)'><![CDATA[
<compress xmlns='http://jabber.org/protocol/compress'>
  <method>foobar</method>
  <feature xmlns='http://jabber.org/protocol/feature-neg'>
    <x xmlns='jabber:x:data' type='submit'>
      <field type='hidden' var='FORM_TYPE'>
         <value>http://jabber.org/protocol/compress/method/foobar</value>
      </field>
      <field var='foobar-compression-level'>
         <value>3</value>
      </field>
    </x>
  </feature>
</compress>
    ]]></example>
    <p>If the receiving entity does not support the use of feature negotiation within stream compression, it MUST ignore the &lt;feature/&gt; element.</p>
    <p>If the receiving entity does not support one or more of the included features, it MUST return a &lt;failure/&gt; containing an XMPP &feature; error and SHOULD specify the feature(s) not implemented in an XMPP &lt;text/&gt; element.</p>
    <example caption="Receiving entity does not support a feature"><![CDATA[
<compress xmlns='http://jabber.org/protocol/compress'>
  <failure>
    <feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>foobar-compression-level</text>
  </failure>
</compress>
    ]]></example>
    <p>If the receiving entity supports none of the included options for a certain feature, it MUST return a &lt;failure/&gt; containing an XMPP &notacceptable; error and SHOULD specify the option(s) not supported in an XMPP &lt;text/&gt; element.</p>
    <example caption="Receiving entity does not support an option"><![CDATA[
<compress xmlns='http://jabber.org/protocol/compress'>
  <failure>
    <not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    <text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>foobar-compression-level: 3</text>
</compress>
    ]]></example>
  </section1>
-->

  <section1 topic='Business Rules' anchor='bizrules'>
    <p>The following business rules apply:</p>
    <ul>
      <li>If stream compression is negotiated, it MUST be used in both directions.</li>
      <li>TLS compression and stream compression SHOULD NOT be used simultaneously.</li>
      <li>Stream compression MAY be offered after TLS negotiation if TLS compression fails.</li>
    </ul>
    <p>For detailed recommendations regarding the order of stream feature negotiation, refer to &xep0170;.</p>
  </section1>

  <section1 topic='Mandatory-to-Implement Technologies' anchor='mandatory'>
    <p>Support for the ZLIB compression method as specified in &rfc1950; is REQUIRED.</p>
    <p>All other methods are OPTIONAL; such methods may be defined in future specifications or by registration as described in the <link url='#registrar-methods'>Compression Methods Registry</link> section of this document.</p>
  </section1>

  <section1 topic='Optional Technologies' anchor='optional'>
    <p>Implementations MAY support the following methods in addition to ZLIB:</p>
    <ul>
      <li>&xep0229;</li>
    </ul>
  </section1>

  <section1 topic='Implementation Notes' anchor='impl'>
    <p>When using ZLIB for compression, the sending application SHOULD complete a partial flush of ZLIB when its current send is complete. Note that this statement is deliberately somewhat vague: the sending application may end up performing this partial flush after sending every XML stanza, but on the other hand may perform the partial flush only after sending a group of stanzas that have been queued up for delivery. When to flush the state of the compression application is up to the sending application.</p>
  </section1>

  <section1 topic='Security Considerations' anchor='security'>
    <p>Stream encryption via TLS (as defined in <cite>RFC 3920</cite>) and stream compression (as defined herein) are not mutually exclusive, but stream encryption via TLS MUST be negotiated before negotiation of stream compression in order to secure the stream.</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='Stream Features' anchor='registrar-stream'>
      <p>The &REGISTRAR; includes 'http://jabber.org/features/compress' in its registry of stream features.</p>
    </section2>
    <section2 topic='Protocol Namespaces' anchor='registrar-ns'>
      <p>The XMPP Registrar includes 'http://jabber.org/protocol/compress' in its registry of protocol namespaces.</p>
    </section2>
    <section2 topic='Compression Methods Registry' anchor='registrar-methods'>
      <p>The XMPP Registrar maintains a registry of compression methods at &COMPRESSMETHODS;.</p>
      <section3 topic='Process' anchor='registrar-methods-process'>
        &REGPROCESS;
        <code><![CDATA[
<method>
  <name>the XML character data of the method element</name>
  <desc>a natural-language description of the compression method</desc>
  <doc>the document that specifies or registers the compression method</doc>
</method>
        ]]></code>
        <p>The registrant may register more than one compression method at a time, each contained in a separate &lt;method/&gt; element.</p>
      </section3>
      <section3 topic='Registration' anchor='registrar-methods-init'>
        <code><![CDATA[
<method>
  <name>zlib</name>
  <desc>the ZLIB compression method</desc>
  <doc>RFC 1950</doc>
</method>
        ]]></code>
      </section3>
    </section2>
    <!--
    <section2 topic='Field Standardization' anchor='registrar-formtype'>
      <p>&xep0068; defines a process for standardizing the fields used within Data Forms qualified by a particular namespace. Reserved fields shall be registered with the XMPP Registrar as necessary.</p>
    </section2>
    -->
  </section1>

  <section1 topic='XML Schemas' anchor='schemas'>
    <section2 topic='Stream Feature' anchor='schemas-stream'>
      <code><![CDATA[
<?xml version='1.0' encoding='UTF-8'?>

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

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      XEP-0138: http://www.xmpp.org/extensions/xep-0138.html
    </xs:documentation>
  </xs:annotation>

  <xs:element name='compression'>
    <xs:complexType>
      <xs:sequence>
        <xs:element name='method' type='xs:NCName' maxOccurs='unbounded'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

</xs:schema>
      ]]></code>
    </section2>
    <section2 topic='Protocol Namespace' anchor='schemas-protocol'>
      <code><![CDATA[
<?xml version='1.0' encoding='UTF-8'?>

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

  <xs:annotation>
    <xs:documentation>
      The protocol documented by this schema is defined in
      XEP-0138: http://www.xmpp.org/extensions/xep-0138.html
    </xs:documentation>
  </xs:annotation>

  <xs:import namespace='urn:ietf:params:xml:ns:xmpp-stanzas'
             schemaLocation='http://xmpp.org/schemas/stanzaerror.xsd'/>

  <xs:element name='compress'>
    <xs:complexType>
      <xs:sequence>
        <xs:element name='method' type='xs:NCName' minOccurs='1' maxOccurs='unbounded'/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:element name='compressed' type='empty'/>

  <xs:element name='failure'>
    <xs:complexType>
      <xs:choice>
        <xs:element name='setup-failed' type='empty'/>
        <xs:element name='processing-failed' type='empty'/>
        <xs:element name='unsupported-method' type='empty'/>
        <xs:sequence xmlns:err='urn:ietf:params:xml:ns:xmpp-stanzas'>
          <xs:group ref='err:stanzaErrorGroup'/>
          <xs:element ref='err:text' minOccurs='0'/>
        </xs:sequence>
      </xs:choice>
    </xs:complexType>
  </xs:element>

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

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

</xep>