changeset 2736:fff185e7ab73

mod_cloud_notify: Implement the "stripped stanzas" proposal. See https://mail.jabber.org/pipermail/standards/2017-July/033089.html
author tmolitor <thilo@eightysoft.de>
date Mon, 14 Aug 2017 23:31:05 +0200
parents b5fae17e4403
children f43c77c69a8a
files mod_cloud_notify/mod_cloud_notify.lua
diffstat 1 files changed, 35 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/mod_cloud_notify/mod_cloud_notify.lua	Sat Aug 12 20:45:11 2017 +0200
+++ b/mod_cloud_notify/mod_cloud_notify.lua	Mon Aug 14 23:31:05 2017 +0200
@@ -4,6 +4,7 @@
 --
 -- This file is MIT/X11 licensed.
 
+local t_insert = table.insert;
 local st = require"util.stanza";
 local jid = require"util.jid";
 local dataform = require"util.dataforms".new;
@@ -110,7 +111,7 @@
 		if hashes.sha256(push_identifier, true) == stanza.attr.id then
 			if user_push_services[push_identifier] and user_push_services[push_identifier].jid == from and push_errors[push_identifier] > 0 then
 				push_errors[push_identifier] = 0;
-				module:log("debug", "Push succeeded, error count for identifier '%s' is now at %s", push_identifier, tostring(push_errors[push_identifier]));
+				module:log("debug", "Push succeeded, error count for identifier '%s' is now at %s again", push_identifier, tostring(push_errors[push_identifier]));
 			end
 		end
 	end
@@ -132,6 +133,8 @@
 	local push_jid = enable.attr.jid;
 	-- SHOULD contain a 'node' attribute
 	local push_node = enable.attr.node;
+	-- CAN contain a 'include_payload' attribute
+	local include_payload = enable.attr.include_payload;
 	if not push_jid then
 		origin.log("debug", "Push notification enable request missing the 'jid' field");
 		origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing jid"));
@@ -146,6 +149,7 @@
 	local push_service = {
 		jid = push_jid;
 		node = push_node;
+		include_payload = include_payload;
 		count = 0;
 		options = publish_options and st.preserialize(publish_options);
 	};
@@ -197,6 +201,23 @@
 end
 module:hook("iq-set/self/"..xmlns_push..":disable", push_disable);
 
+-- clone a stanza and strip it
+local function strip_stanza(stanza)
+	local tags = {};
+	local new = { name = stanza.name, attr = { xmlns = stanza.attr.xmlns, type = stanza.attr.type }, tags = tags };
+	for i=1,#stanza do
+		local child = stanza[i];
+		if type(child) == "table" then		-- don't add raw text nodes
+			if child.name then
+				child = strip_stanza(child);
+				t_insert(tags, child);
+			end
+			t_insert(new, child);
+		end
+	end
+	return setmetatable(new, st.stanza_mt);
+end
+
 local push_form = dataform {
 	{ name = "FORM_TYPE"; type = "hidden"; value = "urn:xmpp:push:summary"; };
 	{ name = "message-count"; type = "text-single"; };
@@ -242,6 +263,16 @@
 				form_data["last-message-body"] = stanza:get_child_text("body");
 			end
 			push_publish:add_child(push_form:form(form_data));
+			if stanza and push_info.include_payload == "stripped" then
+				push_publish:tag("payload", { type = "stripped" })
+					:add_child(strip_stanza(stanza));
+				push_publish:up(); -- / payload
+			end
+			if stanza and push_info.include_payload == "full" then
+				push_publish:tag("payload", { type = "full" })
+					:add_child(st.clone(stanza));
+				push_publish:up(); -- / payload
+			end
 			push_publish:up(); -- / notification
 			push_publish:up(); -- / publish
 			push_publish:up(); -- / pubsub
@@ -250,6 +281,7 @@
 			end
 			-- send out push
 			module:log("debug", "Sending push notification for %s@%s to %s (%s)", node, module.host, push_info.jid, tostring(push_info.node));
+			-- module:log("debug", "PUSH STANZA: %s", tostring(push_publish));
 			-- handle push errors for this node
 			if push_errors[push_identifier] == nil then
 				push_errors[push_identifier] = 0;
@@ -274,6 +306,7 @@
 -- publish on offline message
 module:hook("message/offline/handle", function(event)
 	local node, user_push_services = get_push_settings(event.stanza, event.origin);
+	module:log("debug", "Invoking cloud handle_notify_request() for offline stanza");
 	handle_notify_request(event.stanza, node, user_push_services);
 end, 1);
 
@@ -309,7 +342,7 @@
 	-- process unacked stanzas
 	process_smacks_queue(queue, session);
 	-- process future unacked (hibernated) stanzas
-	filters.add_filter(session, "stanzas/out", process_smacks_stanza);
+	filters.add_filter(session, "stanzas/out", process_smacks_stanza, -990);
 end
 
 -- smacks hibernation is ended
@@ -384,21 +417,6 @@
 -- can be used by other modules to ping one or more (or all) push endpoints
 module:hook("cloud-notify-ping", send_ping);
 
--- TODO: this has to be done on first connect not on offline broadcast, else the counter will be incorrect
--- TODO: it seems this is already done, so this could be safely removed, couldn't it?
--- module:hook("message/offline/broadcast", function(event)
--- 	local origin = event.origin;
--- 	local user_push_services = push_store:get(origin.username);
--- 	if not #user_push_services then return end
--- 
--- 	for _, push_info in pairs(user_push_services) do
--- 		if push_info then
--- 			push_info.count = 0;
--- 		end
--- 	end
--- 	push_store:set(origin.username, user_push_services);
--- end, 1);
-
 module:log("info", "Module loaded");
 function module.unload()
 	if module.unhook then