I checked many issues related to ReconnectionManager like this , this and this all complaining about reconnection manager not able to reconnect and no reply/fix yet. I think I have found the bug.
My Smack library version is - 4.2.4
SMPP server - ejabberd 18.04
Basically reconnection manager tries to reconnect only when connection is not already established (connected flag is false in AbstractXMPPConnection). The flow goes like this
-
AbstractXMPPConnection.connect()
-
Put exchange msg in queue
2.1 RequestProcessor picks up this message in new thread
2.2 As connection fails (due to e.g. network error ), raise BOSHClientConnEvent and notify ConnectionListner with connectionClosedOnError call.
2.3 ReconnectionManager notified about connection failure with above event.
2.4 ReconnectionManager check if isConnected= false and tries reconnecting -
Current thread continues in XMPPBOSHConnection.connect() and set connected flag true
-
Current Thread send connection event to listen with ConnectionListner.connected()
In above flow when 2.4 execute first, it tries to reconnect first time but then once step 4 is finished in main thread it marks connection ad connected and then reconnection manager never tries and we don’t have any option then to restart client.
Below is main stracktrace that I caught.
While connection fails, one thread send connectionCloseOnError notificaion
XMPPBOSHConnection.shutdown() line: 265
XMPPBOSHConnection.notifyConnectionError(Exception) line: 407
XMPPBOSHConnection$BOSHConnectionListener.connectionEvent(BOSHClientConnEvent) line: 454
BOSHClient.fireConnectionClosedOnError(Throwable) line: 1675
BOSHClient.dispose(Throwable) line: 705
BOSHClient.processExchange(int, HTTPExchange) line: 1129
BOSHClient.processMessages(int) line: 990
BOSHClient.access$300(BOSHClient, int) line: 100
BOSHClient$RequestProcessor.run() line: 1719
Thread.run() line: 745
While another thread continues after send call and mark connected=true
BOSHClient.send(ComposableBody) line: 506
XMPPBOSHConnection.connectInternal() line: 177
XMPPBOSHConnection(AbstractXMPPConnection).connect() line: 383
ReconnectionManager$2.run() line: 289
Thread.run() line: 745
So ReconnectionManager.isReconnectionPossible() return false is connection.isConnected() calls return true even client was not connected to server.
Simple way to reproduce is to start client without starting server. Even when ReconnectionManager is set to call at Fixed delay it will at max calls only once.
To resolve issue, I think connect() method should wait for event from RequestProcessor or some other way it should find if connection is already established and then only return.