diff options
author | Matthew Wild <mwild1@gmail.com> | 2022-08-29 15:45:52 +0100 |
---|---|---|
committer | Matthew Wild <mwild1@gmail.com> | 2022-08-29 15:45:52 +0100 |
commit | 79ac7f6b74e25eb62f4590cb76f424507954085c (patch) | |
tree | 5be4a5bbd55c70059907083123fd6aa389d1171d /plugins | |
parent | b02ab508d51481e19991053645ed48dcb819c4d9 (diff) | |
download | prosody-79ac7f6b74e25eb62f4590cb76f424507954085c.tar.gz prosody-79ac7f6b74e25eb62f4590cb76f424507954085c.zip |
mod_smacks: Split enable handling to stages, to allow easier SASL2 integration
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/mod_smacks.lua | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/plugins/mod_smacks.lua b/plugins/mod_smacks.lua index 7aa8687a..2ffbc45a 100644 --- a/plugins/mod_smacks.lua +++ b/plugins/mod_smacks.lua @@ -107,7 +107,11 @@ local ack_errors = require"util.error".init("mod_smacks", xmlns_sm3, { overflow = { condition = "resource-constraint", text = "Too many unacked stanzas remaining, session can't be resumed" } }); -local resume_errors = require "util.error".init("mod_smacks", xmlns_sm3, { +local enable_errors = require "util.error".init("mod_smacks", xmlns_sm3, { + already_enabled = { condition = "unexpected-request", text = "Stream management is already enabled" }; + bind_required = { condition = "unexpected-request", text = "Client must bind a resource before enabling stream management" }; + unavailable = { condition = "service-unavailable", text = "Stream management is not available for this stream" }; + -- Resumption expired = { condition = "item-not-found", text = "Session expired, and cannot be resumed" }; already_bound = { condition = "unexpected-request", text = "Cannot resume another session after a resource is bound" }; unknown_session = { condition = "item-not-found", text = "Unknown session" }; @@ -127,18 +131,18 @@ local function ack_delayed(session, stanza) end local function can_do_smacks(session, advertise_only) - if session.smacks then return false, "unexpected-request", "Stream management is already enabled"; end + if session.smacks then return false, enable_errors.new("already_enabled"); end local session_type = session.type; if session.username then if not(advertise_only) and not(session.resource) then -- Fail unless we're only advertising sm - return false, "unexpected-request", "Client must bind a resource before enabling stream management"; + return false, enable_errors.new("bind_required"); end return true; elseif s2s_smacks and (session_type == "s2sin" or session_type == "s2sout") then return true; end - return false, "service-unavailable", "Stream management is not available for this stream"; + return false, enable_errors.new("unavailable"); end module:hook("stream-features", @@ -294,12 +298,11 @@ local function wrap_session(session, resume) return session; end -function handle_enable(session, stanza, xmlns_sm) - local ok, err, err_text = can_do_smacks(session); +function do_enable(session, stanza) + local ok, err = can_do_smacks(session); if not ok then - session.log("warn", "Failed to enable smacks: %s", err_text); -- TODO: XEP doesn't say we can send error text, should it? - (session.sends2s or session.send)(st.stanza("failed", { xmlns = xmlns_sm }):tag(err, { xmlns = xmlns_errors})); - return true; + session.log("warn", "Failed to enable smacks: %s", err.text); -- TODO: XEP doesn't say we can send error text, should it? + return nil, err; end if session.username then @@ -320,20 +323,44 @@ function handle_enable(session, stanza, xmlns_sm) end end - session.log("debug", "Enabling stream management"); - session.smacks = xmlns_sm; - - wrap_session(session, false); - - local resume_max; local resume_token; local resume = stanza.attr.resume; if resume == "true" or resume == "1" then resume_token = new_id(); - track_session(session, resume_token); - resume_max = tostring(resume_timeout); end - (session.sends2s or session.send)(st.stanza("enabled", { xmlns = xmlns_sm, id = resume_token, resume = resume, max = resume_max })); + + return { + id = resume_token; + resume_max = resume_token and tostring(resume_timeout) or nil; + session = session; + finish = function () + session.log("debug", "Enabling stream management"); + + track_session(session, resume_token); + wrap_session(session, false); + + end; + }; +end + +function handle_enable(session, stanza, xmlns_sm) + local enabled, err = do_enable(session, stanza); + if not enabled then + (session.sends2s or session.send)(st.stanza("failed", { xmlns = xmlns_sm }):add_error(err)); + return true; + end + + session.smacks = xmlns_sm; + + (session.sends2s or session.send)(st.stanza("enabled", { + xmlns = xmlns_sm; + id = enabled.id; + resume = enabled.id and "1" or nil; + max = enabled.resume_max; + })); + + enabled.finish(); + return true; end module:hook_tag(xmlns_sm2, "enable", function (session, stanza) return handle_enable(session, stanza, xmlns_sm2); end, 100); @@ -536,7 +563,7 @@ module:hook("s2sin-destroyed", handle_s2s_destroyed); function do_resume(session, stanza) if session.full_jid then session.log("warn", "Tried to resume after resource binding"); - return nil, resume_errors.new("already_bound"); + return nil, enable_errors.new("already_bound"); end local id = stanza.attr.previd; @@ -547,10 +574,10 @@ function do_resume(session, stanza) session.log("debug", "Tried to resume old expired session with id %s", id); clear_old_session(session, id); resumption_expired(1); - return nil, resume_errors.new("expired", { h = old_session.h }); + return nil, enable_errors.new("expired", { h = old_session.h }); end session.log("debug", "Tried to resume non-existent session with id %s", id); - return nil, resume_errors.new("unknown_session"); + return nil, enable_errors.new("unknown_session"); end if original_session.hibernating_watchdog then |