[Standards-JIG] rfc3920bis: Stanza Acknowledgements

Bruce Fitzsimons Bruce at Fitzsimons.org
Sun Nov 5 11:19:41 UTC 2006

Hi Justin,

I've been working on a Proto-XEP for this, but you well and truly beat
me to the punch, as is your right since you did the original almost-JEP.

Justin Karneges wrote:
> This protocol allows for requesting stream-level acks or tagging stream-level 
> sequence numbers on a per-stanza basis.
Nice. It isn't made clear, but I think it is intended, that every hop
can add/change/strip the ack status as it sees fit. So a non-supporting
client doesn't stop the s2s connections from using it, and s2s will want
to rewrite the sequence numbers if it is to take advantage of the fact
that sequence numbers always increase by 1 (see below, you need a req.
for this).

>   4. The initiating entity issues the enable command (i.e., a <enable/>
>      element qualified by the 'urn:ietf:params:xml:ns:xmpp-ack' namespace)
>      to instruct the receiving entity that it wishes to enable the
>      acknowledgement feature.  The element MAY contain a 'previd' attribute
>      and a 'prevc' attribute, if the initiating entity wishes to recover a
>      previously known acknowledgement session.  The value of the 'previd'
>      attribute is set to the same value as the 'id' attribute of the
>      <stream> in the previous session.  The value of the 'prevc' attribute,
>      if applicable, is set to the last received sequence number (discussed
>      below) by the initiating entity.  If the initiating entity is not
>      recovering a past session, the 'previd' and 'prevc' attributes MUST NOT
>      be included.
I really can't see the need for "previous" requests. Let me restate the
1. The sender has a queue of stanzas it doesn't think the recipient has.
2. The recipient has sent a response or two (or n) that were not
received (but doesn't know this).
3. The sender will re-send some entries that the recipient already has
(and knows about) when they reconnect.

The way SCTP copes with this is to ignore the duplicates -- and I think
XMPP can do the same. They're infrequent and the protocol overheard to
try and avoid them is much more complicated than ignoring them. Think
about all the extra permutations and the definition of behaviour for
them...make it the client's responsibility to cope (display, suppress,
whatever) not a protocol exchange with rules.

I've seen reports comparing this to an "SMTP problem" but this is not
the same -- the recipient is presumably storing state already (so it can
ask for a sequence number) and so it is trivial for it to suppress it --
no duplicates to the user.

I'm wondering if you're solving the duplicates problem and another, that
of how to relate the client queue to a newly opened stream? Shouldn't
this be like queued messages are handled currently? It gets twisty when
you're ack'ing message, presence and iq stanzas and the stream goes down
though -- can we just write the message stanzas to storage and turf the
rest? That would break the monotonous nature of the sequence
numbers...but old presence info is pretty useless. "fill in" stanzas? :-(
>   5. The receiving entity MUST reply with an <enabled/> element qualified by
>      the 'urn:ietf:params:xml:ns:xmpp-ack' namespace.  If the initiating
>      entity provided a 'previd' attribute in the <enable/> element, and the
>      receiving entity supports session recovery, then the receiving entity
>      MAY provide a 'prevc' attribute in the <enabled/> element.  The value
>      of this attribute is set to the last received sequence number
>      (discussed below) for the previous session.  If the receiving entity
>      does not support session recovery, or does not recognize the 'previd'
>      as an earlier session, or there is no known last received sequence
>      number for the session, then the attribute MUST NOT be included.
>   6. When a stanza is sent by either the initiating or receiving entity, an
>      'r' attribute ("request ack") or a 'c' attribute ("sequence number")
>      qualified by the 'urn:ietf:params:xml:ns:xmpp-ack' namespace MAY be
>      provided in the top-level element of the stanza to indicate how
>      acknowledgements are to be handled with respect to the stanza.  If no
>      acknowledgement processing is desired for a stanza, then the attribute
>      MUST NOT be included.  Note that only stanzas ('message', 'presence',
>      and 'iq', in the jabber:client or jabber:server namespaces) can have
>      this kind of processing applied.  Non-stanza elements, such as those
>      related to authentication or other stream-level purposes are not to be
>      acknowledged using this protocol.
I'm intrigued to know why you can turn on/off acking on a
stanza-by-stanza basis. Some implementation notes around this would be
useful -- are you thinking that a client may only apply this to messages
and not to presence?

>   7. When a stanza is received, containing an 'r' attribute ("request ack")
>      with a value of "true", the recipient MUST acknowledge the stanza by
>      sending an <a/> element qualified by the
>      'urn:ietf:params:xml:ns:xmpp-ack' namespace back to the sender.
>      Stanzas not containing an 'r' attribute MUST NOT be acknowledged.
>      Several stanzas MAY be acknowledged at one time by including an 'n'
>      attribute in the <a/> element, set to the integer value of the number
>      of stanzas.  An ack indicates stanza acceptance, in that the stanza is
>      now safe in the receiver's hands and that the receiver will take care
>      of it from that point.  Acks do not indicate successful delivery to a
>      remote entity beyond the receiver.  The sender does not have to wait
>      for an ack to continue sending stanzas.  Acks SHOULD be sent as soon as
>      possible, and MUST NOT be withheld for any condition other than a
>      timeout. For example, a client with a slow connection might want to
>      collect many stanzas over a period of time before acking, and a server
>      might want to throttle incoming stanzas. As acks indicate stanza
>      acceptance, a server that is throttling stanzas MUST defer the acks
>      until the client is no longer being penalized.
1. Um, I see an internal contradiction here. You say: "Acks SHOULD be
sent as soon as possible, and MUST NOT be withheld for any condition
other than a timeout.". Fair enough. But then your example shows the
opposite behaviour to that which you've recommended? I'm confused.
2. Un-numbered acks are not a wise thing to include support for. If
every message has one on, and you get many acks, where did you get up
to? It becomes something like a heartbeat, it doesn't give any absolute
message-by-message reliability, only a hand-waving "got to about here
and it broke".
>   8. When a stanza is received, containing a 'c' attribute ("sequence
>      number"), the recipient SHOULD keep a record of this value as the last
>      received sequence number for the current stream.  Everytime a new
>      sequence number is received, the previous number can be forgotten.
I think you need a "monotonically increasing" requirement around here
for the sequence number. Your design currently doesn't state that the
client can't reuse them in other ways either.

I'd like to promote the discussion that one ack can, and should, be able
to ack multiple stanzas. If we're really serious about XMPP over
[anything] rather than assuming TCP then I'd like to remove the
assumption I saw earlier today about stanzas on a stream arriving in
order. They do on TCP, and some applications might want this behaviour,
but is it a core XMPP requirement? Is a stream ordered? (RFC 3920 -
"Definition of XML Stream" doesn't say so). Shoot me down please, it
makes the implementation simpler -- but it should be more than implicit.

An ack message that can say "I got up to sequence number n, oh but I had
a few gaps" still works on TCP/SCTP because there will never be gaps. It
also scales rather nicely (1 ack per period rather than 1 per stanza).
Acks of this form would need to be sent on a time schedule (conflicting
with point 7 above) but the time schedule can still be sub-second -- it
just means the ack load is the same for 1 message per period vs 1000 per
ack period.

I've been looking at ack's in ejabberd. It is not a trivial change, and
I think that'd be true for any of the servers. The need to maintain a
per-stream queue (which is also index-able) means substantial changes
are required. The need to make it persistent has implications if this is
a separate queue to the off-line messages. The memory and disk
requirements from the per-stream queue need to be discussed, and I think
some implementation notes are in order (e.g. see above, do you store
presence stanzas and why/why not?).

Please take this feedback as constructive, you're the only one to get
off your backside and do something about this and I applaud that.


PS. I've got a bit of text refuting the "the transport layer should take
care of reliability" argument should you require it. I've seen this
argument in the archives quite frequently and it all comes down to the
lack of a decent contract between the application using the sockets api
and the TCP stack. Jabber is the first protocol I've seen that ignores
this problem, others constantly work around it...SMPP anyone?

More information about the Standards mailing list