mirror of
https://github.com/bjc/prosody.git
synced 2025-04-04 13:47:41 +03:00
mod_smacks: Split enable handling to stages, to allow easier SASL2 integration
This commit is contained in:
parent
b02ab508d5
commit
79ac7f6b74
1 changed files with 48 additions and 21 deletions
|
@ -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" }
|
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" };
|
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" };
|
already_bound = { condition = "unexpected-request", text = "Cannot resume another session after a resource is bound" };
|
||||||
unknown_session = { condition = "item-not-found", text = "Unknown session" };
|
unknown_session = { condition = "item-not-found", text = "Unknown session" };
|
||||||
|
@ -127,18 +131,18 @@ local function ack_delayed(session, stanza)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function can_do_smacks(session, advertise_only)
|
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;
|
local session_type = session.type;
|
||||||
if session.username then
|
if session.username then
|
||||||
if not(advertise_only) and not(session.resource) then -- Fail unless we're only advertising sm
|
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
|
end
|
||||||
return true;
|
return true;
|
||||||
elseif s2s_smacks and (session_type == "s2sin" or session_type == "s2sout") then
|
elseif s2s_smacks and (session_type == "s2sin" or session_type == "s2sout") then
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
return false, "service-unavailable", "Stream management is not available for this stream";
|
return false, enable_errors.new("unavailable");
|
||||||
end
|
end
|
||||||
|
|
||||||
module:hook("stream-features",
|
module:hook("stream-features",
|
||||||
|
@ -294,12 +298,11 @@ local function wrap_session(session, resume)
|
||||||
return session;
|
return session;
|
||||||
end
|
end
|
||||||
|
|
||||||
function handle_enable(session, stanza, xmlns_sm)
|
function do_enable(session, stanza)
|
||||||
local ok, err, err_text = can_do_smacks(session);
|
local ok, err = can_do_smacks(session);
|
||||||
if not ok then
|
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.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 nil, err;
|
||||||
return true;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if session.username then
|
if session.username then
|
||||||
|
@ -320,20 +323,44 @@ function handle_enable(session, stanza, xmlns_sm)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
session.log("debug", "Enabling stream management");
|
|
||||||
session.smacks = xmlns_sm;
|
|
||||||
|
|
||||||
wrap_session(session, false);
|
|
||||||
|
|
||||||
local resume_max;
|
|
||||||
local resume_token;
|
local resume_token;
|
||||||
local resume = stanza.attr.resume;
|
local resume = stanza.attr.resume;
|
||||||
if resume == "true" or resume == "1" then
|
if resume == "true" or resume == "1" then
|
||||||
resume_token = new_id();
|
resume_token = new_id();
|
||||||
track_session(session, resume_token);
|
|
||||||
resume_max = tostring(resume_timeout);
|
|
||||||
end
|
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;
|
return true;
|
||||||
end
|
end
|
||||||
module:hook_tag(xmlns_sm2, "enable", function (session, stanza) return handle_enable(session, stanza, xmlns_sm2); end, 100);
|
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)
|
function do_resume(session, stanza)
|
||||||
if session.full_jid then
|
if session.full_jid then
|
||||||
session.log("warn", "Tried to resume after resource binding");
|
session.log("warn", "Tried to resume after resource binding");
|
||||||
return nil, resume_errors.new("already_bound");
|
return nil, enable_errors.new("already_bound");
|
||||||
end
|
end
|
||||||
|
|
||||||
local id = stanza.attr.previd;
|
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);
|
session.log("debug", "Tried to resume old expired session with id %s", id);
|
||||||
clear_old_session(session, id);
|
clear_old_session(session, id);
|
||||||
resumption_expired(1);
|
resumption_expired(1);
|
||||||
return nil, resume_errors.new("expired", { h = old_session.h });
|
return nil, enable_errors.new("expired", { h = old_session.h });
|
||||||
end
|
end
|
||||||
session.log("debug", "Tried to resume non-existent session with id %s", id);
|
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
|
end
|
||||||
|
|
||||||
if original_session.hibernating_watchdog then
|
if original_session.hibernating_watchdog then
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue