ReconnectionManager giving up after an error when SM enabled

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:

  1. Enable ReconnectionManager with fixed delay 1 second
  2. Connect and login successfully
  3. Restart the XMPP server, removing the virtual domain
  4. 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:

This file can help repro the problem (you need the server setup as well):

Thanks for the detailed issue report. I hope to find the time to look into it soon.

1 Like

This topic was automatically closed 62 days after the last reply. New replies are no longer allowed.

I assume this is presented as part of an exception. You don’t happen to have the stacktrace of that exception?

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.