powered by Jive Software

Smack 4.4.3: Does not response to <stream:error> and instead throws NoResponseException

While testing aTalk server login with EXTERNAL client certificate authentication, smack auto issues </stream:stream> to close the stream on error. However smack does not response to the server reply stanza i.e.:

    <stream:error>
      <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
    </stream:error>

Instead it throws SmackException$NoResponseException, after holding the process for the defined smack timeout. This causes problem for aTalk to handle “Failed to get peer certificate” to request user action.

2021-09-25 10:49:24.931 6952-8791/org.atalk.android D/SMACK: SENT (1): 
    <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='EXTERNAL'>
      c3dvcmRmaXNoQGF0YWxrLnN5dGVzLm5ldA==
    </auth>
2021-09-25 10:49:24.939 6952-8792/org.atalk.android D/SMACK: RECV (1): 
    <failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
      <not-authorized/>
      <text xml:lang='en'>
        Failed to get peer certificate
      </text>
    </failure>
2021-09-25 10:49:24.949 6952-8791/org.atalk.android D/SMACK: SENT (1): 
    </stream:stream>
2021-09-25 10:49:24.957 6952-8792/org.atalk.android D/SMACK: RECV (1): 
    <stream:error>
      <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
    </stream:error>
2021-09-25 10:49:54.961 6952-8785/org.atalk.android I/aTalk: [80042] org.jivesoftware.smack.AbstractXMPPConnection.waitForClosingStreamTagFromServer() Exception while waiting for closing stream element from the server XMPPTCPConnection[not-authenticated] (1)
    org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 30000ms (~30s). While waiting for closing stream tag from the server [XMPPTCPConnection[not-authenticated] (1)]
        at org.jivesoftware.smack.AbstractXMPPConnection.waitForConditionOrConnectionException(AbstractXMPPConnection.java:732)
        at org.jivesoftware.smack.AbstractXMPPConnection.waitForConditionOrThrowConnectionException(AbstractXMPPConnection.java:737)
        at org.jivesoftware.smack.AbstractXMPPConnection.waitForClosingStreamTagFromServer(AbstractXMPPConnection.java:1024)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.shutdown(XMPPTCPConnection.java:512)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.shutdown(XMPPTCPConnection.java:492)
        at org.jivesoftware.smack.AbstractXMPPConnection.disconnect(AbstractXMPPConnection.java:972)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.disconnectAndCleanConnection(ProtocolProviderServiceJabberImpl.java:1578)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.initializeConnectAndLogin(ProtocolProviderServiceJabberImpl.java:768)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.register(ProtocolProviderServiceJabberImpl.java:619)
        at net.java.sip.communicator.util.account.LoginManager$RegisterProvider.run(LoginManager.java:307)
2021-09-25 10:49:54.967 6952-8785/org.atalk.android E/(LoginManager.java:312)#run: Failed to register protocol provider. 
    java.lang.AssertionError
        at org.jivesoftware.smackx.carbons.CarbonManager$3.connectionClosed(CarbonManager.java:158)
        at org.jivesoftware.smack.AbstractXMPPConnection.callConnectionClosedListener(AbstractXMPPConnection.java:1722)
        at org.jivesoftware.smack.AbstractXMPPConnection.disconnect(AbstractXMPPConnection.java:973)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.disconnectAndCleanConnection(ProtocolProviderServiceJabberImpl.java:1578)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.initializeConnectAndLogin(ProtocolProviderServiceJabberImpl.java:768)
        at net.java.sip.communicator.impl.protocol.jabber.ProtocolProviderServiceJabberImpl.register(ProtocolProviderServiceJabberImpl.java:619)
        at net.java.sip.communicator.util.account.LoginManager$RegisterProvider.run(LoginManager.java:307)

Sorry, the issue of </stream:stream> is from aTalk. Now I include a check for isAuthenticated before proceed. So aTalk is now able handle the SASLError.

By the way, should smack handle <stream:error/> instead of throwing as NoResponseException

Smack does setup a listener for the ‘failure’ nonza at

And this should be propagated up the call chain. I am not sure why this wouldn’t be the case for you. Consider adding a breakpoint to authenticationFailed and SASLMechanism.throwExceptionifRequired() to see where it is lost.

The NoResponseException is due the server not sending a closing ‘stream’ tag after the server send the stream:error.

I am also curous why you trigger the assert in CarbonManager:158.

I think I understand now why.

Not sure if it is too late to offer my view point of the observation.

The below code is actually used by aTalk for stream disconnect; which is not correct as aTalk has not registered with the server yet.

        if (mConnection.isConnected()) {
            try {
                PresenceBuilder presenceBuilder
                        = mConnection.getStanzaFactory().buildPresenceStanza().ofType(Presence.Type.unavailable);
                if ((OpSetPP != null) && StringUtils.isNotEmpty(OpSetPP.getCurrentStatusMessage())) {
                    presenceBuilder.setStatus(OpSetPP.getCurrentStatusMessage());
                }
                mConnection.disconnect(presenceBuilder.build());
            } catch (Exception ex) {
                Timber.w("Exception while disconnect and clean connection!!!");
            }
        }

This leads smack to execute the following:

    public synchronized void disconnect(Presence unavailablePresence) throws NotConnectedException {
        if (unavailablePresence != null) {
            try {
                sendStanza(unavailablePresence);
            } catch (InterruptedException e) {
                LOGGER.log(Level.FINE,
                        "Was interrupted while sending unavailable presence. Continuing to disconnect the connection",
                        e);
            }
        }
        shutdown();
        callConnectionClosedListener();
    }

I believe this causes smack to wait for the closed stream from server.
However aTalk is not authorised to close the stream as it has not registered with the server; hence the problem.

    <stream:error>
      <not-authorized xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
    </stream:error>