TT#72257 refresh plugins from upstream

* refresh sipwise patches

Change-Id: I4e2b70f315564246ab6f1c5e6a0fd4f4527589f9
(cherry picked from commit 0f25a1ce4c)
changes/71/36071/1
Victor Seva 7 years ago committed by Víctor Seva
parent c6a0d5cbec
commit 4bf834733f

@ -39,10 +39,12 @@ Change-Id: Ib79b6f2f60f71a80030bbd12b2eb893b60ac025d
plugins/mod_mam/mod_mam.lua | 2 ++
1 file changed, 2 insertions(+)
diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua
index 61b4388..f8a2321 100644
--- a/plugins/mod_mam/mod_mam.lua
+++ b/plugins/mod_mam/mod_mam.lua
@@ -393,6 +393,8 @@ module:hook("message/bare", message_hand
module:hook("message/full", message_handler, 0);
@@ -423,6 +423,8 @@ module:hook("message/bare", message_handler, priority);
module:hook("message/full", message_handler, priority);
module:add_feature(xmlns_mam0); -- COMPAT with XEP-0313 v 0.1
+module:add_feature(xmlns_mam1); -- COMPAT with XEP-0313 v 0.5

@ -1,20 +1,21 @@
From 0dd1a7404c27b4a9352f196d52462b7ae6237590 Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Tue, 3 Jan 2017 17:14:49 +0100
Subject: [PATCH] TT#8297 mam: implement archive to DB
Change-Id: If9644ac66fdd257a430cfb7fa185230c77cd783e
Change-Id: I587debda7ed78cc51088bd4a5ba96c878db45e6f
---
plugins/mod_mam/mod_mam.lua | 17 +---
plugins/mod_mam/mod_mam.lua | 16 +---
plugins/mod_mam/sipwise_archive.lib.lua | 165 ++++++++++++++++++++++++++++++++
2 files changed, 166 insertions(+), 16 deletions(-)
2 files changed, 166 insertions(+), 15 deletions(-)
create mode 100644 plugins/mod_mam/sipwise_archive.lib.lua
diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua
index a4aa014..13e0a0b 100644
index f8a2321..faff0dd 100644
--- a/plugins/mod_mam/mod_mam.lua
+++ b/plugins/mod_mam/mod_mam.lua
@@ -40,22 +40,7 @@ if global_default_policy ~= "roster" then
@@ -40,21 +40,7 @@ if global_default_policy ~= "roster" then
global_default_policy = module:get_option_boolean("default_archive_policy", global_default_policy);
end
@ -33,11 +34,10 @@ index a4aa014..13e0a0b 100644
- module:log("info", "Using in-memory fallback archive driver");
- archive = module:require "fallback_archive";
-end
-
+local archive = module:require "sipwise_archive";
local cleanup;
-- Handle prefs.
local use_total = true;
diff --git a/plugins/mod_mam/sipwise_archive.lib.lua b/plugins/mod_mam/sipwise_archive.lib.lua
new file mode 100644
index 0000000..f772ea6
@ -209,6 +209,3 @@ index 0000000..f772ea6
+end
+
+return archive_store;
--
2.11.0

@ -1,4 +1,3 @@
From 9e93fb65101c48a62fec403541216f99e24a121a Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Thu, 19 Jan 2017 16:25:24 +0100
Subject: [PATCH] TT#9303 mod_mam: sipwise_archive.lib fix crash at find()
@ -38,6 +37,3 @@ index f772ea6..087c306 100644
res = engine:select(select_key_query, key);
local out = {};
for row in res do
--
2.11.0

@ -1,4 +1,3 @@
From b17aec94a0563c5fab58ed350c1e32787ae3f7fe Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Thu, 19 Jan 2017 16:38:26 +0100
Subject: [PATCH] TT#9311 mod_mam/sipwise_archive.lib: full username
@ -62,6 +61,3 @@ index 087c306..46166f8 100644
engine.conn:commit();
return true;
end
--
2.11.0

@ -1,4 +1,3 @@
From 9e01a7a10fc1cd8a2d7dc6fe65bdccccf90f8668 Mon Sep 17 00:00:00 2001
From: Victor Seva <vseva@sipwise.com>
Date: Thu, 19 Jan 2017 17:13:12 +0100
Subject: [PATCH] TT#9317 mod_mam: don't store bodyless chat messages
@ -16,12 +15,12 @@ Change-Id: I590b1fb9bd95afdce6a117778052d11d8102f718
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/plugins/mod_mam/mod_mam.lua b/plugins/mod_mam/mod_mam.lua
index 13e0a0b..8d8ef62 100644
index faff0dd..759a5e2 100644
--- a/plugins/mod_mam/mod_mam.lua
+++ b/plugins/mod_mam/mod_mam.lua
@@ -269,19 +269,30 @@ local function message_handler(event, c2s)
return tag;
end);
@@ -285,19 +285,30 @@ local function message_handler(event, c2s)
event.stanza = stanza;
end
- -- We store chat messages or normal messages that have a body
- if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body")) ) then
@ -56,6 +55,3 @@ index 13e0a0b..8d8ef62 100644
end
-- Check with the users preferences
--
2.11.0

@ -1,6 +1,16 @@
From: Sipwise Development Team <support@sipwise.com>
Date: Wed, 11 Dec 2019 11:15:14 +0100
Subject: TT-27653-mod_mam-sipwise_archive.lib-fix-uuid-trailing-garbage
---
plugins/mod_mam/sipwise_archive.lib.lua | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/mod_mam/sipwise_archive.lib.lua b/plugins/mod_mam/sipwise_archive.lib.lua
index e58f593..15acb33 100644
--- a/plugins/mod_mam/sipwise_archive.lib.lua
+++ b/plugins/mod_mam/sipwise_archive.lib.lua
@@ -56,7 +56,7 @@
@@ -56,7 +56,7 @@ local function load_db(query, _params)
res = engine:select(query, unpack(_params));
local out = {};
for row in res do

@ -1,6 +1,16 @@
From: Sipwise Development Team <support@sipwise.com>
Date: Wed, 11 Dec 2019 11:15:14 +0100
Subject: TT-35053-mod_mam-sipwise_archive.lib-fix-retrieving-incoming
---
plugins/mod_mam/sipwise_archive.lib.lua | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/plugins/mod_mam/sipwise_archive.lib.lua b/plugins/mod_mam/sipwise_archive.lib.lua
index 15acb33..533df4f 100644
--- a/plugins/mod_mam/sipwise_archive.lib.lua
+++ b/plugins/mod_mam/sipwise_archive.lib.lua
@@ -36,7 +36,7 @@
@@ -36,7 +36,7 @@ WHERE `key` = UuidToBin(?);
local select_query_base=[[
SELECT UuidFromBin(`key`),`stanza`,`epoch`,`with` FROM `sipwise_mam`
@ -9,7 +19,7 @@
]]
-- Reconnect to DB if necessary
@@ -100,7 +100,7 @@
@@ -100,7 +100,7 @@ function archive_store:find(username, query)
local qstart, qend, qwith = -math.huge, math.huge;
local qlimit, qid;
local db_query = select_query_base;
@ -18,7 +28,7 @@
local i, values = 0;
if query then
@@ -118,7 +118,8 @@
@@ -118,7 +118,8 @@ function archive_store:find(username, query)
end
if qwith then

@ -1,6 +1,16 @@
From: Sipwise Development Team <support@sipwise.com>
Date: Wed, 11 Dec 2019 11:15:14 +0100
Subject: TT-35604-mod_sipwise_pushd.lib-add-silent-push
---
plugins/mod_sipwise_pushd.lua | 58 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 49 insertions(+), 9 deletions(-)
diff --git a/plugins/mod_sipwise_pushd.lua b/plugins/mod_sipwise_pushd.lua
index e29453a..229a2dd 100644
--- a/plugins/mod_sipwise_pushd.lua
+++ b/plugins/mod_sipwise_pushd.lua
@@ -61,6 +61,18 @@
@@ -61,6 +61,18 @@ SELECT vp.attribute, vup.value FROM provisioning.voip_preferences vp
WHERE vp.attribute = 'mobile_push_enable'
AND vd.domain = ?;
]];
@ -19,7 +29,7 @@
local engine;
-- luacheck: ignore request
@@ -74,6 +86,21 @@
@@ -74,6 +86,21 @@ local function process_response(response, code, request)
end
end
@ -41,7 +51,7 @@
local function push_enable(username, domain)
-- Reconnect to DB if necessary
if not engine.conn:ping() then
@@ -303,20 +330,25 @@
@@ -303,20 +330,25 @@ local function handle_offline(event)
msg.data_sender_name = tostring(caller_info.display_name);
return msg;
end
@ -74,7 +84,7 @@
if stanza.attr.type == 'groupchat' then
msg.data_type = 'groupchat'
caller_jid = get_muc_caller(stanza.attr.from);
@@ -325,6 +357,7 @@
@@ -325,6 +357,7 @@ local function handle_offline(event)
caller_info = get_caller_info(caller_jid, caller_defaults) or
caller_defaults;
muc = get_muc_info(stanza, caller_info);
@ -82,7 +92,7 @@
else
msg.data_type = 'message';
caller_jid = format("%s@%s",
@@ -340,13 +373,19 @@
@@ -340,13 +373,19 @@ local function handle_offline(event)
caller_info = get_caller_info(caller_jid, caller_defaults) or
caller_defaults;
muc = get_muc_info(stanza, caller_info);
@ -103,7 +113,7 @@
end
return msg;
end
@@ -445,6 +484,7 @@
@@ -445,6 +484,7 @@ local function handle_muc_offline(event, room_jid)
end
local function handle_msg(event)
@ -111,7 +121,7 @@
local stanza = event.stanza;
local room_jid = stanza.attr.to;
@@ -529,5 +569,5 @@
@@ -529,5 +569,5 @@ function module.load()
sql_config = module:get_option("auth_sql", sql_config);
engine = mod_sql:create_engine(sql_config);
engine:execute("SET NAMES 'utf8' COLLATE 'utf8_bin';");

@ -1,7 +1,13 @@
From: Andreas Granig <agranig@sipwise.com>
Date: Wed Aug 7 22:34:34 2013 +0200
Date: Wed, 7 Aug 2013 22:34:34 +0200
Subject: sipwise custom auth
---
plugins/mod_auth_sql/mod_auth_sql.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugins/mod_auth_sql/mod_auth_sql.lua b/plugins/mod_auth_sql/mod_auth_sql.lua
index 2947a91..8ad8f4a 100644
--- a/plugins/mod_auth_sql/mod_auth_sql.lua
+++ b/plugins/mod_auth_sql/mod_auth_sql.lua
@@ -71,7 +71,7 @@ local function getsql(sql, ...)

@ -113,7 +113,7 @@ local function send_push_iqs(username, host, command_type, jids)
end
for resource, session in pairs(prosody.bare_sessions[bare_jid].sessions) do
local iq_push_stanza = st.iq({ type = "set", to = bare_jid.."/"..resource });
local iq_push_stanza = st.iq({ type = "set", to = bare_jid.."/"..resource, id = "blocking-push" });
iq_push_stanza:add_child(stanza_content);
session.send(iq_push_stanza);
end

@ -1,6 +1,6 @@
---
labels:
- 'Stage-Beta'
- 'Stage-Merged'
summary: Message Carbons
...

@ -15,8 +15,6 @@ local xmlns_carbons_v0 = "urn:xmpp:carbons:0";
local bare_sessions = bare_sessions;
local function adhoc_status(self, data, state)
local result;
local bare_jid = jid_bare(data.from);
local user_sessions = bare_sessions[bare_jid];

@ -1,22 +1,20 @@
---
summary: Client State Indication support
labels:
- 'Stage-Merged'
...
Introduction
============
This module implements [Client State
This module implements [XEP-0352: Client State
Indication](http://xmpp.org/extensions/xep-0352.html), a way for mobile
clients to tell the server that they are sitting in someones pocket and
would rather not get some less urgent things pushed to it.
However this module does not do anything by itself. Deciding what things
are considered "less urgent" is left to other modules.
- [mod\_throttle\_presence](/mod_throttle_presence.html) supresses
presence updates
- [mod\_filter\_chatstates](/mod_filter_chatstates.html) removes chat
states (*Someone is typing...*)
This module has been merged into Prosody 0.11. Please see the
[mod_csi documentation](https://prosody.im/doc/modules/mod_csi) for more
information about how it is used.
Configuration
=============
@ -30,3 +28,7 @@ Compatibility
----- -------
0.9 Works
----- -------
0.10 Works
----- -------
0.11 Works (included)
----- -------

@ -11,6 +11,7 @@ end);
function refire_event(name)
return function (event)
if event.origin.username then
event.origin.state = event.stanza.name;
module:fire_event(name, event);
return true;
end

@ -1,6 +1,6 @@
---
labels:
- 'Stage-Beta'
- 'Stage-Merged'
summary: 'XEP-0313: Message Archive Management'
...

@ -24,9 +24,11 @@ local prefs = module:open_store(archive_store .. "_prefs");
local function get_prefs(user)
local user_sessions = sessions[user];
local user_prefs = user_sessions and user_sessions.archive_prefs
if not user_prefs and user_sessions then
if not user_prefs then
user_prefs = prefs:get(user);
user_sessions.archive_prefs = user_prefs;
if user_sessions then
user_sessions.archive_prefs = user_prefs;
end
end
return user_prefs or { [false] = global_default_policy };
end

@ -56,8 +56,17 @@ if archive.name == "null" or not archive.find then
archive = module:require "fallback_archive";
end
local use_total = true;
local cleanup;
local function schedule_cleanup(username)
if cleanup and not cleanup[username] then
table.insert(cleanup, username);
cleanup[username] = true;
end
end
-- Handle prefs.
local function handle_prefs(event)
local origin, stanza = event.origin, event.stanza;
@ -111,7 +120,9 @@ local function handle_mam_query(event)
local query = stanza.tags[1];
local qid = query.attr.queryid;
if cleanup then cleanup[origin.username] = true; end
origin.mam_requested = true;
schedule_cleanup(origin.username);
-- Search query parameters
local qwith, qstart, qend;
@ -154,7 +165,7 @@ local function handle_mam_query(event)
limit = qmax + 1;
before = before; after = after;
reverse = reverse;
total = true;
total = use_total;
});
if not data then
@ -274,15 +285,19 @@ local function message_handler(event, c2s)
local with = jid_bare(c2s and orig_to or orig_from);
-- Filter out <stanza-id> that claim to be from us
stanza:maptags(function (tag)
if tag.name == "stanza-id" and tag.attr.xmlns == xmlns_st_id then
local by_user, by_host, res = jid_prepped_split(tag.attr.by);
if not res and by_host == module.host and by_user == store_user then
return nil;
if stanza:get_child("stanza-id", xmlns_st_id) then
stanza = st.clone(stanza);
stanza:maptags(function (tag)
if tag.name == "stanza-id" and tag.attr.xmlns == xmlns_st_id then
local by_user, by_host, res = jid_prepped_split(tag.attr.by);
if not res and by_host == module.host and by_user == store_user then
return nil;
end
end
end
return tag;
end);
return tag;
end);
event.stanza = stanza;
end
-- We store chat messages or normal messages that have a body
if not(orig_type == "chat" or (orig_type == "normal" and stanza:get_child("body")) ) then
@ -306,9 +321,11 @@ local function message_handler(event, c2s)
-- And stash it
local ok = archive:append(store_user, nil, stanza, time_now(), with);
if ok then
local clone_for_other_handlers = st.clone(stanza);
local id = ok;
stanza:tag("stanza-id", { xmlns = xmlns_st_id, by = store_user.."@"..host, id = id }):up();
if cleanup then cleanup[store_user] = true; end
clone_for_other_handlers:tag("stanza-id", { xmlns = xmlns_st_id, by = store_user.."@"..host, id = id }):up();
event.stanza = clone_for_other_handlers;
schedule_cleanup(store_user);
module:fire_event("archive-message-added", { origin = origin, stanza = stanza, for_user = store_user, id = id });
end
else
@ -322,6 +339,7 @@ end
local function strip_stanza_id(event)
local strip_by = jid_bare(event.origin.full_jid);
event.stanza = st.clone(event.stanza);
event.stanza:maptags(function(tag)
if not ( tag.attr.xmlns == xmlns_st_id and tag.attr.by == strip_by ) then
return tag;
@ -361,13 +379,13 @@ if cleanup_after ~= "never" then
pcall(function ()
-- If this works, then we schedule cleanup for all known users on startup
for user in um.users(module.host) do
cleanup[user] = true;
schedule_cleanup(user);
end
end);
-- At odd intervals, delete old messages for one user
module:add_timer(math.random(10, 60), function()
local user = next(cleanup);
local user = table.remove(cleanup, 1);
if user then
module:log("debug", "Removing old messages for user %q", user);
local ok, err = archive:delete(user, { ["end"] = os.time() - cleanup_after; })
@ -383,14 +401,26 @@ if cleanup_after ~= "never" then
end
return math.random(cleanup_interval, cleanup_interval * 2);
end);
else
-- Don't ask the backend to count the potentially unbounded number of items,
-- it'll get slow.
use_total = false;
end
-- Stanzas sent by local clients
module:hook("pre-message/bare", c2s_message_handler, 0);
module:hook("pre-message/full", c2s_message_handler, 0);
local priority = 0.075
assert(priority < 0.1, "priority must be after mod_firewall");
assert(priority > 0.05, "priority must be before mod_carbons");
assert(priority > 0.01, "priority must be before strip_stanza_id");
module:hook("pre-message/bare", c2s_message_handler, priority);
module:hook("pre-message/full", c2s_message_handler, priority);
-- Stanszas to local clients
module:hook("message/bare", message_handler, 0);
module:hook("message/full", message_handler, 0);
priority = 0.075
assert(priority > 0, "priority must be before mod_message");
assert(priority < 0.1, "priority must be after mod_firewall");
assert(priority > 0.05, "priority must be before mod_carbons");
module:hook("message/bare", message_handler, priority);
module:hook("message/full", message_handler, priority);
module:add_feature(xmlns_mam0); -- COMPAT with XEP-0313 v 0.1

@ -5,7 +5,7 @@
-- Copyright (C) 2012-2015 Kim Alvefur
-- Copyright (C) 2012 Thijs Alkemade
-- Copyright (C) 2014 Florian Zeitz
-- Copyright (C) 2016-2017 Thilo Molitor
-- Copyright (C) 2016-2019 Thilo Molitor
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
@ -15,9 +15,11 @@ local st = require "util.stanza";
local dep = require "util.dependencies";
local cache = dep.softreq("util.cache"); -- only available in prosody 0.10+
local uuid_generate = require "util.uuid".generate;
local jid = require "util.jid";
local t_insert, t_remove = table.insert, table.remove;
local math_min = math.min;
local math_max = math.max;
local os_time = os.time;
local tonumber, tostring = tonumber, tostring;
local add_filter = require "util.filters".add_filter;
@ -42,6 +44,9 @@ local max_old_sessions = module:get_option_number("smacks_max_old_sessions", 10)
local core_process_stanza = prosody.core_process_stanza;
local sessionmanager = require"core.sessionmanager";
assert(max_hibernated_sessions > 0, "smacks_max_hibernated_sessions must be greater than 0");
assert(max_old_sessions > 0, "smacks_old_sessions must be greater than 0");
local c2s_sessions = module:shared("/*/c2s/sessions");
local function init_session_cache(max_entries, evict_callback)
@ -61,7 +66,7 @@ local function init_session_cache(max_entries, evict_callback)
end;
};
end
-- use per user limited cache for prosody >= 0.10
local stores = {};
return {
@ -99,17 +104,19 @@ end);
local function stoppable_timer(delay, callback)
local stopped = false;
local timer = module:add_timer(delay, function (t)
if stopped then return; end
return callback(t);
end);
if timer and timer.stop then return timer; end -- new prosody api includes stop() function
return {
stop = function () stopped = true end;
module:add_timer(delay, function (t)
if stopped then return; end
return callback(t);
end);
timer;
};
end
local function delayed_ack_function(session)
-- fire event only if configured to do so and our session is not hibernated or destroyed
-- fire event only if configured to do so and our session is not already hibernated or destroyed
if delayed_ack_timeout > 0 and session.awaiting_ack
and not session.hibernating and not session.destroyed then
session.log("debug", "Firing event 'smacks-ack-delayed', queue = %d",
@ -150,18 +157,28 @@ module:hook("s2s-stream-features",
end
end);
local function request_ack_if_needed(session, force)
local function request_ack_if_needed(session, force, reason)
local queue = session.outgoing_stanza_queue;
if session.awaiting_ack == nil then
if (#queue > max_unacked_stanzas and session.last_queue_count ~= #queue) or force then
session.log("debug", "Queuing <r> (in a moment)");
local expected_h = session.last_acknowledged_stanza + #queue;
-- session.log("debug", "*** SMACKS(1) ***: awaiting_ack=%s, hibernating=%s", tostring(session.awaiting_ack), tostring(session.hibernating));
if session.awaiting_ack == nil and not session.hibernating then
-- this check of last_requested_h prevents ack-loops if missbehaving clients report wrong
-- stanza counts. it is set when an <r> is really sent (e.g. inside timer), preventing any
-- further requests until a higher h-value would be expected.
-- session.log("debug", "*** SMACKS(2) ***: #queue=%s, max_unacked_stanzas=%s, expected_h=%s, last_requested_h=%s", tostring(#queue), tostring(max_unacked_stanzas), tostring(expected_h), tostring(session.last_requested_h));
if (#queue > max_unacked_stanzas and expected_h ~= session.last_requested_h) or force then
session.log("debug", "Queuing <r> (in a moment) from %s - #queue=%d", reason, #queue);
session.awaiting_ack = false;
session.awaiting_ack_timer = stoppable_timer(1e-06, function ()
if not session.awaiting_ack then
session.log("debug", "Sending <r> (inside timer, before send)");
-- session.log("debug", "*** SMACKS(3) ***: awaiting_ack=%s, hibernating=%s", tostring(session.awaiting_ack), tostring(session.hibernating));
-- only request ack if needed and our session is not already hibernated or destroyed
if not session.awaiting_ack and not session.hibernating and not session.destroyed then
session.log("debug", "Sending <r> (inside timer, before send) from %s - #queue=%d", reason, #queue);
(session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks }))
session.log("debug", "Sending <r> (inside timer, after send)");
session.awaiting_ack = true;
-- expected_h could be lower than this expression e.g. more stanzas added to the queue meanwhile)
session.last_requested_h = session.last_acknowledged_stanza + #queue;
session.log("debug", "Sending <r> (inside timer, after send) from %s - #queue=%d", reason, #queue);
if not session.delayed_ack_timer then
session.delayed_ack_timer = stoppable_timer(delayed_ack_timeout, function()
delayed_ack_function(session);
@ -171,7 +188,7 @@ local function request_ack_if_needed(session, force)
end);
end
end
-- Trigger "smacks-ack-delayed"-event if we added new (ackable) stanzas to the outgoing queue
-- and there isn't already a timer for this event running.
-- If we wouldn't do this, stanzas added to the queue after the first "smacks-ack-delayed"-event
@ -180,8 +197,6 @@ local function request_ack_if_needed(session, force)
session.log("debug", "Calling delayed_ack_function directly (still waiting for ack)");
delayed_ack_function(session);
end
session.last_queue_count = #queue;
end
local function outgoing_stanza_filter(stanza, session)
@ -192,16 +207,20 @@ local function outgoing_stanza_filter(stanza, session)
cached_stanza._cached = true;
if cached_stanza and cached_stanza.name ~= "iq" and cached_stanza:get_child("delay", xmlns_delay) == nil then
cached_stanza = cached_stanza:tag("delay", { xmlns = xmlns_delay, from = session.host, stamp = datetime.datetime()});
cached_stanza = cached_stanza:tag("delay", {
xmlns = xmlns_delay,
from = jid.bare(session.full_jid or session.host),
stamp = datetime.datetime()
});
end
queue[#queue+1] = cached_stanza;
session.log("debug", "#queue = %d", #queue);
if session.hibernating then
session.log("debug", "hibernating, stanza queued");
module:fire_event("smacks-hibernation-stanza-queued", {origin = session, queue = queue, stanza = cached_stanza});
return nil;
end
request_ack_if_needed(session, false);
request_ack_if_needed(session, false, "outgoing_stanza_filter");
end
return stanza;
end
@ -231,7 +250,7 @@ local function wrap_session_out(session, resume)
end
-- send out last ack as per revision 1.5.2 of XEP-0198
if session.smacks and session.conn then
(session.sends2s or session.send)(st.stanza("a", { xmlns = session.smacks, h = tostring(session.handled_stanza_count) }));
(session.sends2s or session.send)(st.stanza("a", { xmlns = session.smacks, h = string.format("%d", session.handled_stanza_count) }));
end
return session_close(...);
end
@ -273,7 +292,7 @@ function handle_enable(session, stanza, xmlns_sm)
session_registry.set(session.username, resume_token, session);
session.resumption_token = resume_token;
end
(session.sends2s or session.send)(st.stanza("enabled", { xmlns = xmlns_sm, id = resume_token, resume = resume }));
(session.sends2s or session.send)(st.stanza("enabled", { xmlns = xmlns_sm, id = resume_token, resume = resume, max = tostring(resume_timeout) }));
return true;
end
module:hook_stanza(xmlns_sm2, "enable", function (session, stanza) return handle_enable(session, stanza, xmlns_sm2); end, 100);
@ -317,7 +336,12 @@ function handle_r(origin, stanza, xmlns_sm)
end
module:log("debug", "Received ack request, acking for %d", origin.handled_stanza_count);
-- Reply with <a>
(origin.sends2s or origin.send)(st.stanza("a", { xmlns = xmlns_sm, h = tostring(origin.handled_stanza_count) }));
(origin.sends2s or origin.send)(st.stanza("a", { xmlns = xmlns_sm, h = string.format("%d", origin.handled_stanza_count) }));
-- piggyback our own ack request if needed (see request_ack_if_needed() for explanation of last_requested_h)
local expected_h = origin.last_acknowledged_stanza + #origin.outgoing_stanza_queue;
if #origin.outgoing_stanza_queue > 0 and expected_h ~= origin.last_requested_h then
request_ack_if_needed(origin, true, "piggybacked by handle_r");
end
return true;
end
module:hook_stanza(xmlns_sm2, "r", function (origin, stanza) return handle_r(origin, stanza, xmlns_sm2); end);
@ -338,6 +362,7 @@ function handle_a(origin, stanza)
local h = tonumber(stanza.attr.h);
if not h then
origin:close{ condition = "invalid-xml"; text = "Missing or invalid 'h' attribute"; };
return;
end
local handled_stanza_count = h-origin.last_acknowledged_stanza;
local queue = origin.outgoing_stanza_queue;
@ -349,12 +374,15 @@ function handle_a(origin, stanza)
origin.log("debug", "Q item %d: %s", i, tostring(queue[i]));
end
end
for i=1,math_min(handled_stanza_count,#queue) do
t_remove(origin.outgoing_stanza_queue, 1);
local handled_stanza = t_remove(origin.outgoing_stanza_queue, 1);
module:fire_event("delivery/success", { session = origin, stanza = handled_stanza });
end
origin.log("debug", "#queue = %d", #queue);
origin.last_acknowledged_stanza = origin.last_acknowledged_stanza + handled_stanza_count;
request_ack_if_needed(origin, false)
request_ack_if_needed(origin, false, "handle_a")
return true;
end
module:hook_stanza(xmlns_sm2, "a", handle_a);
@ -371,12 +399,14 @@ function handle_unacked_stanzas(session)
if #queue > 0 then
session.outgoing_stanza_queue = {};
for i=1,#queue do
local reply = st.reply(queue[i]);
if reply.attr.to ~= session.full_jid then
reply.attr.type = "error";
reply:tag("error", error_attr)
:tag("recipient-unavailable", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"});
core_process_stanza(session, reply);
if not module:fire_event("delivery/failure", { session = session, stanza = queue[i] }) then
local reply = st.reply(queue[i]);
if reply.attr.to ~= session.full_jid then
reply.attr.type = "error";
reply:tag("error", error_attr)
:tag("recipient-unavailable", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"});
core_process_stanza(session, reply);
end
end
end
end
@ -388,7 +418,7 @@ module:hook("pre-resource-unbind", function (event)
if not session.resumption_token then
local queue = session.outgoing_stanza_queue;
if #queue > 0 then
session.log("warn", "Destroying session with %d unacked stanzas", #queue);
session.log("debug", "Destroying session with %d unacked stanzas", #queue);
handle_unacked_stanzas(session);
end
else
@ -410,6 +440,19 @@ module:hook("pre-resource-unbind", function (event)
-- Check the hibernate time still matches what we think it is,
-- otherwise the session resumed and re-hibernated.
and session.hibernating == hibernate_time then
-- wait longer if the timeout isn't reached because push was enabled for this session
-- session.first_hibernated_push is the starting point for hibernation timeouts of those push enabled clients
-- wait for an additional resume_timeout seconds if no push occured since hibernation at all
local current_time = os_time();
local timeout_start = math_max(session.hibernating, session.first_hibernated_push or session.hibernating);
if session.push_identifier ~= nil and not session.first_hibernated_push then
session.log("debug", "No push happened since hibernation started, hibernating session for up to %d extra seconds", resume_timeout);
return resume_timeout;
end
if current_time-timeout_start < resume_timeout and session.push_identifier ~= nil then
session.log("debug", "A push happened since hibernation started, hibernating session for up to %d extra seconds", current_time-timeout_start);
return current_time-timeout_start; -- time left to wait
end
session.log("debug", "Destroying session for hibernating too long");
session_registry.set(session.username, session.resumption_token, nil);
-- save only actual h value and username/host (for security)
@ -448,6 +491,10 @@ end
module:hook("s2sout-destroyed", handle_s2s_destroyed);
module:hook("s2sin-destroyed", handle_s2s_destroyed);
local function get_session_id(session)
return session.id or (tostring(session):match("[a-f0-9]+$"));
end
function handle_resume(session, stanza, xmlns_sm)
if session.full_jid then
session.log("warn", "Tried to resume after resource binding");
@ -465,7 +512,7 @@ function handle_resume(session, stanza, xmlns_sm)
if old_session and session.username == old_session.username
and session.host == old_session.host
and old_session.h then
session.send(st.stanza("failed", { xmlns = xmlns_sm, h = tostring(old_session.h) })
session.send(st.stanza("failed", { xmlns = xmlns_sm, h = string.format("%d", old_session.h) })
:tag("item-not-found", { xmlns = xmlns_errors })
);
else
@ -475,10 +522,11 @@ function handle_resume(session, stanza, xmlns_sm)
end;
elseif session.username == original_session.username
and session.host == original_session.host then
session.log("debug", "mod_smacks resuming existing session...");
session.log("debug", "mod_smacks resuming existing session %s...", get_session_id(original_session));
original_session.log("debug", "mod_smacks session resumed from %s...", get_session_id(session));
-- TODO: All this should move to sessionmanager (e.g. session:replace(new_session))
if original_session.conn then
session.log("debug", "mod_smacks closing an old connection for this session");
original_session.log("debug", "mod_smacks closing an old connection for this session");
local conn = original_session.conn;
c2s_sessions[conn] = nil;
conn:close();
@ -493,6 +541,8 @@ function handle_resume(session, stanza, xmlns_sm)
original_session.stream = session.stream;
original_session.secure = session.secure;
original_session.hibernating = nil;
session.log = original_session.log;
session.type = original_session.type;
wrap_session(original_session, true);
-- Inform xmppstream of the new session (passed to its callbacks)
original_session.stream:set_session(original_session);
@ -500,7 +550,7 @@ function handle_resume(session, stanza, xmlns_sm)
c2s_sessions[session.conn] = original_session;
original_session.send(st.stanza("resumed", { xmlns = xmlns_sm,
h = original_session.handled_stanza_count, previd = id }));
h = string.format("%d", original_session.handled_stanza_count), previd = id }));
-- Fake an <a> with the h of the <resume/> from the client
original_session:dispatch_stanza(st.stanza("a", { xmlns = xmlns_sm,
@ -509,7 +559,6 @@ function handle_resume(session, stanza, xmlns_sm)
-- Ok, we need to re-send any stanzas that the client didn't see
-- ...they are what is now left in the outgoing stanza queue
local queue = original_session.outgoing_stanza_queue;
module:fire_event("smacks-hibernation-end", {origin = session, resumed = original_session, queue = queue});
original_session.log("debug", "#queue = %d", #queue);
for i=1,#queue do
original_session.send(queue[i]);
@ -519,7 +568,8 @@ function handle_resume(session, stanza, xmlns_sm)
session.log("warn", "Tried to send stanza on old session migrated by smacks resume (maybe there is a bug?): %s", tostring(stanza));
return false;
end
request_ack_if_needed(original_session, true);
module:fire_event("smacks-hibernation-end", {origin = session, resumed = original_session, queue = queue});
request_ack_if_needed(original_session, true, "handle_resume");
else
module:log("warn", "Client %s@%s[%s] tried to resume stream for %s@%s[%s]",
session.username or "?", session.host or "?", session.type,
@ -546,7 +596,6 @@ local function handle_read_timeout(event)
return false; -- Kick the session
end
session.log("debug", "Sending <r> (read timeout)");
session.awaiting_ack = false;
(session.sends2s or session.send)(st.stanza("r", { xmlns = session.smacks }));
session.awaiting_ack = true;
if not session.delayed_ack_timer then

@ -1 +1 @@
9b43b7fc3558
0ae28bf0c546

Loading…
Cancel
Save