Smack 4.4.0-alpha5 does not immediately throws StreamErrorException to the calling app for action

Following is a capture of the aTalk debug log on StreamErrorException condition.
It is found that smack-4.4.0-alpha5 does not immediately re-throw this StreamErrorException nor return via ConnectionListener#connectionClosedOnError() to the app for action. Instead it only returns the Exception on response timeout: i.e.

org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 30000ms (~30s). While waiting for establishing TLS [XMPPTCPConnection[not-authenticated] (4)]

Found that the problem is due to new notifyConnectionError() implementation:

    protected final void notifyConnectionError(final Exception exception) {
        synchronized (notifyConnectionErrorMonitor) {
            if (!isConnected()) {
                LOGGER.log(Level.INFO, "Connection was already disconnected when attempting to handle " + exception,
                                exception);
                return;
            }

            // Note that we first have to set the current connection exception and notify waiting threads, as one of them
            // could hold the instance lock, which we also need later when calling instantShutdown().
            setCurrentConnectionExceptionAndNotify(exception);

            // Closes the connection temporary. A if the connection supports stream management, then a reconnection is
            // possible. Note that a connection listener of e.g. XMPPTCPConnection will drop the SM state in
            // case the Exception is a StreamErrorException.
            instantShutdown();

            for (StanzaCollector collector : collectors) {
                collector.notifyConnectionError(exception);
            }

            Async.go(() -> {
                // Notify connection listeners of the error.
                callConnectionClosedOnErrorListener(exception);
            }, AbstractXMPPConnection.this + " callConnectionClosedOnErrorListener()");
        }
    }
2020-08-06 13:08:06.265 19830-20423/org.atalk.android D/SMACK: SENT (0): 
    <stream:stream xmlns='jabber:client' to='atalk.sytes.net' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
2020-08-06 13:08:06.333 19830-20424/org.atalk.android D/SMACK: RECV (0): ?xml version='1.0'?>
    <stream:stream id='16420577292739412012' version='1.0' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' from='atalk.sytes.net' xmlns='jabber:client'>
    <stream:error>
      <policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
      <text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-streams'>
        Too many (20) failed authentications from this IP address (::ffff:42.60.7.13). The address will be unblocked at 05:15:34 06.08.2020 UTC
      </text>
    </stream:error>
    </stream:stream>
2020-08-06 13:08:06.346 19830-20424/org.atalk.android I/aTalk: [241896] org.jivesoftware.smack.AbstractXMPPConnection.notifyConnectionError() Connection was already disconnected when attempting to handle org.jivesoftware.smack.XMPPException$StreamErrorException: policy-violation You can read more about the meaning of this stream error at http://xmpp.org/rfcs/rfc6120.html#streams-error-conditions
    <stream:error><policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en'>Too many (20) failed authentications from this IP address (::ffff:42.60.7.13). The address will be unblocked at 05:15:34 06.08.2020 UTC</text></stream:error>
    org.jivesoftware.smack.XMPPException$StreamErrorException: policy-violation You can read more about the meaning of this stream error at http://xmpp.org/rfcs/rfc6120.html#streams-error-conditions
    <stream:error><policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en'>Too many (20) failed authentications from this IP address (::ffff:42.60.7.13). The address will be unblocked at 05:15:34 06.08.2020 UTC</text></stream:error>
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:966)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921)
        at java.lang.Thread.run(Thread.java:919)

Pending on when the StreamErrorException is being thrown, if after the connection is made etc, then the following can also happen.

2020-08-06 13:26:06.154 22680-22847/org.atalk.android W/g.atalk.androi: Long monitor contention with owner Thread-15 (22836) at void org.jivesoftware.smack.AbstractXMPPConnection.login(java.lang.CharSequence, java.lang.String, org.jxmpp.jid.parts.Resourcepart)(AbstractXMPPConnection.java:-1) waiters=0 in void org.jivesoftware.smack.tcp.XMPPTCPConnection.instantShutdown() for 29.122s
2020-08-06 13:26:06.167 22680-22867/org.atalk.android W/aTalk: [242028] org.jivesoftware.smack.AbstractXMPPConnection.callConnectionClosedOnErrorListener() Connection XMPPTCPConnection[not-authenticated] (0) closed with error
    org.jivesoftware.smack.XMPPException$StreamErrorException: policy-violation You can read more about the meaning of this stream error at http://xmpp.org/rfcs/rfc6120.html#streams-error-conditions
    <stream:error><policy-violation xmlns='urn:ietf:params:xml:ns:xmpp-streams'/><text xml:lang='en'>Too many (20) failed authentications from this IP address (::ffff:42.60.7.13). The address will be unblocked at 06:25:35 06.08.2020 UTC</text></stream:error>
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:966)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$700(XMPPTCPConnection.java:898)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:921)
        at java.lang.Thread.run(Thread.java:919)

Could you elaborate your findings on the problem instead of just showing the problematic code part?

I think I understand now what the issue is: the stream error exception is ignored because the connection is not assumed to be connected when the notifyConnectionError() callback is invoked.

Suggested fix

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