private synchronized void sendStreamFeatures() throws IOException
        {
            final Element stream = DocumentHelper.createElement(QName.get("stream", "stream", "http://etherx.jabber.org/streams"));
            final Document document = DocumentHelper.createDocument(stream);
            final Element features = DocumentHelper.createElement(QName.get("features", "stream", "http://etherx.jabber.org/streams"));
            document.getRootElement().add(features);

            if (!(socket instanceof SSLSocket)) {
                if (encryptionPolicy != Connection.TLSPolicy.disabled) {
                    final Element startTLS = features.addElement(QName.get("starttls", "urn:ietf:params:xml:ns:xmpp-tls"));
                    if (encryptionPolicy == Connection.TLSPolicy.required) {
                        startTLS.addElement("required");
                    }
                }
                if (!isAuthenticated) {
                    if (!disableDialback && encryptionPolicy != Connection.TLSPolicy.required) { // do not offer Dialback if we expect TLS first.
                        features.addElement(QName.get("dialback", "urn:xmpp:features:dialback"));
                        allowableSocketTimeouts = 10; // It's possible that the peer will start dialback. If that's happening, we need to be more forgiving in regard to socket timeouts.
                    }
                }
            } else if (!isAuthenticated) {
                if (!disableDialback) {
                    features.addElement(QName.get("dialback", "urn:xmpp:features:dialback"));
                    allowableSocketTimeouts = 10; // It's possible that the peer will start dialback. If that's happening, we need to be more forgiving in regard to socket timeouts.
                }
                final Element mechanisms = features.addElement(QName.get("mechanisms", "urn:ietf:params:xml:ns:xmpp-sasl"));
                log(((SSLSocket) socket).getSession().getProtocol());
                log(((SSLSocket) socket).getSession().getCipherSuite());

                try {
                    // Throws an exception if the peer (local server) doesn't send a certificate
                    log("" + ((SSLSocket) socket).getSession().getPeerPrincipal());
                    Certificate[] certificates = ((SSLSocket) socket).getSession().getPeerCertificates();
                    if (certificates != null && encryptionPolicy != Connection.TLSPolicy.disabled) {
                        try {
                            ((X509Certificate) certificates[0]).checkValidity(); // first peer certificate will belong to the local server
                            mechanisms.addElement("mechanism").addText("EXTERNAL");
                        } catch (CertificateExpiredException | CertificateNotYetValidException e) {
                            log("local certificate is invalid");
                        }
                    }
                } catch (SSLPeerUnverifiedException e) {
                    log("local certificate is missing/unverified");
                }
            }

            final String result = stream.asXML(); // String opening and closing element. Opening element needs to be written by parser, to avoid namespace declaration on child element.
            final String streamStripped = result.substring(result.indexOf('>')+1, result.lastIndexOf("</stream:stream>")).trim();
            send(streamStripped);
        }
To speed up the test execution, SO_TIMEOUT (the socket read timeout) has been set to a low value. When negotiating Server Dialback, a second
socket connection is used. XMPP session establishment on the first socket connection is paused while the Server Dialback negotiation takes
place. This can easily cause the SO_TIMEOUT to run out. To prevent issues, this implementation allows for reads of the first socket connection
to time out for a certain number of times, before treating this as a terminal exception.
xmppserver/src/test/java/org/jivesoftware/openfire/session/RemoteReceivingServerDummy.java