aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2020-06-01 15:42:19 +0100
committerMatthew Wild <mwild1@gmail.com>2020-06-01 15:42:19 +0100
commit4c6992a00e582dc2c9c6a7ad721cd7e831202a1e (patch)
tree80b6f729c4bba52b4bf8de06b658c03048a6abd1 /plugins
parent6ccd66e347747b0fd7b2a193a777b46d913c38ee (diff)
downloadprosody-4c6992a00e582dc2c9c6a7ad721cd7e831202a1e.tar.gz
prosody-4c6992a00e582dc2c9c6a7ad721cd7e831202a1e.zip
mod_admin_socket, util.adminstream: New module to manage a local unix domain socket for admin functionality
Diffstat (limited to 'plugins')
-rw-r--r--plugins/mod_admin_socket.lua69
1 files changed, 69 insertions, 0 deletions
diff --git a/plugins/mod_admin_socket.lua b/plugins/mod_admin_socket.lua
new file mode 100644
index 00000000..c094aad2
--- /dev/null
+++ b/plugins/mod_admin_socket.lua
@@ -0,0 +1,69 @@
+module:set_global();
+
+local have_unix, unix = pcall(require, "socket.unix");
+
+if not have_unix or type(unix) ~= "table" then
+ module:log_status("error", "LuaSocket unix socket support not available or incompatible, ensure it is up to date");
+ return;
+end
+
+local server = require "net.server";
+
+local adminstream = require "util.adminstream";
+
+local socket_path = module:get_option_string("admin_socket", prosody.paths.data.."/prosody.sock");
+
+local sessions = module:shared("sessions");
+
+local function fire_admin_event(session, stanza)
+ local event_data = {
+ origin = session, stanza = stanza;
+ };
+ local event_name;
+ if stanza.attr.xmlns then
+ event_name = "admin/"..stanza.attr.xmlns..":"..stanza.name;
+ else
+ event_name = "admin/"..stanza.name;
+ end
+ module:log("debug", "Firing %s", event_name);
+ return module:fire_event(event_name, event_data);
+end
+
+module:hook("server-stopping", function ()
+ for _, session in pairs(sessions) do
+ session:close("system-shutdown");
+ end
+ os.remove(socket_path);
+end);
+
+--- Unix domain socket management
+
+local conn, sock;
+
+local listeners = adminstream.server(sessions, fire_admin_event).listeners;
+
+local function accept_connection()
+ module:log("debug", "accepting...");
+ local client = sock:accept();
+ if not client then return; end
+ server.wrapclient(client, "unix", 0, listeners, "*a");
+end
+
+function module.load()
+ sock = unix.stream();
+ sock:settimeout(0);
+ os.remove(socket_path);
+ assert(sock:bind(socket_path));
+ assert(sock:listen());
+ conn = server.watchfd(sock:getfd(), accept_connection);
+end
+
+function module.unload()
+ if conn then
+ conn:close();
+ end
+ if sock then
+ sock:close();
+ end
+ os.remove(socket_path);
+end