mod_s2s, mod_saslauth, mod_compression: Refactor to have common code for opening...
[prosody.git] / plugins / mod_s2s / mod_s2s.lua
index ad628a9b17a3fe711f819bdd3fe5b38af3514b75..8d99b855d47f781459d0435cf480efa5a0282b1e 100644 (file)
@@ -136,6 +136,7 @@ end
 
 --- Helper to check that a session peer's certificate is valid
 local function check_cert_status(session)
+       local host = session.direction == "incoming" and session.from_host or session.to_host
        local conn = session.conn:socket()
        local cert
        if conn.getpeercertificate then
@@ -155,8 +156,6 @@ local function check_cert_status(session)
                        (session.log or log)("debug", "certificate chain validation result: valid");
                        session.cert_chain_status = "valid";
 
-                       local host = session.direction == "incoming" and session.from_host or session.to_host
-
                        -- We'll go ahead and verify the asserted identity if the
                        -- connecting server specified one.
                        if host then
@@ -168,6 +167,7 @@ local function check_cert_status(session)
                        end
                end
        end
+       module:fire_event("s2s-check-certificate", { host = host, session = session, cert = cert });
 end
 
 --- XMPP stream event handlers
@@ -248,9 +248,7 @@ function stream_callbacks.streamopened(session, attr)
 
                if session.secure and not session.cert_chain_status then check_cert_status(session); end
 
-               send("<?xml version='1.0'?>");
-               send(st.stanza("stream:stream", { xmlns='jabber:server', ["xmlns:db"]='jabber:server:dialback',
-                               ["xmlns:stream"]='http://etherx.jabber.org/streams', id=session.streamid, from=to, to=from, version=(session.version > 0 and "1.0" or nil) }):top_tag());
+               session:open_stream()
                if session.version >= 1.0 then
                        local features = st.stanza("stream:features");
                        
@@ -287,7 +285,7 @@ function stream_callbacks.streamopened(session, attr)
                -- If server is pre-1.0, don't wait for features, just do dialback
                if session.version < 1.0 then
                        if not session.dialback_verifying then
-                               hosts[session.from_host].events.fire_event("s2s-authenticate-legacy", { origin = session });
+                               hosts[session.from_host].events.fire_event("s2sout-authenticate-legacy", { origin = session });
                        else
                                s2s_mark_connected(session);
                        end
@@ -347,8 +345,7 @@ local function session_close(session, reason, remote_reason)
        local log = session.log or log;
        if session.conn then
                if session.notopen then
-                       session.sends2s("<?xml version='1.0'?>");
-                       session.sends2s(st.stanza("stream:stream", default_stream_attr):top_tag());
+                       session:open_stream()
                end
                if reason then -- nil == no err, initiated by us, false == initiated by remote
                        if type(reason) == "string" then -- assume stream error
@@ -395,6 +392,27 @@ local function session_close(session, reason, remote_reason)
        end
 end
 
+function session_open_stream(session, from, to)
+       local from = from or session.from_host;
+       local to = to or session.to_host;
+       local attr = {
+               ["xmlns:stream"] = 'http://etherx.jabber.org/streams',
+               xmlns = 'jabber:server',
+               version = session.version and (session.version > 0 and "1.0" or nil),
+               ["xml:lang"] = 'en',
+               id = session.streamid,
+               from = from, to = to,
+       }
+       local local_host = session.direction == "outgoing" and from or to;
+       if not local_host or hosts[local_host].modules.dialback then
+               attr["xmlns:db"] = 'jabber:server:dialback';
+       end
+
+       session.sends2s("<?xml version='1.0'?>");
+       session.sends2s(st.stanza("stream:stream", attr):top_tag());
+       return true;
+end
+
 -- Session initialization logic shared by incoming and outgoing
 local function initialize_session(session)
        local stream = new_xmpp_stream(session, stream_callbacks);
@@ -406,6 +424,8 @@ local function initialize_session(session)
                session.notopen = true;
                session.stream:reset();
        end
+
+       session.open_stream = session_open_stream;
        
        local filter = session.filter;
        function session.data(data)
@@ -429,6 +449,8 @@ local function initialize_session(session)
        add_task(connect_timeout, function ()
                if session.type == "s2sin" or session.type == "s2sout" then
                        return; -- Ok, we're connected
+               elseif session.type == "s2s_destroyed" then
+                       return; -- Session already destroyed
                end
                -- Not connected, need to close session and clean up
                (session.log or log)("debug", "Destroying incomplete session %s->%s due to inactivity",