1
0
mirror of https://github.com/moparisthebest/xeps synced 2024-11-13 21:05:09 -05:00
xeps/inbox/qos.xml
2015-12-08 10:09:28 -07:00

427 lines
22 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'?>
<!--
© XMPP Standards Foundation, 2015
Author: Peter Waher
-->
<xep>
<header>
<title>Quality of Service</title>
<abstract>This specification describes a generic method whereby messages can be sent between clients using a predefined Quality of Service level.</abstract>
&LEGALNOTICE;
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
<sig>Standards</sig>
<approver>Council</approver>
<dependencies>
<spec>XMPP Core</spec>
<spec>XEP-0030</spec>
<spec>XEP-0337</spec>
</dependencies>
<supersedes/>
<supersededby/>
<shortname>qos</shortname>
&peterwaher;
<revision>
<version>0.0.1</version>
<date>2015-11-12</date>
<initials>pw</initials>
<remark>
<p>First draft.</p>
</remark>
</revision>
</header>
<section1 topic='Introduction' anchor='intro'>
<p>
Sometimes it is important for the sender of a message to control the Quality of Service level (or QoS level) of the message.
In other protocols, such as queueing, such QoS levels are built into the protocol itself. XMPP lacks an intrinsic QoS level management feature,
which has left application developers to define proprietary solutions when such have been required. This document however, provides a generic
solution and can be combined with any type of message structure defined either proprietarily or in another XEP.
The handling of the Quality of Service level is done prior to parsing the contents of the message. It defines three generic
Quality of Service levels that can be used regardless of what type of message is being sent:
</p>
<dl>
<di>
<dt>Unacknowledged service - At most once</dt>
<dd>
<p>
The message is sent at most once to its destination. The delivery of the message is not guaranteed. This QoS level
should only be used of the loss of messages is not critical to the application.
</p>
<p>
Example: A sensor sending a stream of current values. If a value is lost might not matter much since the next message
provides a new current value, overriding any lost value.
</p>
</dd>
</di>
<di>
<dt>Acknowledged service - At least once</dt>
<dd>
<p>
The message is sent at least once to its destination. Sending of the message is repeated until message has been acknowledged.
It is not guaranteed that the message is delivered only once. Asynchronous conditions may arise where the message is delivered more
than once. If an acknowledgement is not received, at least the sender may become aware that the message was not delivered
properly. The At least once QoS level requires twice as many messages to be transported in the network as compared to
the At most once QoS level.
</p>
<p>
Example: Any idempotent control action such as setting the light to a certain level. It is important that the control action
is received, but not how many of them are received. Any identical control action that follows makes no difference in output or
performance.
</p>
</dd>
</di>
<di>
<dt>Assured service - Exactly once</dt>
<dd>
<p>
The message is sent and delivered exactly once to its destination. The delivery of the message is divided into two acknowledged
message transfers. First, the message is transferred to the other side, but not parsed. The second operation, the message is requested
to be parsed and delivered. Both these steps are idempotent, making sure that the contents of the message is delivered exactly once.
If not possible to deliver the message, the sender will be made aware of this fact. The Exactly once QoS level requires
four times as many messages to be transported in the network as compared to the At most once QoS level and twice as many
messages to be transported as compared to the At least once QoS level.
</p>
<p>
Example: Any control action or counting operation that is not idempotent, such as sending a control action when a button is
pressed, whenever an event has occurred or a transaction. If counting events, transactions, or accumulating consumption, it is
vital that messages are not processed twice, since it will change the end result.
</p>
</dd>
</di>
</dl>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<section2 topic='Unacknowledged service - At most once' anchor='unack'>
<p>
To send a message that is received at most once to its destination, a normal message stanza is used, as defined by the XMPP
protocol itself. The delivery of the message is not guaranteed. This QoS level should only be used of the loss of messages is not critical
to the application.
</p>
<p>
Example: A sensor sending a stream of current values. If a value is lost might not matter much since the next message
provides a new current value, overriding any lost value.
</p>
<example caption='Sensor sending a momentary value'>
<![CDATA[
<message
from='temperaturesensor@example.org/34892374'
to='user@example.org/938089023'>
<fields xmlns='urn:xmpp:iot:sensordata' seqnr='1' done='true'>
<node nodeId='Temp01'>
<timestamp value='2015-11-11T22:01:30'>
<numeric name='Temperature' momentary='true' automaticReadout='true' value='23.4' unit='°C'/>
</timestamp>
</node>
</fields>
</message>]]>
</example>
</section2>
<section2 topic='Acknowledged service - At least once' anchor='ack'>
<p>
To send a message that is received at least once to its destination, an iq stanza of type set is sent containing an
acknowledged element from the "urn:xmpp:qos" namespace. The acknowledged element in turn contains the message to be delivered.
The iq stanza must have an id attribute that is used to identify if the stanza has been received or not. When an acknowledged
message is received, an empty response is returned to acknowledge the receipt. Parsing the message is done after sending the response.
If no response is received by the sending side within a given time frame, an number of retries should be made, using an interval or drop-off
algorithm. These time frames and number of attempts are implementation specific.
</p>
<p>
It is not guaranteed that the message is delivered only once. Asynchronous conditions may arise where the message is delivered more
than once. If an acknowledgement is not received, at least the sender may become aware that the message was not delivered.
The At least once QoS level requires twice as many messages to be transported in the network as compared to
the At most once QoS level.
</p>
<p>
Example: Any idempotent control action such as setting the light to a certain level. It is important that the control action
is received, but not how many of them are received. Any identical control action that follows makes no difference in output or
performance.
</p>
<example caption='Setting light level'>
<![CDATA[
<iq id='123' type='set'
from='controller@example.org/34892374'
to='lightswitch@example.org/938089023'>
<qos:acknowledged xmlns:qos='urn:xmpp:qos'>
<message>
<set xmlns='urn:xmpp:iot:control'>
<int name='Light' value='80'/>
</set>
</message>
</qos:acknowledged>
</iq>
<iq id='123' type='result'
from='lightswitch@example.org/938089023'
to='controller@example.org/34892374'/>
]]>
</example>
<p>
Note: The to and from attributes in the embedded message stanza are left empty.
</p>
</section2>
<section2 topic='Assured service - Exactly once' anchor='assured'>
<p>
To send a message that is received exactly once to its destination, an iq stanza of type set is sent containing an
assured element from the "urn:xmpp:qos" namespace. The assured element in turn contains the message to be delivered.
The iq stanza must have an id attribute that is used to identify if the stanza has been received or not, just as in the
acknowledged case. But to keep track of the message begin sent, a msgId attribute has to be provided as well. When an assured
message is received, a received response is returned to acknowledge the receipt. This received response echoes the msgId
attribute as well. But the message is not parsed and delivered at this point, only temporarily stored on the receiving end.
If multiple messages are received using the same msgId from the same sender, they are simply ignored, as one is already held in
memory. Still, the received response is returned as normal.
</p>
<p>
When the sender receives the received response, it sends a new iq set stanza, this time with a deliver payload,
to tell the receiving end to parse and deliver the message, if in memory, and remove it from memory. The receiver acknowledges the message
by returning an empty iq result stanza. If receiving multiple requests using the same msgId, it will acknowledge each one. But
only one message will be parsed and delivered, as it will have been removed from the temporary storage on the receiving end. For both the
assured and deliver messages, a retry mechanism similar to the one used for acknowledged service is to be used.
</p>
<p>
The Exactly once QoS level requires twice as many messages to be transported in the network as compared to the At least once
QoS level, and four times the number of messages as compared to the At most once QoS level.
</p>
<p>
Example: Any control action or counting operation that is not idempotent, such as sending a control action when a button is
pressed, or whenever an event has occurred. If counting events, or accumulating consumption, it is vital that messages are not
processed twice, since it will change the end result.
</p>
<example caption='Counting cars or individuals in a closed space'>
<![CDATA[
<iq id='123' type='set'
from='entrance@example.org/34892374'
to='counter@example.org/938089023'>
<qos:assured xmlns:qos='urn:xmpp:qos' msgId='984232334'>
<message>
<log xmlns='urn:xmpp:eventlog' timestamp='2015-11-12T09:07:12Z' id='Entered'>
<message>Entered.</message>
</buy>
</message>
</qos:assured>
</iq>
<iq id='123' type='result'
from='counter@example.org/938089023'>
to='entrance@example.org/34892374'>
<received msgId='984232334'/>
</iq>
<iq id='124' type='set'
from='entrance@example.org/34892374'
to='counter@example.org/938089023'>
<qos:deliver xmlns:qos='urn:xmpp:qos' msgId='984232334'/>
</iq>
<iq id='124' type='result'
from='counter@example.org/938089023'>
to='entrance@example.org/34892374'/>
</iq>
...
<iq id='456' type='set'
from='exit@example.org/34892374'
to='counter@example.org/938089023'>
<qos:assured xmlns:qos='urn:xmpp:qos' msgId='4645623466'>
<message>
<log xmlns='urn:xmpp:eventlog' timestamp='2015-11-12T11:23:54Z' id='Left'>
<message>Left.</message>
</buy>
</message>
</qos:assured>
</iq>
<iq id='456' type='result'
from='counter@example.org/938089023'>
to='exit@example.org/34892374'>
<received msgId='4645623466'/>
</iq>
<iq id='457' type='set'
from='exit@example.org/34892374'
to='counter@example.org/938089023'>
<qos:deliver xmlns:qos='urn:xmpp:qos' msgId='4645623466'/>
</iq>
<iq id='457' type='result'
from='counter@example.org/938089023'>
to='exit@example.org/34892374'/>
</iq>]]>
</example>
<p>
Note: The to and from attributes in the embedded message stanza are left empty.
</p>
</section2>
</section1>
<section1 topic='Determining Support' anchor='support'>
<p>
If an entity supports signing forms as specified herein, it MUST advertise that fact by returning a feature of
"urn:xmpp:qos" in response to &xep0030; information requests.
</p>
<example caption="Service discovery information request">
<![CDATA[
<iq type='get'
from='example.org'
to='device@example.org'
id='disco1'>
<query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>]]>
</example>
<example caption="Service discovery information response">
<![CDATA[
<iq type='result'
from='device@example.org'
to='example.org'
id='disco1'>
<query xmlns='http://jabber.org/protocol/disco#info'>
...
<feature var='urn:xmpp:qos'/>
...
</query>
</iq>]]>
</example>
<p>
In order for an application to determine whether an entity supports this protocol, where possible it SHOULD use the dynamic,
presence-based profile of service discovery defined in &xep0115;. However, if an application has not received entity capabilities
information from an entity, it SHOULD use explicit service discovery instead.
</p>
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
<section2 topic='Offline messages' anchor='offline'>
<p>
When sending messages using unacknowledged service, i.e. using the normal message stanza, it can be subject to offline message
storage if the recipient if offline. This might result in delivery of the message at a later time.
</p>
</section2>
<section2 topic='Resource part' anchor='resource'>
<p>
Message routing using unacknowledged service might be handled somewhat differently as compared to acknowledged and assured service,
since the first uses the message stanza and the latter two the iq stanza, which require a fill JID in order to reach its destination.
For consistency, full JIDs should be used also for unacknowledged messaging service, if possible.
</p>
</section2>
<section2 topic='Generic implementation' anchor='generic'>
<p>
If implementing support for this XEP, make sure implementation is generic and put on a lower level than other XEP-specific processing
of incoming stanzas. Messages received using this server should be fed into the normal message processing and handling after the QoS level
has been ascertained. This makes it possible to use QoS levels for any type of message being sent and received.
</p>
</section2>
<section2 topic='Persistence' anchor='persistence'>
<p>
One decision each implementation of assured QoS has to make, is where to persist incoming messages between reception of message and
the delivery to underlying message processing logic. Should they be persisted in internal memory, persistent Flash/EEProm, as local files
or in a database? Such implementation specific concerns are left to the implementor, as this XEP only concerns itself with the communication
layer between parties. But the choice of solution might affect to what level a message is ascertained to be delivered: Will delivery be
guaranteed, even beyond a system reset at the receiving end? Or a system reset at the sending side? If delivery of the message has to be
ascertained even if a system reset at the sending side is allowed, persistance of the request must also be made on the sending side.
(To some extent, this latter concern even affects acknowledged service.)
</p>
</section2>
<section2 topic='Message IDs' anchor='msdId'>
<p>
Outstanding message IDs used in assured delivery, must be unique for the sender (counting the Full JID as the sender). If running
short on Message IDs, such can be reclaimed after the receipt of a successful delivery of a previous message. Message IDs can be
sequence numbers, or hash values of the contents of the message.
</p>
</section2>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<section2 topic='To and from attributes' anchor='tofrom'>
<p>
The to and from attributes of embedded message elements should be ignored and left out by the sender, except in the case of
unacknowledged service, where the message element is the message stanza itself. In the case of acknowledged and assured quality of
service levels, the message element MUST have its to and from attributes overwritten by the corresponding attributes of the iq
stanza being used. This, to avoid the injection of messages with unauthenticated and unauthorized identities.
</p>
</section2>
<section2 topic='Memory attacks' anchor='memory'>
<p>
As incoming message using the assured quality of service level is temporarily stored on the receiving end, the receiver might become
vulnerable to memory attacks if not implementing some basic counter measures:
</p>
<ol>
<li>
<p>
Do not accept messages using assured service from untrusted sources, for instance from MUC rooms or senders not in the
roster. If deemed untrusted, an iq error of type <strong>not-allowed</strong> should be returned instead of the
<strong>received</strong> element expected in normal flow.
</p>
</li>
<li>
<p>
Set a limit on the number and size of assured messages that can be simultaneously received from a single source. If a source
sends more than this, the <strong>resource-constraint</strong> error should be returned instead of accepting the message.
</p>
</li>
<li>
<p>
Set a total limit on the number and size of assured messages that can be simultaneously received from all sources. If anybody
sends a message that will exceed this amount, the <strong>resource-constraint</strong> error should be returned instead of
accepting the message.
</p>
</li>
</ol>
<p>
Whenever invalid use of the assured messaging service is detected, wether it be from untrusted sources or spam, an event should be
logged using &xep0337; so that the source of the error can be found and appropriate counter measures taken.
</p>
</section2>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with &IANA;.</p>
</section1>
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
<p>
The <link url="#schema">protocol schema</link> needs to be added to the list of <link url="http://xmpp.org/resources/schemas/">XMPP protocol schemas</link>.
</p>
</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:qos'
xmlns='urn:xmpp:qos'
xmlns:jbc='jabber:client'
elementFormDefault='qualified'>
<xs:import namespace='jabber:client'/>
<xs:element name='acknowledged' type='EmbeddedMessage'/>
<xs:element name='assured' type='Assured'/>
<xs:element name='received' type='WithMessageId'/>
<xs:element name='deliver' type='WithMessageId'/>
<xs:complexType name='EmbeddedMessage'>
<xs:sequence minOccurs='1' maxOccurs='1'>
<xs:element ref='jbc:message'/>
</xs:sequence>
</xs:complexType>
<xs:complexType name='Assured'>
<xs:complexContent>
<xs:extension base='EmbeddedMessage'>
<xs:attribute ref='msgId' use='required'/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:attribute name='msgId' type='xs:string'/>
<xs:complexType name='WithMessageId'>
<xs:attribute ref='msgId' use='required'/>
</xs:complexType>
</xs:schema>
]]>
</code>
</section1>
</xep>