IMPORTANT: due to a drive failure, as of 13-Mar-2021, the Mercurial repository had to be re-mirrored, which changed every commit SHA. The old SHAs and trees are backed up in the vault branches. Please migrate to the new branches as soon as you can.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
prosody/plugins/mod_admin_socket.lua

90 lines
2.4 KiB

module:set_global();
local have_unix, unix = pcall(require, "socket.unix");
if have_unix and type(unix) == "function" then
-- COMPAT #1717
-- Before the introduction of datagram support, only the stream socket
-- constructor was exported instead of a module table. Due to the lack of a
-- proper release of LuaSocket, distros have settled on shipping either the
-- last RC tag or some commit since then.
-- Here we accomodate both variants.
unix = { stream = unix };
end
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_path("admin_socket", "prosody.sock", "data");
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);
local ok, err = sock:bind(socket_path);
if not ok then
module:log_status("error", "Unable to bind admin socket %s: %s", socket_path, err);
return;
end
local ok, err = sock:listen();
if not ok then
module:log_status("error", "Unable to listen on admin socket %s: %s", socket_path, err);
return;
end
if server.wrapserver then
conn = server.wrapserver(sock, socket_path, 0, listeners);
else
conn = server.watchfd(sock:getfd(), accept_connection);
end
end
function module.unload()
if conn then
conn:close();
end
if sock then
sock:close();
end
os.remove(socket_path);
end