+ function session.send() return false; end
+
+ local reason = (reason and (reason.name or reason.text or reason.condition)) or reason;
+ session.log("debug", "c2s stream for %s closed: %s", session.full_jid or ("<"..session.ip..">"), reason or "session closed");
+
+ -- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote
+ local conn = session.conn;
+ if reason == nil and not session.notopen and session.type == "c2s" then
+ -- Grace time to process data from authenticated cleanly-closed stream
+ add_task(stream_close_timeout, function ()
+ if not session.destroyed then
+ session.log("warn", "Failed to receive a stream close response, closing connection anyway...");
+ sm_destroy_session(session, reason);
+ conn:close();
+ end
+ end);
+ else
+ sm_destroy_session(session, reason);
+ conn:close();
+ end
+ end
+end
+
+local function session_open_stream(session)
+ local attr = {
+ ["xmlns:stream"] = 'http://etherx.jabber.org/streams',
+ xmlns = stream_callbacks.default_ns,
+ version = "1.0",
+ ["xml:lang"] = 'en',
+ id = session.streamid or "",
+ from = session.host
+ };
+ session.send("<?xml version='1.0'?>");
+ session.send(st.stanza("stream:stream", attr):top_tag());
+end
+
+module:hook_global("user-deleted", function(event)
+ local username, host = event.username, event.host;
+ local user = hosts[host].sessions[username];
+ if user and user.sessions then
+ for jid, session in pairs(user.sessions) do
+ session:close{ condition = "not-authorized", text = "Account deleted" };
+ end