remove support for sm:2

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/xml/Namespace.java                         |   3 
src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java                   | 650 
src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java         |   3 
src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java       |   3 
src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java     |   5 
src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java  |   5 
src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java |   5 
src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java  |   5 
8 files changed, 445 insertions(+), 234 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/xml/Namespace.java πŸ”—

@@ -25,6 +25,9 @@ public final class Namespace {
     public static final String NICK = "http://jabber.org/protocol/nick";
     public static final String FLEXIBLE_OFFLINE_MESSAGE_RETRIEVAL = "http://jabber.org/protocol/offline";
     public static final String BIND = "urn:ietf:params:xml:ns:xmpp-bind";
+    public static final String BIND2 = "urn:xmpp:bind2:0";
+    public static final String STREAM_MANAGEMENT = "urn:xmpp:sm:3";
+    public static final String CSI = "urn:xmpp:csi:0";
     public static final String BOOKMARKS_CONVERSION = "urn:xmpp:bookmarks-conversion:0";
     public static final String BOOKMARKS = "storage:bookmarks";
     public static final String SYNCHRONIZATION = "im.quicksy.synchronization:0";

src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java πŸ”—

@@ -109,38 +109,45 @@ public class XmppConnection implements Runnable {
     private static final int PACKET_IQ = 0;
     private static final int PACKET_MESSAGE = 1;
     private static final int PACKET_PRESENCE = 2;
-    public final OnIqPacketReceived registrationResponseListener = (account, packet) -> {
-        if (packet.getType() == IqPacket.TYPE.RESULT) {
-            account.setOption(Account.OPTION_REGISTER, false);
-            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": successfully registered new account on server");
-            throw new StateChangingError(Account.State.REGISTRATION_SUCCESSFUL);
-        } else {
-            final List<String> PASSWORD_TOO_WEAK_MSGS = Arrays.asList(
-                    "The password is too weak",
-                    "Please use a longer password.");
-            Element error = packet.findChild("error");
-            Account.State state = Account.State.REGISTRATION_FAILED;
-            if (error != null) {
-                if (error.hasChild("conflict")) {
-                    state = Account.State.REGISTRATION_CONFLICT;
-                } else if (error.hasChild("resource-constraint")
-                        && "wait".equals(error.getAttribute("type"))) {
-                    state = Account.State.REGISTRATION_PLEASE_WAIT;
-                } else if (error.hasChild("not-acceptable")
-                        && PASSWORD_TOO_WEAK_MSGS.contains(error.findChildContent("text"))) {
-                    state = Account.State.REGISTRATION_PASSWORD_TOO_WEAK;
+    public final OnIqPacketReceived registrationResponseListener =
+            (account, packet) -> {
+                if (packet.getType() == IqPacket.TYPE.RESULT) {
+                    account.setOption(Account.OPTION_REGISTER, false);
+                    Log.d(
+                            Config.LOGTAG,
+                            account.getJid().asBareJid()
+                                    + ": successfully registered new account on server");
+                    throw new StateChangingError(Account.State.REGISTRATION_SUCCESSFUL);
+                } else {
+                    final List<String> PASSWORD_TOO_WEAK_MSGS =
+                            Arrays.asList(
+                                    "The password is too weak", "Please use a longer password.");
+                    Element error = packet.findChild("error");
+                    Account.State state = Account.State.REGISTRATION_FAILED;
+                    if (error != null) {
+                        if (error.hasChild("conflict")) {
+                            state = Account.State.REGISTRATION_CONFLICT;
+                        } else if (error.hasChild("resource-constraint")
+                                && "wait".equals(error.getAttribute("type"))) {
+                            state = Account.State.REGISTRATION_PLEASE_WAIT;
+                        } else if (error.hasChild("not-acceptable")
+                                && PASSWORD_TOO_WEAK_MSGS.contains(
+                                        error.findChildContent("text"))) {
+                            state = Account.State.REGISTRATION_PASSWORD_TOO_WEAK;
+                        }
+                    }
+                    throw new StateChangingError(state);
                 }
-            }
-            throw new StateChangingError(state);
-        }
-    };
+            };
     protected final Account account;
     private final Features features = new Features(this);
     private final HashMap<Jid, ServiceDiscoveryResult> disco = new HashMap<>();
     private final HashMap<String, Jid> commands = new HashMap<>();
     private final SparseArray<AbstractAcknowledgeableStanza> mStanzaQueue = new SparseArray<>();
-    private final Hashtable<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks = new Hashtable<>();
-    private final Set<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners = new HashSet<>();
+    private final Hashtable<String, Pair<IqPacket, OnIqPacketReceived>> packetCallbacks =
+            new Hashtable<>();
+    private final Set<OnAdvancedStreamFeaturesLoaded> advancedStreamFeaturesLoadedListeners =
+            new HashSet<>();
     private final XmppConnectionService mXmppConnectionService;
     private Socket socket;
     private XmlReader tagReader;
@@ -150,7 +157,6 @@ public class XmppConnection implements Runnable {
     private boolean isBound = false;
     private Element streamFeatures;
     private String streamId = null;
-    private int smVersion = 3;
     private int stanzasReceived = 0;
     private int stanzasSent = 0;
     private long lastPacketReceived = 0;
@@ -178,7 +184,6 @@ public class XmppConnection implements Runnable {
     private volatile Thread mThread;
     private CountDownLatch mStreamCountDownLatch;
 
-
     public XmppConnection(final Account account, final XmppConnectionService service) {
         this.account = account;
         this.mXmppConnectionService = service;
@@ -186,10 +191,12 @@ public class XmppConnection implements Runnable {
 
     private static void fixResource(Context context, Account account) {
         String resource = account.getResource();
-        int fixedPartLength = context.getString(R.string.app_name).length() + 1; //include the trailing dot
+        int fixedPartLength =
+                context.getString(R.string.app_name).length() + 1; // include the trailing dot
         int randomPartLength = 4; // 3 bytes
         if (resource != null && resource.length() > fixedPartLength + randomPartLength) {
-            if (validBase64(resource.substring(fixedPartLength, fixedPartLength + randomPartLength))) {
+            if (validBase64(
+                    resource.substring(fixedPartLength, fixedPartLength + randomPartLength))) {
                 account.setResource(resource.substring(0, fixedPartLength + randomPartLength));
             }
         }
@@ -206,7 +213,12 @@ public class XmppConnection implements Runnable {
     private void changeStatus(final Account.State nextStatus) {
         synchronized (this) {
             if (Thread.currentThread().isInterrupted()) {
-                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": not changing status to " + nextStatus + " because thread was interrupted");
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": not changing status to "
+                                + nextStatus
+                                + " because thread was interrupted");
                 return;
             }
             if (account.getStatus() != nextStatus) {
@@ -260,7 +272,9 @@ public class XmppConnection implements Runnable {
         inSmacksSession = false;
         isBound = false;
         this.attempt++;
-        this.verifiedHostname = null; //will be set if user entered hostname is being used or hostname was verified with dnssec
+        this.verifiedHostname =
+                null; // will be set if user entered hostname is being used or hostname was verified
+                      // with dnssec
         try {
             Socket localSocket;
             shouldAuthenticate = !account.isOptionSet(Account.OPTION_REGISTER);
@@ -279,7 +293,13 @@ public class XmppConnection implements Runnable {
                 final int port = account.getPort();
                 final boolean directTls = Resolver.useDirectTls(port);
 
-                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": connect to " + destination + " via Tor. directTls=" + directTls);
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": connect to "
+                                + destination
+                                + " via Tor. directTls="
+                                + directTls);
                 localSocket = SocksSocketFactory.createSocketOverTor(destination, port);
 
                 if (directTls) {
@@ -290,7 +310,10 @@ public class XmppConnection implements Runnable {
                 try {
                     startXmpp(localSocket);
                 } catch (InterruptedException e) {
-                    Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": thread was interrupted before beginning stream");
+                    Log.d(
+                            Config.LOGTAG,
+                            account.getJid().asBareJid()
+                                    + ": thread was interrupted before beginning stream");
                     return;
                 } catch (Exception e) {
                     throw new IOException(e.getMessage());
@@ -309,41 +332,70 @@ public class XmppConnection implements Runnable {
                     return;
                 }
                 if (results.size() == 0) {
-                    Log.e(Config.LOGTAG, account.getJid().asBareJid() + ": Resolver results were empty");
+                    Log.e(
+                            Config.LOGTAG,
+                            account.getJid().asBareJid() + ": Resolver results were empty");
                     return;
                 }
                 final Resolver.Result storedBackupResult;
                 if (hardcoded) {
                     storedBackupResult = null;
                 } else {
-                    storedBackupResult = mXmppConnectionService.databaseBackend.findResolverResult(domain);
+                    storedBackupResult =
+                            mXmppConnectionService.databaseBackend.findResolverResult(domain);
                     if (storedBackupResult != null && !results.contains(storedBackupResult)) {
                         results.add(storedBackupResult);
-                        Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": loaded backup resolver result from db: " + storedBackupResult);
+                        Log.d(
+                                Config.LOGTAG,
+                                account.getJid().asBareJid()
+                                        + ": loaded backup resolver result from db: "
+                                        + storedBackupResult);
                     }
                 }
-                for (Iterator<Resolver.Result> iterator = results.iterator(); iterator.hasNext(); ) {
+                for (Iterator<Resolver.Result> iterator = results.iterator();
+                        iterator.hasNext(); ) {
                     final Resolver.Result result = iterator.next();
                     if (Thread.currentThread().isInterrupted()) {
-                        Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": Thread was interrupted");
+                        Log.d(
+                                Config.LOGTAG,
+                                account.getJid().asBareJid() + ": Thread was interrupted");
                         return;
                     }
                     try {
                         // if tls is true, encryption is implied and must not be started
                         features.encryptionEnabled = result.isDirectTls();
-                        verifiedHostname = result.isAuthenticated() ? result.getHostname().toString() : null;
+                        verifiedHostname =
+                                result.isAuthenticated() ? result.getHostname().toString() : null;
                         Log.d(Config.LOGTAG, "verified hostname " + verifiedHostname);
                         final InetSocketAddress addr;
                         if (result.getIp() != null) {
                             addr = new InetSocketAddress(result.getIp(), result.getPort());
-                            Log.d(Config.LOGTAG, account.getJid().asBareJid().toString()
-                                    + ": using values from resolver " + (result.getHostname() == null ? "" : result.getHostname().toString()
-                                    + "/") + result.getIp().getHostAddress() + ":" + result.getPort() + " tls: " + features.encryptionEnabled);
+                            Log.d(
+                                    Config.LOGTAG,
+                                    account.getJid().asBareJid().toString()
+                                            + ": using values from resolver "
+                                            + (result.getHostname() == null
+                                                    ? ""
+                                                    : result.getHostname().toString() + "/")
+                                            + result.getIp().getHostAddress()
+                                            + ":"
+                                            + result.getPort()
+                                            + " tls: "
+                                            + features.encryptionEnabled);
                         } else {
-                            addr = new InetSocketAddress(IDN.toASCII(result.getHostname().toString()), result.getPort());
-                            Log.d(Config.LOGTAG, account.getJid().asBareJid().toString()
-                                    + ": using values from resolver "
-                                    + result.getHostname().toString() + ":" + result.getPort() + " tls: " + features.encryptionEnabled);
+                            addr =
+                                    new InetSocketAddress(
+                                            IDN.toASCII(result.getHostname().toString()),
+                                            result.getPort());
+                            Log.d(
+                                    Config.LOGTAG,
+                                    account.getJid().asBareJid().toString()
+                                            + ": using values from resolver "
+                                            + result.getHostname().toString()
+                                            + ":"
+                                            + result.getPort()
+                                            + " tls: "
+                                            + features.encryptionEnabled);
                         }
 
                         localSocket = new Socket();
@@ -355,9 +407,12 @@ public class XmppConnection implements Runnable {
 
                         localSocket.setSoTimeout(Config.SOCKET_TIMEOUT * 1000);
                         if (startXmpp(localSocket)) {
-                            localSocket.setSoTimeout(0); //reset to 0; once the connection is established we don’t want this
+                            localSocket.setSoTimeout(
+                                    0); // reset to 0; once the connection is established we don’t
+                                        // want this
                             if (!hardcoded && !result.equals(storedBackupResult)) {
-                                mXmppConnectionService.databaseBackend.saveResolverResult(domain, result);
+                                mXmppConnectionService.databaseBackend.saveResolverResult(
+                                        domain, result);
                             }
                             break; // successfully connected to server that speaks xmpp
                         } else {
@@ -369,10 +424,20 @@ public class XmppConnection implements Runnable {
                             throw e;
                         }
                     } catch (InterruptedException e) {
-                        Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": thread was interrupted before beginning stream");
+                        Log.d(
+                                Config.LOGTAG,
+                                account.getJid().asBareJid()
+                                        + ": thread was interrupted before beginning stream");
                         return;
                     } catch (final Throwable e) {
-                        Log.d(Config.LOGTAG, account.getJid().asBareJid().toString() + ": " + e.getMessage() + "(" + e.getClass().getName() + ")");
+                        Log.d(
+                                Config.LOGTAG,
+                                account.getJid().asBareJid().toString()
+                                        + ": "
+                                        + e.getMessage()
+                                        + "("
+                                        + e.getClass().getName()
+                                        + ")");
                         if (!iterator.hasNext()) {
                             throw new UnknownHostException();
                         }
@@ -384,7 +449,9 @@ public class XmppConnection implements Runnable {
             this.changeStatus(Account.State.MISSING_INTERNET_PERMISSION);
         } catch (final StateChangingException e) {
             this.changeStatus(e.state);
-        } catch (final UnknownHostException | ConnectException | SocksSocketFactory.HostNotFoundException e) {
+        } catch (final UnknownHostException
+                | ConnectException
+                | SocksSocketFactory.HostNotFoundException e) {
             this.changeStatus(Account.State.SERVER_NOT_FOUND);
         } catch (final SocksSocketFactory.SocksProxyNotFoundException e) {
             this.changeStatus(Account.State.TOR_NOT_AVAILABLE);
@@ -396,7 +463,10 @@ public class XmppConnection implements Runnable {
             if (!Thread.currentThread().isInterrupted()) {
                 forceCloseSocket();
             } else {
-                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": not force closing socket because thread was interrupted");
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": not force closing socket because thread was interrupted");
             }
         }
     }
@@ -430,17 +500,26 @@ public class XmppConnection implements Runnable {
         return tag != null && tag.isStart("stream");
     }
 
-    private SSLSocketFactory getSSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException {
+    private SSLSocketFactory getSSLSocketFactory()
+            throws NoSuchAlgorithmException, KeyManagementException {
         final SSLContext sc = SSLSocketHelper.getSSLContext();
-        final MemorizingTrustManager trustManager = this.mXmppConnectionService.getMemorizingTrustManager();
+        final MemorizingTrustManager trustManager =
+                this.mXmppConnectionService.getMemorizingTrustManager();
         final KeyManager[] keyManager;
         if (account.getPrivateKeyAlias() != null) {
-            keyManager = new KeyManager[]{new MyKeyManager()};
+            keyManager = new KeyManager[] {new MyKeyManager()};
         } else {
             keyManager = null;
         }
         final String domain = account.getServer();
-        sc.init(keyManager, new X509TrustManager[]{mInteractive ? trustManager.getInteractive(domain) : trustManager.getNonInteractive(domain)}, mXmppConnectionService.getRNG());
+        sc.init(
+                keyManager,
+                new X509TrustManager[] {
+                    mInteractive
+                            ? trustManager.getInteractive(domain)
+                            : trustManager.getNonInteractive(domain)
+                },
+                mXmppConnectionService.getRNG());
         return sc.getSocketFactory();
     }
 
@@ -449,7 +528,10 @@ public class XmppConnection implements Runnable {
         synchronized (this) {
             this.mThread = Thread.currentThread();
             if (this.mThread.isInterrupted()) {
-                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": aborting connect because thread was interrupted");
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": aborting connect because thread was interrupted");
                 return;
             }
             forceCloseSocket();
@@ -540,20 +622,16 @@ public class XmppConnection implements Runnable {
                     Log.d(
                             Config.LOGTAG,
                             account.getJid().asBareJid().toString()
-                                    + ": stream management("
-                                    + smVersion
-                                    + ") enabled (resumable)");
+                                    + ": stream management enabled (resumable)");
                 } else {
                     Log.d(
                             Config.LOGTAG,
                             account.getJid().asBareJid().toString()
-                                    + ": stream management("
-                                    + smVersion
-                                    + ") enabled");
+                                    + ": stream management enabled");
                 }
                 this.stanzasReceived = 0;
                 this.inSmacksSession = true;
-                final RequestPacket r = new RequestPacket(smVersion);
+                final RequestPacket r = new RequestPacket();
                 tagWriter.writeStanzaAsync(r);
             } else if (nextTag.isStart("resumed")) {
                 final Element resumed = tagReader.readElement(nextTag);
@@ -567,7 +645,7 @@ public class XmppConnection implements Runnable {
                                     + ": acknowledging stanza #"
                                     + this.stanzasReceived);
                 }
-                final AckPacket ack = new AckPacket(this.stanzasReceived, smVersion);
+                final AckPacket ack = new AckPacket(this.stanzasReceived);
                 tagWriter.writeStanzaAsync(ack);
             } else if (nextTag.isStart("a")) {
                 boolean accountUiNeedsRefresh = false;
@@ -628,7 +706,8 @@ public class XmppConnection implements Runnable {
         }
     }
 
-    private boolean processSuccess(final Element success) throws IOException, XmlPullParserException {
+    private boolean processSuccess(final Element success)
+            throws IOException, XmlPullParserException {
         final SaslMechanism.Version version;
         try {
             version = SaslMechanism.Version.of(success);
@@ -651,20 +730,22 @@ public class XmppConnection implements Runnable {
         }
         Log.d(
                 Config.LOGTAG,
-                account.getJid().asBareJid().toString()
-                        + ": logged in (using "
-                        + version
-                        + ")");
-        account.setKey(
-                Account.PINNED_MECHANISM_KEY, String.valueOf(saslMechanism.getPriority()));
+                account.getJid().asBareJid().toString() + ": logged in (using " + version + ")");
+        account.setKey(Account.PINNED_MECHANISM_KEY, String.valueOf(saslMechanism.getPriority()));
         if (version == SaslMechanism.Version.SASL_2) {
             final String authorizationIdentifier =
                     success.findChildContent("authorization-identifier");
             final Jid authorizationJid;
             try {
-                authorizationJid = Strings.isNullOrEmpty(authorizationIdentifier) ? null : Jid.ofEscaped(authorizationIdentifier);
+                authorizationJid =
+                        Strings.isNullOrEmpty(authorizationIdentifier)
+                                ? null
+                                : Jid.ofEscaped(authorizationIdentifier);
             } catch (final IllegalArgumentException e) {
-                Log.d(Config.LOGTAG,account.getJid().asBareJid()+": SASL 2.0 authorization identifier was not a valid jid");
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": SASL 2.0 authorization identifier was not a valid jid");
                 throw new StateChangingException(Account.State.BIND_FAILURE);
             }
             if (authorizationJid == null) {
@@ -676,11 +757,18 @@ public class XmppConnection implements Runnable {
                             + ": SASL 2.0 authorization identifier was "
                             + authorizationJid);
             if (!account.getJid().getDomain().equals(authorizationJid.getDomain())) {
-                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server tried to re-assign domain to " + authorizationJid.getDomain());
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": server tried to re-assign domain to "
+                                + authorizationJid.getDomain());
                 throw new StateChangingError(Account.State.BIND_FAILURE);
             }
             if (authorizationJid.isFullJid() && account.setJid(authorizationJid)) {
-                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": jid changed during SASL 2.0. updating database");
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": jid changed during SASL 2.0. updating database");
                 mXmppConnectionService.databaseBackend.updateAccount(account);
             }
             final Element resumed = success.findChild("resumed", "urn:xmpp:sm:3");
@@ -709,7 +797,7 @@ public class XmppConnection implements Runnable {
     private void processResumed(final Element resumed) throws StateChangingException {
         this.inSmacksSession = true;
         this.isBound = true;
-        this.tagWriter.writeStanzaAsync(new RequestPacket(smVersion));
+        this.tagWriter.writeStanzaAsync(new RequestPacket());
         lastPacketReceived = SystemClock.elapsedRealtime();
         final String h = resumed.getAttribute("h");
         if (h == null) {
@@ -795,13 +883,22 @@ public class XmppConnection implements Runnable {
 
     private boolean acknowledgeStanzaUpTo(int serverCount) {
         if (serverCount > stanzasSent) {
-            Log.e(Config.LOGTAG, "server acknowledged more stanzas than we sent. serverCount=" + serverCount + ", ourCount=" + stanzasSent);
+            Log.e(
+                    Config.LOGTAG,
+                    "server acknowledged more stanzas than we sent. serverCount="
+                            + serverCount
+                            + ", ourCount="
+                            + stanzasSent);
         }
         boolean acknowledgedMessages = false;
         for (int i = 0; i < mStanzaQueue.size(); ++i) {
             if (serverCount >= mStanzaQueue.keyAt(i)) {
                 if (Config.EXTENDED_SM_LOGGING) {
-                    Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server acknowledged stanza #" + mStanzaQueue.keyAt(i));
+                    Log.d(
+                            Config.LOGTAG,
+                            account.getJid().asBareJid()
+                                    + ": server acknowledged stanza #"
+                                    + mStanzaQueue.keyAt(i));
                 }
                 final AbstractAcknowledgeableStanza stanza = mStanzaQueue.valueAt(i);
                 if (stanza instanceof MessagePacket && acknowledgedListener != null) {
@@ -809,7 +906,8 @@ public class XmppConnection implements Runnable {
                     final String id = packet.getId();
                     final Jid to = packet.getTo();
                     if (id != null && to != null) {
-                        acknowledgedMessages |= acknowledgedListener.onMessageAcknowledged(account, to, id);
+                        acknowledgedMessages |=
+                                acknowledgedListener.onMessageAcknowledged(account, to, id);
                     }
                 }
                 mStanzaQueue.removeAt(i);
@@ -819,8 +917,8 @@ public class XmppConnection implements Runnable {
         return acknowledgedMessages;
     }
 
-    private @NonNull
-    Element processPacket(final Tag currentTag, final int packetType) throws IOException {
+    private @NonNull Element processPacket(final Tag currentTag, final int packetType)
+            throws IOException {
         final Element element;
         switch (packetType) {
             case PACKET_IQ:
@@ -856,7 +954,12 @@ public class XmppConnection implements Runnable {
         if (inSmacksSession) {
             ++stanzasReceived;
         } else if (features.sm()) {
-            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": not counting stanza(" + element.getClass().getSimpleName() + "). Not in smacks session.");
+            Log.d(
+                    Config.LOGTAG,
+                    account.getJid().asBareJid()
+                            + ": not counting stanza("
+                            + element.getClass().getSimpleName()
+                            + "). Not in smacks session.");
         }
         lastPacketReceived = SystemClock.elapsedRealtime();
         if (Config.BACKGROUND_STANZA_LOGGING && mXmppConnectionService.checkListeners()) {
@@ -874,7 +977,13 @@ public class XmppConnection implements Runnable {
     private void processIq(final Tag currentTag) throws IOException {
         final IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ);
         if (!packet.valid()) {
-            Log.e(Config.LOGTAG, "encountered invalid iq from='" + packet.getFrom() + "' to='" + packet.getTo() + "'");
+            Log.e(
+                    Config.LOGTAG,
+                    "encountered invalid iq from='"
+                            + packet.getFrom()
+                            + "' to='"
+                            + packet.getTo()
+                            + "'");
             return;
         }
         if (packet instanceof JinglePacket) {
@@ -884,7 +993,8 @@ public class XmppConnection implements Runnable {
         } else {
             OnIqPacketReceived callback = null;
             synchronized (this.packetCallbacks) {
-                final Pair<IqPacket, OnIqPacketReceived> packetCallbackDuple = packetCallbacks.get(packet.getId());
+                final Pair<IqPacket, OnIqPacketReceived> packetCallbackDuple =
+                        packetCallbacks.get(packet.getId());
                 if (packetCallbackDuple != null) {
                     // Packets to the server should have responses from the server
                     if (packetCallbackDuple.first.toServer(account)) {
@@ -892,17 +1002,25 @@ public class XmppConnection implements Runnable {
                             callback = packetCallbackDuple.second;
                             packetCallbacks.remove(packet.getId());
                         } else {
-                            Log.e(Config.LOGTAG, account.getJid().asBareJid().toString() + ": ignoring spoofed iq packet");
+                            Log.e(
+                                    Config.LOGTAG,
+                                    account.getJid().asBareJid().toString()
+                                            + ": ignoring spoofed iq packet");
                         }
                     } else {
-                        if (packet.getFrom() != null && packet.getFrom().equals(packetCallbackDuple.first.getTo())) {
+                        if (packet.getFrom() != null
+                                && packet.getFrom().equals(packetCallbackDuple.first.getTo())) {
                             callback = packetCallbackDuple.second;
                             packetCallbacks.remove(packet.getId());
                         } else {
-                            Log.e(Config.LOGTAG, account.getJid().asBareJid().toString() + ": ignoring spoofed iq packet");
+                            Log.e(
+                                    Config.LOGTAG,
+                                    account.getJid().asBareJid().toString()
+                                            + ": ignoring spoofed iq packet");
                         }
                     }
-                } else if (packet.getType() == IqPacket.TYPE.GET || packet.getType() == IqPacket.TYPE.SET) {
+                } else if (packet.getType() == IqPacket.TYPE.GET
+                        || packet.getType() == IqPacket.TYPE.SET) {
                     callback = this.unregisteredIqListener;
                 }
             }
@@ -919,7 +1037,13 @@ public class XmppConnection implements Runnable {
     private void processMessage(final Tag currentTag) throws IOException {
         final MessagePacket packet = (MessagePacket) processPacket(currentTag, PACKET_MESSAGE);
         if (!packet.valid()) {
-            Log.e(Config.LOGTAG, "encountered invalid message from='" + packet.getFrom() + "' to='" + packet.getTo() + "'");
+            Log.e(
+                    Config.LOGTAG,
+                    "encountered invalid message from='"
+                            + packet.getFrom()
+                            + "' to='"
+                            + packet.getTo()
+                            + "'");
             return;
         }
         this.messageListener.onMessagePacketReceived(account, packet);
@@ -928,7 +1052,13 @@ public class XmppConnection implements Runnable {
     private void processPresence(final Tag currentTag) throws IOException {
         PresencePacket packet = (PresencePacket) processPacket(currentTag, PACKET_PRESENCE);
         if (!packet.valid()) {
-            Log.e(Config.LOGTAG, "encountered invalid presence from='" + packet.getFrom() + "' to='" + packet.getTo() + "'");
+            Log.e(
+                    Config.LOGTAG,
+                    "encountered invalid presence from='"
+                            + packet.getFrom()
+                            + "' to='"
+                            + packet.getTo()
+                            + "'");
             return;
         }
         this.presenceListener.onPresencePacketReceived(account, packet);
@@ -967,14 +1097,21 @@ public class XmppConnection implements Runnable {
             throw new StateChangingException(Account.State.TLS_ERROR);
         }
         final InetAddress address = socket.getInetAddress();
-        final SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket, address.getHostAddress(), socket.getPort(), true);
+        final SSLSocket sslSocket =
+                (SSLSocket)
+                        sslSocketFactory.createSocket(
+                                socket, address.getHostAddress(), socket.getPort(), true);
         SSLSocketHelper.setSecurity(sslSocket);
         SSLSocketHelper.setHostname(sslSocket, IDN.toASCII(account.getServer()));
         SSLSocketHelper.setApplicationProtocol(sslSocket, "xmpp-client");
         final XmppDomainVerifier xmppDomainVerifier = new XmppDomainVerifier();
         try {
-            if (!xmppDomainVerifier.verify(account.getServer(), this.verifiedHostname, sslSocket.getSession())) {
-                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": TLS certificate domain verification failed");
+            if (!xmppDomainVerifier.verify(
+                    account.getServer(), this.verifiedHostname, sslSocket.getSession())) {
+                Log.d(
+                        Config.LOGTAG,
+                        account.getJid().asBareJid()
+                                + ": TLS certificate domain verification failed");
                 FileBackend.close(sslSocket);
                 throw new StateChangingException(Account.State.TLS_ERROR_DOMAIN);
             }
@@ -1016,7 +1153,7 @@ public class XmppConnection implements Runnable {
                 && shouldAuthenticate
                 && isSecure) {
             authenticate(SaslMechanism.Version.SASL);
-        } else if (this.streamFeatures.hasChild("sm", "urn:xmpp:sm:" + smVersion)
+        } else if (this.streamFeatures.hasChild("sm", Namespace.STREAM_MANAGEMENT)
                 && streamId != null) {
             if (Config.EXTENDED_SM_LOGGING) {
                 Log.d(
@@ -1025,7 +1162,7 @@ public class XmppConnection implements Runnable {
                                 + ": resuming after stanza #"
                                 + stanzasReceived);
             }
-            final ResumePacket resume = new ResumePacket(this.streamId, stanzasReceived, smVersion);
+            final ResumePacket resume = new ResumePacket(this.streamId, stanzasReceived);
             this.mSmCatchupMessageCounter.set(0);
             this.mWaitingForSmCatchup.set(true);
             this.tagWriter.writeStanzaAsync(resume);
@@ -1059,7 +1196,8 @@ public class XmppConnection implements Runnable {
             saslMechanism = new ScramSha256(tagWriter, account, mXmppConnectionService.getRNG());
         } else if (mechanisms.contains(ScramSha1.MECHANISM)) {
             saslMechanism = new ScramSha1(tagWriter, account, mXmppConnectionService.getRNG());
-        } else if (mechanisms.contains(Plain.MECHANISM) && !account.getJid().getDomain().toEscapedString().equals("nimbuzz.com")) {
+        } else if (mechanisms.contains(Plain.MECHANISM)
+                && !account.getJid().getDomain().toEscapedString().equals("nimbuzz.com")) {
             saslMechanism = new Plain(tagWriter, account);
         } else if (mechanisms.contains(DigestMd5.MECHANISM)) {
             saslMechanism = new DigestMd5(tagWriter, account, mXmppConnectionService.getRNG());
@@ -1067,15 +1205,24 @@ public class XmppConnection implements Runnable {
             saslMechanism = new Anonymous(tagWriter, account, mXmppConnectionService.getRNG());
         }
         if (saslMechanism == null) {
-            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to find supported SASL mechanism in " + mechanisms);
+            Log.d(
+                    Config.LOGTAG,
+                    account.getJid().asBareJid()
+                            + ": unable to find supported SASL mechanism in "
+                            + mechanisms);
             throw new StateChangingException(Account.State.INCOMPATIBLE_SERVER);
         }
         final int pinnedMechanism = account.getKeyAsInt(Account.PINNED_MECHANISM_KEY, -1);
         if (pinnedMechanism > saslMechanism.getPriority()) {
-            Log.e(Config.LOGTAG, "Auth failed. Authentication mechanism " + saslMechanism.getMechanism() +
-                    " has lower priority (" + saslMechanism.getPriority() +
-                    ") than pinned priority (" + pinnedMechanism +
-                    "). Possible downgrade attack?");
+            Log.e(
+                    Config.LOGTAG,
+                    "Auth failed. Authentication mechanism "
+                            + saslMechanism.getMechanism()
+                            + " has lower priority ("
+                            + saslMechanism.getPriority()
+                            + ") than pinned priority ("
+                            + pinnedMechanism
+                            + "). Possible downgrade attack?");
             throw new StateChangingException(Account.State.DOWNGRADE_ATTACK);
         }
         final String firstMessage = saslMechanism.getClientFirstMessage();
@@ -1091,9 +1238,11 @@ public class XmppConnection implements Runnable {
                 authenticate.addChild("initial-response").setContent(firstMessage);
             }
             final Element inline = this.streamFeatures.findChild("inline", Namespace.SASL_2);
-            final boolean inlineStreamManagement = inline != null && inline.hasChild("sm", "urn:xmpp:sm:3");
+            final boolean inlineStreamManagement =
+                    inline != null && inline.hasChild("sm", "urn:xmpp:sm:3");
+            final boolean inlineBind2 = inline != null && inline.hasChild("bind", Namespace.BIND2);
             if (inlineStreamManagement && streamId != null) {
-                final ResumePacket resume = new ResumePacket(this.streamId, stanzasReceived, smVersion);
+                final ResumePacket resume = new ResumePacket(this.streamId, stanzasReceived);
                 this.mSmCatchupMessageCounter.set(0);
                 this.mWaitingForSmCatchup.set(true);
                 authenticate.addChild(resume);
@@ -1102,35 +1251,46 @@ public class XmppConnection implements Runnable {
             throw new AssertionError("Missing implementation for " + version);
         }
 
-        Log.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with "+version+ "/" + saslMechanism.getMechanism());
+        Log.d(
+                Config.LOGTAG,
+                account.getJid().toString()
+                        + ": Authenticating with "
+                        + version
+                        + "/"
+                        + saslMechanism.getMechanism());
         authenticate.setAttribute("mechanism", saslMechanism.getMechanism());
         tagWriter.writeElement(authenticate);
     }
 
     private static List<String> extractMechanisms(final Element stream) {
-        final ArrayList<String> mechanisms = new ArrayList<>(stream
-                .getChildren().size());
+        final ArrayList<String> mechanisms = new ArrayList<>(stream.getChildren().size());
         for (final Element child : stream.getChildren()) {
             mechanisms.add(child.getContent());
         }
         return mechanisms;
     }
 
-
     private void register() {
         final String preAuth = account.getKey(Account.PRE_AUTH_REGISTRATION_TOKEN);
         if (preAuth != null && features.invite()) {
             final IqPacket preAuthRequest = new IqPacket(IqPacket.TYPE.SET);
             preAuthRequest.addChild("preauth", Namespace.PARS).setAttribute("token", preAuth);
-            sendUnmodifiedIqPacket(preAuthRequest, (account, response) -> {
-                if (response.getType() == IqPacket.TYPE.RESULT) {
-                    sendRegistryRequest();
-                } else {
-                    final String error = response.getErrorCondition();
-                    Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": failed to pre auth. " + error);
-                    throw new StateChangingError(Account.State.REGISTRATION_INVALID_TOKEN);
-                }
-            }, true);
+            sendUnmodifiedIqPacket(
+                    preAuthRequest,
+                    (account, response) -> {
+                        if (response.getType() == IqPacket.TYPE.RESULT) {
+                            sendRegistryRequest();
+                        } else {
+                            final String error = response.getErrorCondition();
+                            Log.d(
+                                    Config.LOGTAG,
+                                    account.getJid().asBareJid()
+                                            + ": failed to pre auth. "
+                                            + error);
+                            throw new StateChangingError(Account.State.REGISTRATION_INVALID_TOKEN);
+                        }
+                    },
+                    true);
         } else {
             sendRegistryRequest();
         }
@@ -1140,79 +1300,91 @@ public class XmppConnection implements Runnable {
         final IqPacket register = new IqPacket(IqPacket.TYPE.GET);
         register.query(Namespace.REGISTER);
         register.setTo(account.getDomain());
-        sendUnmodifiedIqPacket(register, (account, packet) -> {
-            if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
-                return;
-            }
-            if (packet.getType() == IqPacket.TYPE.ERROR) {
-                throw new StateChangingError(Account.State.REGISTRATION_FAILED);
-            }
-            final Element query = packet.query(Namespace.REGISTER);
-            if (query.hasChild("username") && (query.hasChild("password"))) {
-                final IqPacket register1 = new IqPacket(IqPacket.TYPE.SET);
-                final Element username = new Element("username").setContent(account.getUsername());
-                final Element password = new Element("password").setContent(account.getPassword());
-                register1.query(Namespace.REGISTER).addChild(username);
-                register1.query().addChild(password);
-                register1.setFrom(account.getJid().asBareJid());
-                sendUnmodifiedIqPacket(register1, registrationResponseListener, true);
-            } else if (query.hasChild("x", Namespace.DATA)) {
-                final Data data = Data.parse(query.findChild("x", Namespace.DATA));
-                final Element blob = query.findChild("data", "urn:xmpp:bob");
-                final String id = packet.getId();
-                InputStream is;
-                if (blob != null) {
-                    try {
-                        final String base64Blob = blob.getContent();
-                        final byte[] strBlob = Base64.decode(base64Blob, Base64.DEFAULT);
-                        is = new ByteArrayInputStream(strBlob);
-                    } catch (Exception e) {
-                        is = null;
+        sendUnmodifiedIqPacket(
+                register,
+                (account, packet) -> {
+                    if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
+                        return;
                     }
-                } else {
-                    final boolean useTor = mXmppConnectionService.useTorToConnect() || account.isOnion();
-                    try {
-                        final String url = data.getValue("url");
-                        final String fallbackUrl = data.getValue("captcha-fallback-url");
-                        if (url != null) {
-                            is = HttpConnectionManager.open(url, useTor);
-                        } else if (fallbackUrl != null) {
-                            is = HttpConnectionManager.open(fallbackUrl, useTor);
+                    if (packet.getType() == IqPacket.TYPE.ERROR) {
+                        throw new StateChangingError(Account.State.REGISTRATION_FAILED);
+                    }
+                    final Element query = packet.query(Namespace.REGISTER);
+                    if (query.hasChild("username") && (query.hasChild("password"))) {
+                        final IqPacket register1 = new IqPacket(IqPacket.TYPE.SET);
+                        final Element username =
+                                new Element("username").setContent(account.getUsername());
+                        final Element password =
+                                new Element("password").setContent(account.getPassword());
+                        register1.query(Namespace.REGISTER).addChild(username);
+                        register1.query().addChild(password);
+                        register1.setFrom(account.getJid().asBareJid());
+                        sendUnmodifiedIqPacket(register1, registrationResponseListener, true);
+                    } else if (query.hasChild("x", Namespace.DATA)) {
+                        final Data data = Data.parse(query.findChild("x", Namespace.DATA));
+                        final Element blob = query.findChild("data", "urn:xmpp:bob");
+                        final String id = packet.getId();
+                        InputStream is;
+                        if (blob != null) {
+                            try {
+                                final String base64Blob = blob.getContent();
+                                final byte[] strBlob = Base64.decode(base64Blob, Base64.DEFAULT);
+                                is = new ByteArrayInputStream(strBlob);
+                            } catch (Exception e) {
+                                is = null;
+                            }
                         } else {
-                            is = null;
+                            final boolean useTor =
+                                    mXmppConnectionService.useTorToConnect() || account.isOnion();
+                            try {
+                                final String url = data.getValue("url");
+                                final String fallbackUrl = data.getValue("captcha-fallback-url");
+                                if (url != null) {
+                                    is = HttpConnectionManager.open(url, useTor);
+                                } else if (fallbackUrl != null) {
+                                    is = HttpConnectionManager.open(fallbackUrl, useTor);
+                                } else {
+                                    is = null;
+                                }
+                            } catch (final IOException e) {
+                                Log.d(
+                                        Config.LOGTAG,
+                                        account.getJid().asBareJid() + ": unable to fetch captcha",
+                                        e);
+                                is = null;
+                            }
                         }
-                    } catch (final IOException e) {
-                        Log.d(Config.LOGTAG,account.getJid().asBareJid()+": unable to fetch captcha", e);
-                        is = null;
-                    }
-                }
 
-                if (is != null) {
-                    Bitmap captcha = BitmapFactory.decodeStream(is);
-                    try {
-                        if (mXmppConnectionService.displayCaptchaRequest(account, id, data, captcha)) {
-                            return;
+                        if (is != null) {
+                            Bitmap captcha = BitmapFactory.decodeStream(is);
+                            try {
+                                if (mXmppConnectionService.displayCaptchaRequest(
+                                        account, id, data, captcha)) {
+                                    return;
+                                }
+                            } catch (Exception e) {
+                                throw new StateChangingError(Account.State.REGISTRATION_FAILED);
+                            }
+                        }
+                        throw new StateChangingError(Account.State.REGISTRATION_FAILED);
+                    } else if (query.hasChild("instructions")
+                            || query.hasChild("x", Namespace.OOB)) {
+                        final String instructions = query.findChildContent("instructions");
+                        final Element oob = query.findChild("x", Namespace.OOB);
+                        final String url = oob == null ? null : oob.findChildContent("url");
+                        if (url != null) {
+                            setAccountCreationFailed(url);
+                        } else if (instructions != null) {
+                            final Matcher matcher = Patterns.AUTOLINK_WEB_URL.matcher(instructions);
+                            if (matcher.find()) {
+                                setAccountCreationFailed(
+                                        instructions.substring(matcher.start(), matcher.end()));
+                            }
                         }
-                    } catch (Exception e) {
                         throw new StateChangingError(Account.State.REGISTRATION_FAILED);
                     }
-                }
-                throw new StateChangingError(Account.State.REGISTRATION_FAILED);
-            } else if (query.hasChild("instructions") || query.hasChild("x", Namespace.OOB)) {
-                final String instructions = query.findChildContent("instructions");
-                final Element oob = query.findChild("x", Namespace.OOB);
-                final String url = oob == null ? null : oob.findChildContent("url");
-                if (url != null) {
-                    setAccountCreationFailed(url);
-                } else if (instructions != null) {
-                    final Matcher matcher = Patterns.AUTOLINK_WEB_URL.matcher(instructions);
-                    if (matcher.find()) {
-                        setAccountCreationFailed(instructions.substring(matcher.start(), matcher.end()));
-                    }
-                }
-                throw new StateChangingError(Account.State.REGISTRATION_FAILED);
-            }
-        }, true);
+                },
+                true);
     }
 
     private void setAccountCreationFailed(final String url) {
@@ -1247,7 +1419,10 @@ public class XmppConnection implements Runnable {
         try {
             mXmppConnectionService.restoredFromDatabaseLatch.await();
         } catch (InterruptedException e) {
-            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": interrupted while waiting for DB restore during bind");
+            Log.d(
+                    Config.LOGTAG,
+                    account.getJid().asBareJid()
+                            + ": interrupted while waiting for DB restore during bind");
             return;
         }
         clearIqCallbacks();
@@ -1257,49 +1432,76 @@ public class XmppConnection implements Runnable {
             fixResource(mXmppConnectionService, account);
         }
         final IqPacket iq = new IqPacket(IqPacket.TYPE.SET);
-        final String resource = Config.USE_RANDOM_RESOURCE_ON_EVERY_BIND ? nextRandomId() : account.getResource();
+        final String resource =
+                Config.USE_RANDOM_RESOURCE_ON_EVERY_BIND ? nextRandomId() : account.getResource();
         iq.addChild("bind", Namespace.BIND).addChild("resource").setContent(resource);
-        this.sendUnmodifiedIqPacket(iq, (account, packet) -> {
-            if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
-                return;
-            }
-            final Element bind = packet.findChild("bind");
-            if (bind != null && packet.getType() == IqPacket.TYPE.RESULT) {
-                isBound = true;
-                final Element jid = bind.findChild("jid");
-                if (jid != null && jid.getContent() != null) {
-                    try {
-                        Jid assignedJid = Jid.ofEscaped(jid.getContent());
-                        if (!account.getJid().getDomain().equals(assignedJid.getDomain())) {
-                            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server tried to re-assign domain to " + assignedJid.getDomain());
-                            throw new StateChangingError(Account.State.BIND_FAILURE);
-                        }
-                        if (account.setJid(assignedJid)) {
-                            Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": jid changed during bind. updating database");
-                            mXmppConnectionService.databaseBackend.updateAccount(account);
-                        }
-                        if (streamFeatures.hasChild("session")
-                                && !streamFeatures.findChild("session").hasChild("optional")) {
-                            sendStartSession();
+        this.sendUnmodifiedIqPacket(
+                iq,
+                (account, packet) -> {
+                    if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
+                        return;
+                    }
+                    final Element bind = packet.findChild("bind");
+                    if (bind != null && packet.getType() == IqPacket.TYPE.RESULT) {
+                        isBound = true;
+                        final Element jid = bind.findChild("jid");
+                        if (jid != null && jid.getContent() != null) {
+                            try {
+                                Jid assignedJid = Jid.ofEscaped(jid.getContent());
+                                if (!account.getJid().getDomain().equals(assignedJid.getDomain())) {
+                                    Log.d(
+                                            Config.LOGTAG,
+                                            account.getJid().asBareJid()
+                                                    + ": server tried to re-assign domain to "
+                                                    + assignedJid.getDomain());
+                                    throw new StateChangingError(Account.State.BIND_FAILURE);
+                                }
+                                if (account.setJid(assignedJid)) {
+                                    Log.d(
+                                            Config.LOGTAG,
+                                            account.getJid().asBareJid()
+                                                    + ": jid changed during bind. updating database");
+                                    mXmppConnectionService.databaseBackend.updateAccount(account);
+                                }
+                                if (streamFeatures.hasChild("session")
+                                        && !streamFeatures
+                                                .findChild("session")
+                                                .hasChild("optional")) {
+                                    sendStartSession();
+                                } else {
+                                    sendPostBindInitialization();
+                                }
+                                return;
+                            } catch (final IllegalArgumentException e) {
+                                Log.d(
+                                        Config.LOGTAG,
+                                        account.getJid().asBareJid()
+                                                + ": server reported invalid jid ("
+                                                + jid.getContent()
+                                                + ") on bind");
+                            }
                         } else {
-                            sendPostBindInitialization();
+                            Log.d(
+                                    Config.LOGTAG,
+                                    account.getJid()
+                                            + ": disconnecting because of bind failure. (no jid)");
                         }
-                        return;
-                    } catch (final IllegalArgumentException e) {
-                        Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": server reported invalid jid (" + jid.getContent() + ") on bind");
+                    } else {
+                        Log.d(
+                                Config.LOGTAG,
+                                account.getJid()
+                                        + ": disconnecting because of bind failure ("
+                                        + packet);
                     }
-                } else {
-                    Log.d(Config.LOGTAG, account.getJid() + ": disconnecting because of bind failure. (no jid)");
-                }
-            } else {
-                Log.d(Config.LOGTAG, account.getJid() + ": disconnecting because of bind failure (" + packet);
-            }
-            final Element error = packet.findChild("error");
-            if (packet.getType() == IqPacket.TYPE.ERROR && error != null && error.hasChild("conflict")) {
-                account.setResource(createNewResource());
-            }
-            throw new StateChangingError(Account.State.BIND_FAILURE);
-        }, true);
+                    final Element error = packet.findChild("error");
+                    if (packet.getType() == IqPacket.TYPE.ERROR
+                            && error != null
+                            && error.hasChild("conflict")) {
+                        account.setResource(createNewResource());
+                    }
+                    throw new StateChangingError(Account.State.BIND_FAILURE);
+                },
+                true);
     }
 
     private void clearIqCallbacks() {

src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/ActivePacket.java πŸ”—

@@ -1,10 +1,11 @@
 package eu.siacs.conversations.xmpp.stanzas.csi;
 
+import eu.siacs.conversations.xml.Namespace;
 import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
 
 public class ActivePacket extends AbstractStanza {
 	public ActivePacket() {
 		super("active");
-		setAttribute("xmlns", "urn:xmpp:csi:0");
+		setAttribute("xmlns", Namespace.CSI);
 	}
 }

src/main/java/eu/siacs/conversations/xmpp/stanzas/csi/InactivePacket.java πŸ”—

@@ -1,10 +1,11 @@
 package eu.siacs.conversations.xmpp.stanzas.csi;
 
+import eu.siacs.conversations.xml.Namespace;
 import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
 
 public class InactivePacket extends AbstractStanza {
 	public InactivePacket() {
 		super("inactive");
-		setAttribute("xmlns", "urn:xmpp:csi:0");
+		setAttribute("xmlns", Namespace.CSI);
 	}
 }

src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/AckPacket.java πŸ”—

@@ -1,12 +1,13 @@
 package eu.siacs.conversations.xmpp.stanzas.streammgmt;
 
+import eu.siacs.conversations.xml.Namespace;
 import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
 
 public class AckPacket extends AbstractStanza {
 
-	public AckPacket(int sequence, int smVersion) {
+	public AckPacket(final int sequence) {
 		super("a");
-		this.setAttribute("xmlns", "urn:xmpp:sm:" + smVersion);
+		this.setAttribute("xmlns", Namespace.STREAM_MANAGEMENT);
 		this.setAttribute("h", Integer.toString(sequence));
 	}
 

src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/EnablePacket.java πŸ”—

@@ -1,12 +1,13 @@
 package eu.siacs.conversations.xmpp.stanzas.streammgmt;
 
+import eu.siacs.conversations.xml.Namespace;
 import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
 
 public class EnablePacket extends AbstractStanza {
 
-	public EnablePacket(int smVersion) {
+	public EnablePacket() {
 		super("enable");
-		this.setAttribute("xmlns", "urn:xmpp:sm:" + smVersion);
+		this.setAttribute("xmlns", Namespace.STREAM_MANAGEMENT);
 		this.setAttribute("resume", "true");
 	}
 

src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/RequestPacket.java πŸ”—

@@ -1,12 +1,13 @@
 package eu.siacs.conversations.xmpp.stanzas.streammgmt;
 
+import eu.siacs.conversations.xml.Namespace;
 import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
 
 public class RequestPacket extends AbstractStanza {
 
-	public RequestPacket(int smVersion) {
+	public RequestPacket() {
 		super("r");
-		this.setAttribute("xmlns", "urn:xmpp:sm:" + smVersion);
+		this.setAttribute("xmlns", Namespace.STREAM_MANAGEMENT);
 	}
 
 }

src/main/java/eu/siacs/conversations/xmpp/stanzas/streammgmt/ResumePacket.java πŸ”—

@@ -1,12 +1,13 @@
 package eu.siacs.conversations.xmpp.stanzas.streammgmt;
 
+import eu.siacs.conversations.xml.Namespace;
 import eu.siacs.conversations.xmpp.stanzas.AbstractStanza;
 
 public class ResumePacket extends AbstractStanza {
 
-	public ResumePacket(String id, int sequence, int smVersion) {
+	public ResumePacket(final String id, final int sequence) {
 		super("resume");
-		this.setAttribute("xmlns", "urn:xmpp:sm:" + smVersion);
+		this.setAttribute("xmlns", Namespace.STREAM_MANAGEMENT);
 		this.setAttribute("previd", id);
 		this.setAttribute("h", Integer.toString(sequence));
 	}