mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-28 04:02:20 -05:00
124 lines
5.0 KiB
XML
124 lines
5.0 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>Best Practice for Closing Idle Streams</title>
|
||
|
<abstract>This document specifies best practice for closing an idle XMPP stream.</abstract>
|
||
|
&LEGALNOTICE;
|
||
|
<number>0190</number>
|
||
|
<status>Experimental</status>
|
||
|
<type>Informational</type>
|
||
|
<jig>Standards JIG</jig>
|
||
|
<dependencies>
|
||
|
<spec>XMPP Core</spec>
|
||
|
</dependencies>
|
||
|
<supersedes/>
|
||
|
<supersededby/>
|
||
|
<shortname>N/A</shortname>
|
||
|
<author>
|
||
|
<firstname>Carlo</firstname>
|
||
|
<surname>von Loesch</surname>
|
||
|
<email>lynX@jabber.getting.psyced.org</email>
|
||
|
<jid>lynX@ve.symlynX.com</jid>
|
||
|
</author>
|
||
|
<revision>
|
||
|
<version>0.1</version>
|
||
|
<date>2006-07-26</date>
|
||
|
<initials>psa</initials>
|
||
|
<remark><p>Initial JEP version.</p></remark>
|
||
|
</revision>
|
||
|
<revision>
|
||
|
<version>0.0.2</version>
|
||
|
<date>2006-06-30</date>
|
||
|
<initials>cvl</initials>
|
||
|
<remark>Second draft.</remark>
|
||
|
</revision>
|
||
|
<revision>
|
||
|
<version>0.0.1</version>
|
||
|
<date>2006-05-31</date>
|
||
|
<initials>cvl</initials>
|
||
|
<remark>First draft.</remark>
|
||
|
</revision>
|
||
|
</header>
|
||
|
|
||
|
<section1 topic='Introduction' anchor='intro'>
|
||
|
&BISNOTE;
|
||
|
<p><cite>RFC 3920</cite> offers several ways on how to terminate an XMPP stream, but
|
||
|
doesn't always make a clear statement which one to take. This can lead
|
||
|
to faulty implementations. In particular, closing a stream that hasn't
|
||
|
been in use for a while is very often achieved using a connection-timeout
|
||
|
error, then closing the socket. This can lead to loss of data. Therefore
|
||
|
this document proposes a practice that will avoid such data loss.</p>
|
||
|
</section1>
|
||
|
|
||
|
<!-- section1 topic='How Not to Close an Idle Stream' anchor='dont'>
|
||
|
<section2 topic='Using a connection-timeout error'>
|
||
|
<p>Although RFC 3920 provides for an error condition
|
||
|
<code><![CDATA[ <connection-timeout/> ]]></code>
|
||
|
such error MUST NOT be used to close an idle connection, unless
|
||
|
the sender is expecting a message from the other entity, and a timeout
|
||
|
has occured instead, like during a dialback or SASL negotiation.</p>
|
||
|
<p>This has been a popular strategy, but it can cause frequent data
|
||
|
loss each time a connection is timeouted while the other entity just
|
||
|
started transmitting data.</p>
|
||
|
</section2>
|
||
|
<section2 topic='Closing the TCP connection without warning'>
|
||
|
<p>Several implementations even close the TCP connection without an
|
||
|
error or a stream shutdown. This has the same effects of data loss
|
||
|
as the friendlier variant mentioned before. Additionally it leaves
|
||
|
the other side wondering if the termination was intentional or erroneous.
|
||
|
This method MUST NOT be put into practice.</p>
|
||
|
</section2>
|
||
|
</section1 -->
|
||
|
|
||
|
<section1 topic='How to Close an Idle Stream' anchor='do'>
|
||
|
<section2 topic='Handshake Stream Shutdown'>
|
||
|
<p>As shown in the basic "session" example in the
|
||
|
Simplified Stream Examples (4.8 of RFC 3920),
|
||
|
it is a valid transaction to close the outgoing stream by sending
|
||
|
<code><![CDATA[ </stream:stream> ]]></code>
|
||
|
then wait for the other entity to close its stream, like this:
|
||
|
<code><![CDATA[ </stream:stream> ]]></code>
|
||
|
and shut down the underlying TCP connection.</p>
|
||
|
<p>This will ensure that, should the other entity have transmitted
|
||
|
any data, it will arrive and be processed before the TCP connection
|
||
|
is terminated.</p>
|
||
|
<p>Special care MUST be taken that under no circumstance further
|
||
|
packets may be written to the socket after the stream was closed,
|
||
|
until the other side shuts down the socket.</p>
|
||
|
<p>On the outgoing TCP connection you MAY do a read-only shutdown
|
||
|
of the socket, as long as the other side will safely be able to
|
||
|
send its stream termination token.</p>
|
||
|
</section2>
|
||
|
<section2 topic='Handshake Failure'>
|
||
|
<p>In case the other entity fails to close the stream within a
|
||
|
reasonable time frame, the entity that started the handshake is
|
||
|
entitled to terminate the TCP connection. Since the stream has
|
||
|
already been closed, it is correct not to produce an error condition.</p>
|
||
|
</section2>
|
||
|
</section1>
|
||
|
|
||
|
<section1 topic='Conclusion' anchor='conclusion'>
|
||
|
<p>Please update your implementations to use the 'Handshake Stream Shutdown'
|
||
|
strategy when shutting down streams you no longer need.</p>
|
||
|
<p>Even not to shut down idle streams at all is a better strategy than to
|
||
|
shut them down by creating an error condition, so if your application
|
||
|
has no necessity for shutting down idle connections, just don't do it.</p>
|
||
|
</section1>
|
||
|
|
||
|
<section1 topic='Security Considerations' anchor='security'>
|
||
|
<p>This proposal introduces no new security aspects.</p>
|
||
|
</section1>
|
||
|
<section1 topic='IANA Considerations' anchor='iana'>
|
||
|
<p>This proposal requires no interaction with &IANA;.</p>
|
||
|
</section1>
|
||
|
<section1 topic='Jabber Registrar Considerations' anchor='registrar'>
|
||
|
<p>This proposal requires no interaction with the ®ISTRAR;.</p>
|
||
|
</section1>
|
||
|
|
||
|
</jep>
|