@Override
    boolean processUnknowPacket(Element doc) {
        String rootTagName = doc.getName();

        // Handle features
        if ("features".equals(rootTagName)) {

            // Prevent falling back to dialback if we are already authenticated
            if (session.isAuthenticated()) {
                return true;
            }

            // Encryption ------
            if (shouldUseTls() && remoteFeaturesContainsStartTLS(doc)) {
                LOG.debug("Both us and the remote server support the STARTTLS feature. Encrypt and authenticate the connection with TLS & SASL...");
                LOG.debug("Indicating we want TLS and wait for response.");
                connection.deliverRawText("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
                startedTLS = true;
                return true;
            } else if (mustUseTls() && !connection.isEncrypted()) {
                LOG.debug("I MUST use TLS but I have no StartTLS in features.");
                abandonSessionInitiation();
                return false;
            } else if (cannotUseTls() && remoteFeaturesRequiresStartTLS(doc)) {
                LOG.debug("I CANNOT use TLS but remote server requires the STARTTLS feature.");
                abandonSessionInitiation();
                return false;
            }

            // Authentication ------
            LOG.debug("Check if both us as well as the remote server have enabled STARTTLS and/or dialback ...");
            final boolean saslExternalOffered = isSaslExternalOfferred(doc);
            final boolean dialbackOffered = isDialbackOffered(doc);
            LOG.debug("Remote server is offering dialback: {}, EXTERNAL SASL: {}", dialbackOffered, saslExternalOffered);

            // First, try SASL
            if (saslExternalOffered) {
                LOG.debug("Trying to authenticate with EXTERNAL SASL.");
                LOG.debug("Starting EXTERNAL SASL for: " + domainPair);

                final Element auth = DocumentHelper.createElement(QName.get("auth", "urn:ietf:params:xml:ns:xmpp-sasl"));
                auth.addAttribute("mechanism", "EXTERNAL");
                // XMPP does not _require_ an authzid to be sent (see RFC-6120, section 6.3.8). XEP-0178 suggests doing so for backwards compatibility.
                if (SASLAuthentication.EXTERNAL_S2S_SKIP_SENDING_AUTHZID.getValue()) {
                    auth.addText("=");
                } else {
                    auth.addText(Base64.getEncoder().encodeToString(domainPair.getLocal().getBytes(StandardCharsets.UTF_8)));
                }
                connection.deliverRawText(auth.asXML());
                startedSASL = true;
                return true;
            } else if (dialbackOffered && (ServerDialback.isEnabled() || ServerDialback.isEnabledForSelfSigned())) {
                // Next, try dialback
                LOG.debug("Trying to authenticate using dialback.");
                LOG.debug("[Acting as Originating Server: Authenticate domain: " + domainPair.getLocal() + " with a RS in the domain of: " + domainPair.getRemote() + " (id: " + session.getStreamID() + ")]");
                ServerDialback dialback = new ServerDialback(connection, domainPair);
                dialback.createAndSendDialbackKey(session.getStreamID().getID());
                return true;
            } else {
                LOG.debug("No authentication mechanism available.");
                abandonSessionInitiation();
                return false;
            }
        }

        // Handle dialback result
        if ("db".equals(doc.getNamespacePrefix()) && "result".equals(rootTagName)) {
            if ("valid".equals(doc.attributeValue("type"))) {
                LOG.debug("Authentication succeeded!");
                LOG.debug("Dialback was successful.");

                connection.init(session);
                // Set the remote domain name as the address of the session.
                session.setAddress(new JID(null, domainPair.getRemote(), null));
                if (session instanceof LocalOutgoingServerSession) {
                    ((LocalOutgoingServerSession) session).setAuthenticationMethod(ServerSession.AuthenticationMethod.DIALBACK);
                }

                // Make sure to set 'authenticated' only after the internal state of 'session' itself is updated, to avoid race conditions.
                isSessionAuthenticated.complete(null);

                return true;
            } else {
                LOG.debug("Dialback failed");
                LOG.debug("Failed to authenticate domain: the validation response was received, but did not grant authentication.");
                return false;
            }
        }

        // Handles SASL failure
        if ("failure".equals(rootTagName)) {
            LOG.debug("EXTERNAL SASL failed.");

            // Try dialback
            if (ServerDialback.isEnabled() || ServerDialback.isEnabledForSelfSigned()) {

                LOG.debug("Trying to authenticate using dialback.");
                LOG.debug("[Acting as Originating Server: Authenticate domain: " + domainPair.getLocal() + " with a RS in the domain of: " + domainPair.getRemote() + " (id: " + session.getStreamID() + ")]");
                ServerDialback dialback = new ServerDialback(connection, domainPair);
                dialback.createAndSendDialbackKey(session.getStreamID().getID());
                return true;
            }

            return false;
        }

        // Handles SASL success
        if ("success".equals(rootTagName)) {
            LOG.debug("EXTERNAL SASL was successful.");

            // SASL was successful so initiate a new stream
            final Element stream = DocumentHelper.createElement(QName.get("stream", "stream", "http://etherx.jabber.org/streams"));
            final Document document = DocumentHelper.createDocument(stream);
            document.setXMLEncoding(StandardCharsets.UTF_8.toString());
            stream.add(Namespace.get("jabber:server"));
            stream.addAttribute("from", domainPair.getLocal()); // OF-673
            stream.addAttribute("to", domainPair.getRemote());
            stream.addAttribute("version", "1.0");

            connection.deliverRawText(StringUtils.asUnclosedStream(document));

            connection.init(session);
            // Set the remote domain name as the address of the session.
            session.setAddress(new JID(null, domainPair.getRemote(), null));
            if (session instanceof LocalOutgoingServerSession) {
                ((LocalOutgoingServerSession) session).setAuthenticationMethod(ServerSession.AuthenticationMethod.SASL_EXTERNAL);
            } else {
                LOG.warn("Expected session to be a LocalOutgoingServerSession but it isn't, unable to setAuthenticationMethod(). Session: {}", session);
                return false;
            }

            // Make sure to set 'authenticated' only after the internal state of 'session' itself is updated, to avoid race conditions.
            isSessionAuthenticated.complete(null);
            return true;
        }

        // Handles proceed (prior to TLS negotiation)
        if (rootTagName.equals("proceed")) {
            LOG.debug("Received 'proceed' from remote server. Negotiating TLS...");

            try {
                LOG.debug("Encrypting and authenticating connection ...");
                connection.startTLS(true, false);
            } catch (Exception e) {
                LOG.debug("TLS negotiation failed to start: " + e.getMessage());
                return false;
            }
            return true;
        }

        return false;
    }
Transfer an existing connection to a new session when a new streamID is detected. Also transfers existing
authentication method if previously set.
@param newStreamId new stream ID for the new session
@param existingAuthMethod authentication method used previously (possibly null)
xmppserver/src/main/java/org/jivesoftware/openfire/net/RespondingServerStanzaHandler.java