diff plugins/mod_admin_shell.lua @ 13976:a2d4c71f5066

mod_admin_shell: Add debug:ping() which prints debug logs until pong Essentially a verbose version of xmpp:ping(), but more useful for debugging s2s issues without having to watch (and have enabled) debug logs at the same time and try to pick out where the start and end are.
author Kim Alvefur <zash@zash.se>
date Sun, 05 Oct 2025 11:08:27 +0200
parents b1e7d3f571b1
children d520cee2bbdb
line wrap: on
line diff
--- a/plugins/mod_admin_shell.lua	Thu Oct 02 21:09:51 2025 +0200
+++ b/plugins/mod_admin_shell.lua	Sun Oct 05 11:08:27 2025 +0200
@@ -2465,6 +2465,44 @@
 	return true, ("Showing %d certificates in %s"):format(c, path);
 end
 
+describe_command [[debug:ping(localhost, remotehost) - Sends a ping to a remote XMPP server while printing debug logs]]
+function def_env.debug:ping(localhost, remotehost, timeout)
+	localhost = select(2, jid_split(localhost));
+	remotehost = select(2, jid_split(remotehost));
+	if not localhost then
+		return nil, "Invalid sender hostname";
+	elseif not prosody.hosts[localhost] then
+		return nil, "No such local host";
+	end
+	if not remotehost then
+		return nil, "Invalid destination hostname";
+	elseif prosody.hosts[remotehost] then
+		return nil, "Both hosts are local";
+	end
+
+	local iq = st.iq{ from=localhost, to=remotehost, type="get", id=new_id()}
+			:tag("ping", {xmlns="urn:xmpp:ping"});
+	local time_start = time.now();
+	local print = self.session.print;
+
+	local writing = false;
+	local sink = logger.add_simple_sink(function (source, level, message)
+		if writing then return; end
+		writing = true;
+		print(source, level, message);
+		writing = false;
+	end);
+
+	return module:context(localhost):send_iq(iq, nil, timeout):finally(function()
+		if not logger.remove_sink(sink) then
+			module:log("warn", "Unable to remove watch:log() sink");
+		end
+	end):next(function(pong)
+		return ("pong from %s on %s in %gs"):format(pong.stanza.attr.from, pong.origin.id, time.now() - time_start);
+	end);
+end
+
+
 def_env.role = new_section("Role and access management");
 
 describe_command [[role:list(host) - List known roles]]