Android Smack client suddenly sends Unavailable PRESENCE for no reason, then server thinks i'm offline

I am using Smack version 4.2.3 for android
I am working with openfire 4.2.2 server.
In the server i have configured Client Connection - Idle Connections Policy - Disconnect client after 30 seconds + Send an XMPP ping request to idle clients.

In the client, I have set a stable XMPPConnection with a ReconnectionManager enabled, and a ConnectionListener that reports each connect/reconnect/disconnect event.

I am connected to the server with my client with username: john@test.com.
When I look at the packets with Wireshark going back and forth from the server to the client, I can see the ping requests and my ping results every 15 seconds and thus the server sees me as Online.
However, after about 10 minutes, suddenly I get a PRESENCE packet from the server of type Unavailable from john to john and then immediately the server sees me as Offline.
In my client I never deliberately send an Unavailable presence, except when I call connection.disconnect().
Also, in the client’s connectionListener I do not see any action when this happens, and the pings keep going back and forth even after this happens, yet the server still thinks I am offline.

Anybody have any idea why is this happening?

Thanks.

1 Like

I think this may cause problems, but I’m not an expert.

Hi, We also facing same issue, any solutions you found for this problem.

Thanks
Mohsin

1 Like

Same here, as @fuxuhew said, this is happening since 4.2

Is it problem in Openfire or Smack client library. This leads to some major issue in productions.

Thanks
Mohsin

It should be easy to figure that out by looking at the stanza trace.

I have been tracking this issue for a while. After compare the Spark’s debugger console and my Android Studio project log, the only difference that I found is that spark client is sending a ping every 3 mins.

Openfire is configured to “Disconnect clients after they have been idle for 360 seconds”, and “Send an XMPP Ping request to idle clients”.

Turns out that if I disable previous settings (using “Do not disconnect clients that are idle”) client (Smack) don’t sends unavailable presence anymore.

Are you sure that Smack explicitly sends an unavailable presence? Or does it just look that way?

Hi Flow, sorry for the late answer, working on Markable messages made me forget about this xD.

Answering your question, is OF the one who is sending that stanza. Smack by default send back an answer to server ping (1), but like I said, the difference between my app and Spark is that the last one is sending a ping every 3 mins.

So I think that there is a bug with OF and idle clients configurations.

(1) this is an example of the stanza sent by smack:

<iq to='xxxxxdev12345666' id='342-7182' type='result'></iq><r xmlns='urn:xmpp:sm:3'/>

Bad news:
Even checking Do not disconnect clients that are idle in OF configurations, smack is recv a stanza that he never sent, a unavailable presence from him to him.
We added listeners to connection for incoming and outgoing stanzas and the only one captured was the RECV one.

@atmohsin, @Paul_Schaub, @Flow

I found more information that can help to solve this problem:

Looking the OF logs I found a correlation between the time when the stanza we are talking in this post arrives to client and a warn log like the following one:

2018.09.26 15:49:35 class org.jivesoftware.openfire.streammanagement.StreamManager[XXX.XXX.XXX.XXX] - Client acknowledges stanzas that we didn't send! Client Ack h: 195, our last stanza: 52 
2018.09.26 15:50:48 org.jivesoftware.openfire.nio.ConnectionHandler - Closing connection due to exception in session: (0x00003072: nio socket, server, null => 0.0.0.0/0.0.0.0:5222)

After this happens I guess the sockets is being close from server side but without notify the client about it.

I used to see this error some months ago in logcat (android studio) but not anymore. In that time, when this error happened Smack automatically did a reconnection with OF.

In our case I think we are be able to handle this using in smack:

  • xmpptcpConnection.setUseStreamManagement(true);
  • ReconnectionManager
  • PingManager (we still are not sure if we need this one)

But still not sure if this is a work around or not.

News about this behavior,

We realized this issue can be triggered easily having 2 clients from same IP (for example two android emulators)

using streamManagment has decreased the number of occurence and using ping has helped to handle the case to some extent but there is no answer to why this issues occurs and a full proof solution to this.
if anyone of the readers has a solution, kindly share.

Hi!
If you are using XMPPTCPConnection and calling createStanzaCollectorAndSend(IQ packet), check that you are calling removeStanzaCollector(StanzaCollector collector) when you receive the response (or a timemout).
I have not anlyzed this further, but stacking up collectors on the connection seems to trigger this issue.

If you do it the Smack idiomatic way:

connection.createStanzaCollectorAndSend(iq).nextResultOrThrow()

which you should, then the collector will be always be canceled (unless you hit a bug).

1 Like

I also ran into this problem.
When reconnecting to the same resource, the status unavailable may be received from the jid with this resource (and possibly with other previously connected resources).

I do not know how to overcome this.