diff mod_carbons/mod_carbons.lua @ 480:0cef5be669de

mod_carbons: Consolidate message handlers
author Kim Alvefur <zash@zash.se>
date Sat, 26 Nov 2011 09:06:04 +0100
parents 7d6a05f94941
children 59e80326f2b3
line wrap: on
line diff
--- a/mod_carbons/mod_carbons.lua	Fri Nov 25 11:03:04 2011 +0100
+++ b/mod_carbons/mod_carbons.lua	Sat Nov 26 09:06:04 2011 +0100
@@ -27,104 +27,78 @@
 	end
 end);
 
-function c2s_message_handler(event)
+local function message_handler(event, c2s)
 	local origin, stanza = event.origin, event.stanza;
 	local orig_type = stanza.attr.type;
 	local orig_to = stanza.attr.to;
+	local orig_from = stanza.attr.from;
 	
 	if not (orig_type == nil
 			or orig_type == "normal"
 			or orig_type == "chat") then
-		return
+		return -- No carbons for messages of type error or headline
 	end
 
 	local bare_jid, user_sessions;
-	if origin.type == "s2s" then
-		bare_jid = jid_bare(stanza.attr.from);
-		user_sessions = host_sessions[jid_split(orig_to)];
-	else
+	local no_carbon_to = {};
+	module:log("debug", "origin (%s) type: %s", tostring(origin), origin.type)
+	if c2s then -- Stanza sent by a local client
 		bare_jid = (origin.username.."@"..origin.host)
 		user_sessions = host_sessions[origin.username];
+	else -- Stanza about to be delivered to a local client
+		local username, hostname, resource = jid_split(orig_to);
+		bare_jid = jid_bare(orig_to);
+		user_sessions = host_sessions[username];
+		if resource then
+			no_carbon_to[resource] = true;
+		else
+			local top_resources = user_sessions.top_resources;
+			for _, session in ipairs(top_resources) do
+				no_carbon_to[session.resource] = true;
+			end
+		end
 	end
 
-	if not stanza:get_child("private", xmlns_carbons)
-			and not stanza:get_child("forwarded", xmlns_forward) then
+	if not c2s and stanza:get_child("private", xmlns_carbons) then
+		stanza:maptags(function(tag)
+			return tag.attr.xmlns == xmlns_carbons
+				and tag.name == "private" and tag or nil;
+		end);
+		return
+	end
+
+	if not stanza:get_child("forwarded", xmlns_forward) then
 		user_sessions = user_sessions and user_sessions.sessions;
 		for resource, session in pairs(user_sessions) do
 			local full_jid = bare_jid .. "/" .. resource;
-			if session ~= origin and session.want_carbons then
-				local msg = st.clone(stanza);
-				msg.attr.xmlns = msg.attr.xmlns or "jabber:client";
-				local fwd = st.message{
-							from = bare_jid,
-							to = full_jid,
-							type = orig_type,
-						}
-					:tag("forwarded", { xmlns = xmlns_forward })
-						:tag("sent", { xmlns = xmlns_carbons }):up()
-							:add_child(msg);
-				core_route_stanza(origin, fwd);
+			if session.want_carbons then
+				if (c2s and session ~= origin) or (not c2s and not no_carbon_to[resource]) then
+					local msg = st.clone(stanza);
+					msg.attr.xmlns = msg.attr.xmlns or "jabber:client";
+					local fwd = st.message{
+								from = bare_jid,
+								to = full_jid,
+								type = orig_type,
+							}
+						:tag("forwarded", { xmlns = xmlns_forward })
+							:tag(c2s and "sent" or "received", { xmlns = xmlns_carbons }):up()
+								:add_child(msg);
+					core_post_stanza(origin, fwd);
+				end
 			end
 		end
 	end
 end
 
-function s2c_message_handler(event)
-	local origin, stanza = event.origin, event.stanza;
-	local orig_type = stanza.attr.type;
-	local orig_to = stanza.attr.to;
-	
-	if not (orig_type == nil
-			or orig_type == "normal"
-			or orig_type == "chat") then
-		return
-	end
-
-	local full_jid, bare_jid = orig_to, jid_bare(orig_to);
-	local username, hostname, resource = jid_split(full_jid);
-	local user_sessions = username and host_sessions[username];
-	if not user_sessions or hostname ~= module.host then
-		return
-	end
-
-	local no_carbon_to = {};
-	if resource then
-		no_carbon_to[resource] = true;
-	else
-		local top_resources = user_sessions.top_resources;
-		for i, session in ipairs(top_resources) do
-			no_carbon_to[session.resource] = true;
-			module:log("debug", "not going to send to /%s", resource);
-		end
-	end
-
-	if not stanza:get_child("private", xmlns_carbons)
-			and not stanza:get_child("forwarded", xmlns_forward) then
-		user_sessions = user_sessions and user_sessions.sessions;
-		for resource, session in pairs(user_sessions) do
-			local full_jid = bare_jid .. "/" .. resource;
-			if not no_carbon_to[resource] and session.want_carbons then
-				local msg = st.clone(stanza);
-				msg.attr.xmlns = msg.attr.xmlns or "jabber:client";
-				local fwd = st.message{
-							from = bare_jid,
-							to = full_jid,
-							type = orig_type,
-						}
-					:tag("forwarded", { xmlns = xmlns_forward })
-						:tag("received", { xmlns = xmlns_carbons }):up()
-							:add_child(msg);
-				core_route_stanza(origin, fwd);
-			end
-		end
-	end
+local function c2s_message_handler(event)
+	return message_handler(event, true)
 end
 
 -- Stanzas sent by local clients
 module:hook("pre-message/bare", c2s_message_handler, 1);
 module:hook("pre-message/full", c2s_message_handler, 1);
 -- Stanszas to local clients
-module:hook("message/bare", s2c_message_handler, 1);
-module:hook("message/full", s2c_message_handler, 1);
+module:hook("message/bare", message_handler, 1);
+module:hook("message/full", message_handler, 1);
 
 module:add_feature(xmlns_carbons);