mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-28 12:12:22 -05:00
433 lines
18 KiB
XML
433 lines
18 KiB
XML
|
<?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>Message Carbons</title>
|
||
|
<abstract>In order to keep all IM clients for a user engaged in a conversation, outbound messages are carbon-copied to all interested resources.</abstract>
|
||
|
&LEGALNOTICE;
|
||
|
<number>0280</number>
|
||
|
<status>Experimental</status>
|
||
|
<type>Standards Track</type>
|
||
|
<sig>Standards</sig>
|
||
|
<approver>Council</approver>
|
||
|
<dependencies>
|
||
|
<spec>XMPP Core</spec>
|
||
|
<spec>XEP-0001</spec>
|
||
|
<spec>XEP-0030</spec>
|
||
|
<spec>XEP-0085</spec>
|
||
|
</dependencies>
|
||
|
<supersedes>
|
||
|
<spec>XEP-0259</spec>
|
||
|
</supersedes>
|
||
|
<supersededby/>
|
||
|
<shortname>carbons</shortname>
|
||
|
<author>
|
||
|
<firstname>Joe</firstname>
|
||
|
<surname>Hildebrand</surname>
|
||
|
<email>jhildebr@cisco.com</email>
|
||
|
<jid>jhildebr@cisco.com</jid>
|
||
|
</author>
|
||
|
<revision>
|
||
|
<version>0.1</version>
|
||
|
<date>2010-05-03</date>
|
||
|
<initials>psa</initials>
|
||
|
<remark><p>Initial published version.</p></remark>
|
||
|
</revision>
|
||
|
<revision>
|
||
|
<version>0.0.2</version>
|
||
|
<date>2010-04-21</date>
|
||
|
<initials>jjh</initials>
|
||
|
<remark><p>Updated after further analysis of edge cases.</p></remark>
|
||
|
</revision>
|
||
|
<revision>
|
||
|
<version>0.0.1</version>
|
||
|
<date>2010-02-25</date>
|
||
|
<initials>jjh</initials>
|
||
|
<remark><p>First draft.</p></remark>
|
||
|
</revision>
|
||
|
</header>
|
||
|
<section1 topic='Introduction' anchor='intro'>
|
||
|
<p>At the time of original writing of this XEP, many XMPP servers
|
||
|
handle message stanzas sent to a user@host (or "bare") JID with no
|
||
|
resource by delivering that message only to the resource with the
|
||
|
highest priority for the target user. Some server implementations,
|
||
|
however, have chosen to send these messages to all of the online
|
||
|
resources for the target user. If the target user is online with
|
||
|
multiple resources when the original message is sent, a conversation
|
||
|
ensues on one of the user's devices; if the user subsequently
|
||
|
switches devices, parts of the conversation may end up on the
|
||
|
alternate device, causing the user to be confused, misled, or
|
||
|
annoyed.</p>
|
||
|
|
||
|
<p>This XEP defines an approach for ensuring that all of my devices
|
||
|
get both sides of all conversations in order to avoid user
|
||
|
confusion. As a pleasant side-effect, information about the current
|
||
|
state of a conversation is shared between all of a user's clients
|
||
|
that implement this protocol.</p>
|
||
|
</section1>
|
||
|
|
||
|
<section1 topic='Requirements' anchor='reqs'>
|
||
|
<ul>
|
||
|
<li>Large changes SHOULD NOT be required to existing servers</li>
|
||
|
<li>Clients that do not implement the new protocol MUST be able
|
||
|
participate in conversations</li>
|
||
|
<li>Clients that do not implement the new protocol MUST NOT
|
||
|
receive a large number of new partial conversations</li>
|
||
|
<li>Clients that do not implement the new protocol MUST NOT
|
||
|
receive protocol they do not expect</li>
|
||
|
<li>All clients that turn on the new protocol MUST be able to see
|
||
|
all inbound chat-type messages.</li>
|
||
|
<li>All clients that turn on the new protocol MUST be able to see
|
||
|
all outbound chat-type messages from all of the resources of the
|
||
|
user, regardless of whether the clients for the other resources
|
||
|
have implemented the new protocol.</li>
|
||
|
</ul>
|
||
|
</section1>
|
||
|
<section1 topic='Use Cases' anchor='usecases'>
|
||
|
<section2 topic='Discovering Support' anchor='disco'>
|
||
|
<p>If a server implements the Message Carbons capability, it MUST specify the
|
||
|
'urn:xmpp:carbons:0' feature in its service discovery
|
||
|
information features as specified in &xep0030; or section 6.3 of &xep0115;.
|
||
|
Clients MUST NOT enable or disable Carbons if their server does
|
||
|
not support this feature.</p>
|
||
|
<example caption='Client requests information about its own server'><![CDATA[
|
||
|
<iq type='get'
|
||
|
from='romeo@montague.net/orchard'
|
||
|
id='info1'>
|
||
|
<query xmlns='http://jabber.org/protocol/disco#info'/>
|
||
|
</iq>]]></example>
|
||
|
<example caption='Server responds with Carbons feature'><![CDATA[
|
||
|
<iq type='get'
|
||
|
to='romeo@montague.net/home'
|
||
|
from='montague.net'
|
||
|
id='info1'>
|
||
|
<query xmlns='http://jabber.org/protocol/disco#info'>
|
||
|
...
|
||
|
<feature var='urn:xmpp:carbons:0'/>
|
||
|
...
|
||
|
</query>
|
||
|
</iq>]]></example>
|
||
|
</section2>
|
||
|
|
||
|
<section2 topic='Enabling Carbons' anchor='enabling'>
|
||
|
<p>Servers MUST NOT enable the Carbons protocol for a client by
|
||
|
default, since unmodified clients might be confused by the new
|
||
|
protocol. When a client wants to participate in the Carbons
|
||
|
protocol, it sends an IQ set to enable the protocol.</p>
|
||
|
<example caption='Client enables Carbons'><![CDATA[
|
||
|
<iq type='set' id='enable1'>
|
||
|
<carbons var='urn:xmpp:carbons:0' mode='enable'/>
|
||
|
</iq>]]></example>
|
||
|
<p>Carbons will generally be enabled before the client sends the
|
||
|
first undirected presence, to ensure that all inbound messages
|
||
|
will be delivered according to the Carbon rules. The server will
|
||
|
respond with an IQ result when Carbons are enabled:</p>
|
||
|
<example caption='Server acknowledges Carbons enablement'><![CDATA[
|
||
|
<iq type='result' id='enable1'/>]]></example>
|
||
|
</section2>
|
||
|
|
||
|
<section2 topic='Disabling Carbons' anchor='disabling'>
|
||
|
<p>Some clients might want to disable Carbons. An example of this
|
||
|
might be a mobile client that wants Carbons when the application
|
||
|
is in the foreground, and disabled when it is in the background.
|
||
|
To disable Carbons, clients send an IQ set:</p>
|
||
|
<example caption='Client disables Carbons'><![CDATA[
|
||
|
<iq type='set' id='disable1'>
|
||
|
<carbons var='urn:xmpp:carbons:0' mode='disable'/>
|
||
|
</iq>]]></example>
|
||
|
<p>The server will respond with an IQ result when Carbons are disabled:</p>
|
||
|
<example caption='Server acknowledges Carbons enablement'><![CDATA[
|
||
|
<iq type='result' id='disable1'/>]]></example>
|
||
|
</section2>
|
||
|
|
||
|
<section2 topic='Error Cases' anchor='errors'>
|
||
|
<p>Enabling or disabling Carbons may fail in the several ways. If
|
||
|
one of these errors is returned, the server MUST keep the previous
|
||
|
state, where the initial state is Carbons disabled. For example,
|
||
|
if the first enable returns an error, the server MUST NOT enable
|
||
|
Carbons.</p>
|
||
|
<section3 topic='bad-request' anchor='bad-request'>
|
||
|
<p>The sender has sent a stanza containing XML that does not
|
||
|
conform to the appropriate schema or that cannot be processed.
|
||
|
One example is an IQ stanza that includes an unrecognized value
|
||
|
of the 'type' attribute. Another is changing to the state that
|
||
|
is already in effect (enabling Carbons a second time).</p>
|
||
|
<example caption='Error: bad-request'><![CDATA[<iq id='enable1'
|
||
|
type='error'>
|
||
|
<error type='modify'>
|
||
|
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
||
|
</error>
|
||
|
</iq>]]></example>
|
||
|
</section3>
|
||
|
<section3 topic='feature-not-implemented' anchor='feature-not-implemented'>
|
||
|
<p>The sender has sent an enable or disable request to a server
|
||
|
that does not support the protocol. This SHOULD NOT happen in
|
||
|
practice, because clients MUST check for server support before
|
||
|
sending their request.</p>
|
||
|
<example caption='Error: feature-not-implemented'><![CDATA[<iq id='enable1'
|
||
|
type='error'>
|
||
|
<error type='cancel'>
|
||
|
<feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
||
|
</error>
|
||
|
</iq>]]></example>
|
||
|
</section3>
|
||
|
<section3 topic='forbidden' anchor='forbidden'>
|
||
|
<p>The sender does is forbidden by policy from enabling or
|
||
|
disabling Carbons.</p>
|
||
|
<example caption='Error: forbidden'><![CDATA[<iq id='enable1'
|
||
|
type='error'>
|
||
|
<error type='auth'>
|
||
|
<forbidden xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
||
|
</error>
|
||
|
</iq>]]></example>
|
||
|
</section3>
|
||
|
<section3 topic='not-allowed' anchor='not-allowed'>
|
||
|
<p>The receiver does not allow any entity to turn on Carbons.
|
||
|
This might occur in a multi-domain deployment, where
|
||
|
administrators of one domain allow Carbons, but another does
|
||
|
not.</p>
|
||
|
<example caption='Error: not-allowed'><![CDATA[<iq id='enable1'
|
||
|
type='error'>
|
||
|
<error type='cancel'>
|
||
|
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
|
||
|
</error>
|
||
|
</iq>]]></example>
|
||
|
</section3>
|
||
|
</section2>
|
||
|
|
||
|
<section2 topic='Inbound Messages' anchor='inbound'>
|
||
|
<p>Messages of type chat that are addressed to the bare JID
|
||
|
(localpart@domain) MUST be copied by the receiving server to all of the
|
||
|
resources for that user that have non-negative presence priority
|
||
|
and have not filtered messages through some other means. The
|
||
|
process of making copies is known as "forking." The receiving
|
||
|
server SHOULD NOT modify the 'to' address of the forked
|
||
|
messages.</p>
|
||
|
|
||
|
<example caption='Juliet sends Romeo an undirected message, which is forked'><![CDATA[
|
||
|
<message
|
||
|
from='juliet@example.com/balcony'
|
||
|
to='romeo@example.net'
|
||
|
type='chat'>
|
||
|
<body>Wherefore art thou, Romeo?</body>
|
||
|
<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>
|
||
|
</message>
|
||
|
|
||
|
... each of romeo@example.net's resources receives this stanza verbatim
|
||
|
]]></example>
|
||
|
|
||
|
<p>Messages of type "chat" that are addressed to a full JID
|
||
|
(localpart@domain/resource) MUST be sent by the receiving server to the
|
||
|
addressed resource, and MUST also be sent to all of the
|
||
|
Carbons-enabled resources for the receiving user. The goal of
|
||
|
the copies to Carbons-enabled resources is to allow those clients
|
||
|
to have both halves of *all* IM conversations, including messages
|
||
|
that are sent from clients that lock in to particular resources.</p>
|
||
|
</section2>
|
||
|
|
||
|
<section2 topic='Sending Messages' anchor='sending'>
|
||
|
<p>Once most of the clients that are deployed have implemented
|
||
|
Carbons, clients MAY choose to always send chat type messages to
|
||
|
the bare JID. Until then, traditional resource locking is
|
||
|
RECOMMENDED. (Note: another XEP might be written to document
|
||
|
traditional resource locking, if the documentation in &rfc3921bis;
|
||
|
is not sufficient.)</p>
|
||
|
|
||
|
<p>Also note that &xep0085; recommends sending chat state
|
||
|
notifications as chat type messages, which means that they will be
|
||
|
subject to Carbon-copying. This is intentional.</p>
|
||
|
</section2>
|
||
|
|
||
|
<section2 topic='Outbound Message Carbon Copies' anchor='outbound'>
|
||
|
<p>Carbons clients want to have copies of messages going in
|
||
|
<em>both</em> directions for other resources associated with the
|
||
|
same user. To that end, messages of type chat that are sent from
|
||
|
any resource MUST be copied by the sending server to each of the
|
||
|
resources that have enabled Carbons, but are not the sending
|
||
|
resource. Note that the 'to' address will be the original target of
|
||
|
the message (bare JID, as above), and the 'from' address will
|
||
|
contain the full JID (localpart@domain/resource) of the sending
|
||
|
resource. The 'to' address not matching the JID of the session is
|
||
|
somewhat unprecedented in XMPP, which is why Carbons must be
|
||
|
explicitly enabled.</p>
|
||
|
|
||
|
<p>Messages that have carbon copies sent back to Carbons-enabled
|
||
|
resources MUST NOT be copied back to the originating client. The
|
||
|
copies MUST have the full JID (localpart@domain/resource) of the sender
|
||
|
as the 'from' address. The copies MUST include a sent element in
|
||
|
the urn:xmpp:carbons:0 namespace.</p>
|
||
|
|
||
|
<example caption='Romeo responds to Juliet, which is Carboned'><![CDATA[
|
||
|
<message
|
||
|
to='juliet@example.com/balcony'
|
||
|
from='romeo@example.net/home'
|
||
|
type='chat'>
|
||
|
<body>Neither, fair saint, if either thee dislike.</body>
|
||
|
<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>
|
||
|
</message>]]></example>
|
||
|
|
||
|
<example caption='Romeo's OTHER Carbons-enabled clients
|
||
|
receive a copy'><![CDATA[
|
||
|
<message
|
||
|
to='juliet@example.com/balcony'
|
||
|
from='romeo@example.net/home'
|
||
|
type='chat'>
|
||
|
<body>Neither, fair saint, if either thee dislike.</body>
|
||
|
<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>
|
||
|
<sent xmlns='urn:xmpp:carbons:0'/>
|
||
|
</message>]]></example>
|
||
|
</section2>
|
||
|
|
||
|
<section2 topic='Avoiding Carbons for a single message' anchor='avoiding'>
|
||
|
<p>Some clients might want to avoid carbons on a single message,
|
||
|
while still keeping all of the other semantics of Carbon support.
|
||
|
This might be useful for clients sending end-to-end encrypted
|
||
|
messages, for example.</p>
|
||
|
|
||
|
<p>To avoid a message being Carbon-copied to its other resources,
|
||
|
the sending client MUST add a private element in the
|
||
|
urn:xmpp:carbons:0 namespace. When the sending server receives
|
||
|
the message, it MUST NOT make carbon copies to the other
|
||
|
Carbons-enabled resources, and MUST remove the private element
|
||
|
before forwarding the message to the intended recipient.</p>
|
||
|
|
||
|
<p>Note: use of the private mechanism will lead to partial
|
||
|
conversations on other devices. This is the intended effect.</p>
|
||
|
|
||
|
<example caption='Romeo sends to Juliet, avoiding Carbon copies'><![CDATA[
|
||
|
<message
|
||
|
to='juliet@example.com'
|
||
|
from='romeo@example.net/home'
|
||
|
type='chat'>
|
||
|
<body>Neither, fair saint, if either thee dislike.</body>
|
||
|
<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>
|
||
|
<private xmlns='urn:xmpp:carbons:0'/>
|
||
|
</message>]]></example>
|
||
|
|
||
|
<example caption='Romeo's server removes the private tag before forwarding, and does NOT send carbon copies to Romeo's other resources'><![CDATA[
|
||
|
<message
|
||
|
to='juliet@example.com'
|
||
|
from='romeo@example.net/home'
|
||
|
type='chat'>
|
||
|
<body>Neither, fair saint, if either thee dislike.</body>
|
||
|
<thread>0e3141cd80894871a68e6fe6b1ec56fa</thread>
|
||
|
</message>]]></example>
|
||
|
</section2>
|
||
|
</section1>
|
||
|
<section1 topic='Business Rules' anchor='rules'>
|
||
|
<section2 topic='Interaction with Chat States' anchor='chatstates'>
|
||
|
<p>Clients that implement Carbons MAY take special use of
|
||
|
&xep0085; notifications.</p>
|
||
|
<p>It is RECOMMENDED that upon receiving an outbound <em>gone</em>
|
||
|
chat state (as a carbon copy) for a given conversation, that
|
||
|
conversation be removed from user display as if the user on the
|
||
|
copied client had terminated the conversation. In order to
|
||
|
prevent unwanted termination of conversations on other resources,
|
||
|
clients SHOULD NOT send <em>gone</em> chat states on logout, but
|
||
|
instead SHOULD count on the unavailable presence to convey the change
|
||
|
in attention.</p>
|
||
|
<p>Upon receiving an outbound notification of any chat state other
|
||
|
than <em>gone</em>, the copied client MAY conclude that the
|
||
|
sending client has taken responsibility for the conversation, and
|
||
|
make appropriate user interface modifications. For example,
|
||
|
notifications could be muted on non-primary devices.</p>
|
||
|
</section2>
|
||
|
<section2 topic='Handling of errors' anchor='errors'>
|
||
|
<p>When a receiving server attempts to deliver a forked message,
|
||
|
and that message bounces with an error for any reason, the
|
||
|
receiving server MUST NOT forward that error back to the original
|
||
|
sender. The receiving server SHOULD use the sent element in the
|
||
|
bounce to determine that an error is from a forked message.</p>
|
||
|
<p>This rule is used to prevent some of the half-failure modes
|
||
|
that have been an issue in other prototocols.</p>
|
||
|
</section2>
|
||
|
<section2 topic='Auto-responses' anchor='auto-responses'>
|
||
|
<p>Clients that automatically respond to messages for any reason
|
||
|
(e.g. when in DND presence state) MUST take adequate care when
|
||
|
enabling Carbons in order to prevent storms or loops. Carbon
|
||
|
copies of outbound messages MUST NOT be auto-replied to under any
|
||
|
circumstances. Forked inbound messages SHOULD NOT be auto-replied
|
||
|
to, unless the client has some way of knowing that the receiver
|
||
|
will not receive more than one auto-reply from other similar
|
||
|
clients for the same user.</p>
|
||
|
</section2>
|
||
|
<section2 topic='Mobile Considerations' anchor='mobile'>
|
||
|
<p>Since mobile devices often must pay for network traffic based
|
||
|
on usage, the enablement of Carbons for such devices should be
|
||
|
undertaken advisedly. More complicated mechanisms for controlling
|
||
|
the Carbon-copying or forking of individual conversations may need
|
||
|
to be added to deal with mobile clients in the future.</p>
|
||
|
</section2>
|
||
|
</section1>
|
||
|
<section1 topic='Security Considerations' anchor='security'>
|
||
|
<p>The security model assumed by this document is that all of the
|
||
|
resources for a single user are in the same trust boundary.</p>
|
||
|
<p>Outbound chat messages that are encrypted end-to-end are not often
|
||
|
useful to receive on other resources. As such, they should use the
|
||
|
private element specified above to avoid such copying, unless the
|
||
|
encryption mechanism is adjusted to have knowledge of Carbons.</p>
|
||
|
</section1>
|
||
|
<section1 topic='IANA Considerations' anchor='iana'>
|
||
|
<p>This document requires no interaction with &IANA;.</p>
|
||
|
</section1>
|
||
|
<section1 topic='XMPP Registrar Considerations' anchor='reg'>
|
||
|
<section2 topic='Protocol Namespaces' anchor='registrar-ns'>
|
||
|
<p>This specification defines the following XML namespace:</p>
|
||
|
<ul>
|
||
|
<li>urn:xmpp:carbons:0</li>
|
||
|
</ul>
|
||
|
<p>Upon advancement of this specification from a status of Experimental to a status of Draft, the ®ISTRAR; shall add the foregoing namespace to the registry located at &NAMESPACES;, as described in Section 4 of &xep0053;.</p>
|
||
|
</section2>
|
||
|
<section2 topic='Protocol Versioning' anchor='registrar-versioning'>
|
||
|
&NSVER;
|
||
|
</section2>
|
||
|
</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='urn:xmpp:carbons:0'
|
||
|
xmlns='urn:xmpp:carbons:0'
|
||
|
elementFormDefault='qualified'>
|
||
|
|
||
|
<xs:element name='carbons'>
|
||
|
<xs:complexType>
|
||
|
<xs:simpleContent>
|
||
|
<xs:extension base='empty'>
|
||
|
<xs:attribute name='mode' use='required'>
|
||
|
<xs:simpleType>
|
||
|
<xs:restriction base="xs:string">
|
||
|
<xs:enumeration value="enable"/>
|
||
|
<xs:enumeration value="disable"/>
|
||
|
</xs:restriction>
|
||
|
</xs:simpleType>
|
||
|
</xs:attribute>
|
||
|
</xs:extension>
|
||
|
</xs:simpleContent>
|
||
|
</xs:complexType>
|
||
|
</xs:element>
|
||
|
|
||
|
<xs:element name='sent' type='empty'/>
|
||
|
|
||
|
<xs:element name='private' type='empty'/>
|
||
|
|
||
|
<xs:simpleType name='empty'>
|
||
|
<xs:restriction base='xs:string'>
|
||
|
<xs:enumeration value=''/>
|
||
|
</xs:restriction>
|
||
|
</xs:simpleType>
|
||
|
|
||
|
</xs:schema>
|
||
|
]]></code>
|
||
|
</section1>
|
||
|
<section1 topic='Acknowledgements' anchor='ack'>
|
||
|
<p>The author wishes to thank Patrick Barry, Teh Chang, Jack Erwin, Craig Kaes, Kathleen McMurry, Matt Miller, Tory Patnoe, Peter Saint-Andre, and Ben Schumacher for their feedback.</p>
|
||
|
</section1>
|
||
|
</xep>
|