We ran into an issue with ReconnectionManager and stream resumption. I can reproduce with both 4.4.8 and 4.4.6. The scenario is the following:
Enable ReconnectionManager with fixed delay 1 second
Connect and login successfully
Restart the XMPP server, removing the virtual domain
Smack attempts to re-connect and gets a host-unknown error
Expected behavior:
Smack should continue to attempt to re-connect at 1 second interval.
Actual behavior:
Smack stops the re-connect attempts.
The issue only occurs when Stream Management is enabled. If we disable it, the behavior is as expected. Also, if we stop the XMPP server instead of mis-configuring it, so the TCP socket fails to connect then the behavior is as expected.
XMPPTCPConnection.setUseStreamManagementResumptionDefault(false);
XMPPTCPConnection.setUseStreamManagementDefault(false);
I suspect it has to do with ReconnectionManager running after the XMPPTCPConnection is marked as connected
here, but I don’t understand the details:
* @throws SmackException if Smack detected an exceptional situation.
* @throws IOException if an I/O error occurred.
* @throws InterruptedException if the calling thread was interrupted.
*/
@Override
protected void connectInternal() throws SmackException, IOException, XMPPException, InterruptedException {
// Establishes the TCP connection to the server and does setup the reader and writer. Throws an exception if
// there is an error establishing the connection
connectUsingConfiguration();
connected = true;
// We connected successfully to the servers TCP port
initConnection();
// TLS handled will be true either if TLS was established, or if it was not mandatory.
waitForConditionOrThrowConnectionException(() -> tlsHandled, "establishing TLS");
// Wait with SASL auth until the SASL mechanisms have been received
waitForConditionOrThrowConnectionException(() -> saslFeatureReceived, "SASL mechanisms stream feature from server");
}
This file can help repro the problem (you need the server setup as well):
Flow
December 7, 2024, 1:50pm
2
Thanks for the detailed issue report. I hope to find the time to look into it soon.
1 Like
system
Closed
February 7, 2025, 1:50pm
3
This topic was automatically closed 62 days after the last reply. New replies are no longer allowed.
Flow
February 15, 2025, 2:09pm
4
I assume this is presented as part of an exception. You don’t happen to have the stacktrace of that exception?
Flow
February 15, 2025, 2:34pm
6
I tried to reproduce this on the latest Smack master using
package org.igniterealtime.smack.examples;
import java.io.IOException;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.ReconnectionListener;
import org.jivesoftware.smack.ReconnectionManager;
import org.jivesoftware.smack.ReconnectionManager.ReconnectionPolicy;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.debugger.ConsoleDebugger;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.impl.JidCreate;
public class ReconnectionManagerAndStreamManagement {
public static void reconnectionManagerAndStreamManagement(BareJid jid, String password)
throws XMPPException, SmackException, IOException, InterruptedException {
XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setXmppAddressAndPassword(jid, password)
.setDebuggerFactory(ConsoleDebugger.Factory.INSTANCE)
.build();
XMPPTCPConnection connection = new XMPPTCPConnection(config);
var reconnectionManager = ReconnectionManager.getInstanceFor(connection);
reconnectionManager.setReconnectionPolicy(ReconnectionPolicy.FIXED_DELAY);
reconnectionManager.setFixedDelay(1);
reconnectionManager.enableAutomaticReconnection();
reconnectionManager.addReconnectionListener(new ReconnectionListener() {
@Override
public void reconnectingIn(int seconds) {
System.out.println("Reconnecting in " + seconds + " seconds");
}
@Override
public void reconnectionFailed(Exception e) {
System.out.println("Reconnection failed: " + e);
e.printStackTrace();
}
});
connection.addConnectionListener(new ConnectionListener() {
public void connected(XMPPConnection connection) {
System.out.println("Connected");
}
public void authenticated(XMPPConnection connection, boolean resumed) {
System.out.println("Authenticated");
}
public void connectionClosed() {
System.out.println("Connection closed");
}
public void connectionClosedOnError(Exception e) {
System.out.println("Connection closed on error: " + e);
e.printStackTrace();
}
});
connection.connect().login();
Thread.sleep(10000000);
}
public static void main(String[] args) throws XMPPException, SmackException, IOException, InterruptedException {
BareJid jid = JidCreate.bareFrom(args[0]);
String password = args[1];
reconnectionManagerAndStreamManagement(jid, password);
}
}
and ss -K dport = xmpp-client
to kill the connection. The ReconnectionManager
worked as expected.