I’m building an instant messenger app on iOS that uses ejabberd. I’m currently testing the stream management feature and in particular the resumption that seems to work in most cases. However there is a case I don’t understand, that I can replicate through the following steps, taking in account the settings: resume_timeout: 30, resend_on_timeout: if_offline
- at the beginning client A and client B are connected, no other resources are connected
- client B crashes or disconnects in a not clean way
- client A starts to send a bunch of messages (10+) very quickly
- ejabberd sends an ack to A for each message sent to confirm that the messages reached the server
- around 20 seconds since the crash, B reconnects. At this instant A receives an error for each message sent before
<message xmlns="jabber:client" from="clientB@mydomain" to="clientA@mydomain/resourceID" type="error" id="CFBF4583-209A-4453-2567-CCCC7894827E">
<body>test</body>
<active xmlns="http://jabber.org/protocol/chatstates" />
<request xmlns="urn:xmpp:receipts" />
<error code="503" type="cancel">
<service-unavailable xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" />
</error>
</message>
I tried with ejabberd 16.01.
This happens 80% of the time; sometimes messages sent by A are correctly delivered to B on reconnection within the 30 seconds.
My questions are:
- is this behavior correct? I would expect that no error is bounced to client A if an ack has already been received for a message.
- since
resend_on_timeout
is set toif_offline
and no other resource is connected, I would expect no errors at all. Am I correct?
This is really just a stab in the dark, but after having a glance over the ejabberd code, this could be what happens:
clientB@mydomain/ResourceB
drops their connection, there is now a session awaiting resumption usingResourceB
.ResourceB
again.if_offline
.So my theory is that
if_offline
only checks if there are other sessions when queue of unacknowledged messages needs to be handled, not at the time the message was originally received.