<?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 <compression/> element MUST contain at least one <method/> child element. Each <method/> 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 <unsupported-method/> 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 <setup-failed/> 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 <compress/> 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 <feature/> element.</p> <p>If the receiving entity does not support one or more of the included features, it MUST return a <failure/> containing an XMPP &feature; error and SHOULD specify the feature(s) not implemented in an XMPP <text/> 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 <failure/> containing an XMPP ¬acceptable; error and SHOULD specify the option(s) not supported in an XMPP <text/> 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 ®ISTRAR; 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'> ®PROCESS; <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 <method/> 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>