diff options
-rw-r--r-- | core/modulemanager.lua | 156 | ||||
-rw-r--r-- | core/stanza_router.lua | 10 | ||||
-rw-r--r-- | main.lua | 13 | ||||
-rw-r--r-- | plugins/mod_dialback.lua | 8 | ||||
-rw-r--r-- | plugins/mod_disco.lua | 4 | ||||
-rw-r--r-- | plugins/mod_legacyauth.lua | 4 | ||||
-rw-r--r-- | plugins/mod_ping.lua | 2 | ||||
-rw-r--r-- | plugins/mod_private.lua | 2 | ||||
-rw-r--r-- | plugins/mod_register.lua | 4 | ||||
-rw-r--r-- | plugins/mod_roster.lua | 4 | ||||
-rw-r--r-- | plugins/mod_saslauth.lua | 12 | ||||
-rw-r--r-- | plugins/mod_selftests.lua | 2 | ||||
-rw-r--r-- | plugins/mod_time.lua | 4 | ||||
-rw-r--r-- | plugins/mod_tls.lua | 4 | ||||
-rw-r--r-- | plugins/mod_uptime.lua | 2 | ||||
-rw-r--r-- | plugins/mod_vcard.lua | 4 | ||||
-rw-r--r-- | plugins/mod_version.lua | 4 |
17 files changed, 143 insertions, 96 deletions
diff --git a/core/modulemanager.lua b/core/modulemanager.lua index d313130c..704bd26f 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -1,5 +1,7 @@ -local log = require "util.logger".init("modulemanager") + +local logger = require "util.logger"; +local log = logger.init("modulemanager") local loadfile, pcall = loadfile, pcall; local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; @@ -14,80 +16,59 @@ local debug = debug; module "modulemanager" -local handler_info = {}; -local handlers = {}; - -local modulehelpers = setmetatable({}, { __index = _G }); +local api = {}; -- Module API container -local function _add_iq_handler(module, origin_type, xmlns, handler) - handlers[origin_type] = handlers[origin_type] or {}; - handlers[origin_type].iq = handlers[origin_type].iq or {}; - if not handlers[origin_type].iq[xmlns] then - handlers[origin_type].iq[xmlns]= handler; - handler_info[handler] = module; - log("debug", "mod_%s now handles tag 'iq' with query namespace '%s'", module.name, xmlns); - else - log("warning", "mod_%s wants to handle tag 'iq' with query namespace '%s' but mod_%s already handles that", module.name, xmlns, handler_info[handlers[origin_type].iq[xmlns]].module.name); - end -end +local modulemap = {}; -function modulehelpers.add_iq_handler(origin_type, xmlns, handler) - if not (origin_type and handler and xmlns) then return false; end - if type(origin_type) == "table" then - for _, origin_type in ipairs(origin_type) do - _add_iq_handler(getfenv(2).module, origin_type, xmlns, handler); - end - return; - end - _add_iq_handler(getfenv(2).module, origin_type, xmlns, handler); -end +local handler_info = {}; +local stanza_handlers = {}; -local function _add_handler(module, origin_type, tag, xmlns, handler) - handlers[origin_type] = handlers[origin_type] or {}; - if not handlers[origin_type][tag] then - handlers[origin_type][tag] = handlers[origin_type][tag] or {}; - handlers[origin_type][tag][xmlns]= handler; - handler_info[handler] = module; - log("debug", "mod_%s now handles tag '%s'", module.name, tag); - elseif handler_info[handlers[origin_type][tag]] then - log("warning", "mod_%s wants to handle tag '%s' but mod_%s already handles that", module.name, tag, handler_info[handlers[origin_type][tag]].module.name); - end -end +local modulehelpers = setmetatable({}, { __index = _G }); -function modulehelpers.add_handler(origin_type, tag, xmlns, handler) - if not (origin_type and tag and xmlns and handler) then return false; end - if type(origin_type) == "table" then - for _, origin_type in ipairs(origin_type) do - _add_handler(getfenv(2).module, origin_type, tag, xmlns, handler); - end - return; - end - _add_handler(getfenv(2).module, origin_type, tag, xmlns, handler); -end -function load(name) - local mod, err = loadfile("plugins/mod_"..name..".lua"); +function load(host, module_name, config) + local mod, err = loadfile("plugins/mod_"..module_name..".lua"); if not mod then - log("error", "Unable to load module '%s': %s", name or "nil", err or "nil"); + log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); return nil, err; end - local pluginenv = setmetatable({ module = { name = name } }, { __index = modulehelpers }); + if not modulemap[host] then + modulemap[host] = {}; + stanza_handlers[host] = {}; + elseif modulemap[host][module_name] then + log("warn", "%s is already loaded for %s, so not loading again", module_name, host); + return nil, "module-already-loaded"; + end + + local _log = logger.init(host..":"..module_name); + local api_instance = setmetatable({ name = module_name, host = host, config = config, _log = _log, log = function (self, ...) return _log(...); end }, { __index = api }); + + local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); setfenv(mod, pluginenv); + local success, ret = pcall(mod); if not success then log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil"); return nil, ret; end + + modulemap[host][module_name] = mod; + return true; end -function handle_stanza(origin, stanza) +function handle_stanza(host, origin, stanza) local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; + local handlers = stanza_handlers[host]; + if not handlers then + log("warn", "No handlers for %s", host); + return false; + end + if name == "iq" and xmlns == "jabber:client" and handlers[origin_type] then - log("debug", "Stanza is an <iq/>"); local child = stanza.tags[1]; if child then local xmlns = child.attr.xmlns or xmlns; @@ -112,14 +93,54 @@ function handle_stanza(origin, stanza) return false; -- we didn't handle it end +----- API functions exposed to modules ----------- +-- Must all be in api.* + +-- Returns the name of the current module +function api:get_name() + return self.name; +end + +-- Returns the host that the current module is serving +function api:get_host() + return self.host; +end + + +local function _add_iq_handler(module, origin_type, xmlns, handler) + local handlers = stanza_handlers[module.host]; + handlers[origin_type] = handlers[origin_type] or {}; + handlers[origin_type].iq = handlers[origin_type].iq or {}; + if not handlers[origin_type].iq[xmlns] then + handlers[origin_type].iq[xmlns]= handler; + handler_info[handler] = module; + module:log("debug", "I now handle tag 'iq' [%s] with payload namespace '%s'", origin_type, xmlns); + else + module:log("warn", "I wanted to handle tag 'iq' [%s] with payload namespace '%s' but mod_%s already handles that", origin_type, xmlns, handler_info[handlers[origin_type].iq[xmlns]].name); + end +end + +function api:add_iq_handler(origin_type, xmlns, handler) + if not (origin_type and handler and xmlns) then return false; end + if type(origin_type) == "table" then + for _, origin_type in ipairs(origin_type) do + _add_iq_handler(self, origin_type, xmlns, handler); + end + return; + end + _add_iq_handler(self, origin_type, xmlns, handler); +end + + do local event_handlers = {}; - function modulehelpers.add_event_hook(name, handler) + function api:add_event_hook(name, handler) if not event_handlers[name] then event_handlers[name] = {}; end t_insert(event_handlers[name] , handler); + self:log("debug", "Subscribed to %s", name); end function fire_event(name, ...) @@ -132,4 +153,31 @@ do end end + +local function _add_handler(module, origin_type, tag, xmlns, handler) + local handlers = stanza_handlers[module.host]; + handlers[origin_type] = handlers[origin_type] or {}; + if not handlers[origin_type][tag] then + handlers[origin_type][tag] = handlers[origin_type][tag] or {}; + handlers[origin_type][tag][xmlns]= handler; + handler_info[handler] = module; + module:log("debug", "I now handle tag '%s' [%s] with xmlns '%s'", tag, origin_type, xmlns); + elseif handler_info[handlers[origin_type][tag]] then + log("warning", "I wanted to handle tag '%s' [%s] but mod_%s already handles that", tag, origin_type, handler_info[handlers[origin_type][tag]].module.name); + end +end + +function api:add_handler(origin_type, tag, xmlns, handler) + if not (origin_type and tag and xmlns and handler) then return false; end + if type(origin_type) == "table" then + for _, origin_type in ipairs(origin_type) do + _add_handler(self, origin_type, tag, xmlns, handler); + end + return; + end + _add_handler(self, origin_type, tag, xmlns, handler); +end + +-------------------------------------------------------------------- + return _M; diff --git a/core/stanza_router.lua b/core/stanza_router.lua index 2505fca3..308ae2f4 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -1,10 +1,4 @@ --- The code in this file should be self-explanatory, though the logic is horrible --- for more info on that, see doc/stanza_routing.txt, which attempts to condense --- the rules from the RFCs (mainly 3921) - -require "core.servermanager" - local log = require "util.logger".init("stanzarouter") local st = require "util.stanza"; @@ -82,7 +76,7 @@ function core_process_stanza(origin, stanza) elseif hosts[to] and hosts[to].type == "local" then -- directed at a local server core_handle_stanza(origin, stanza); elseif stanza.attr.xmlns and stanza.attr.xmlns ~= "jabber:client" and stanza.attr.xmlns ~= "jabber:server" then - modules_handle_stanza(origin, stanza); + modules_handle_stanza(host or origin.host or origin.to_host, origin, stanza); elseif hosts[to_bare] and hosts[to_bare].type == "component" then -- hack to allow components to handle node@server component_handle_stanza(origin, stanza); elseif hosts[to] and hosts[to].type == "component" then -- hack to allow components to handle node@server/resource and server/resource @@ -105,7 +99,7 @@ end -- that is, they are handled by this server function core_handle_stanza(origin, stanza) -- Handlers - if modules_handle_stanza(origin, stanza) then return; end + if modules_handle_stanza(stanza.attr.to or origin.host, origin, stanza) then return; end if origin.type == "c2s" or origin.type == "c2s_unauthed" then local session = origin; @@ -63,10 +63,15 @@ require "util.jid" ------------------------------------------------------------------------ -- Initialise modules -local modules_enabled = config.get("*", "core", "modules_enabled"); -if modules_enabled then - for _, module in pairs(modules_enabled) do - modulemanager.load(module); + +for host in pairs(hosts) do + if host ~= "*" then + local modules_enabled = config.get(host, "core", "modules_enabled"); + if modules_enabled then + for _, module in pairs(modules_enabled) do + modulemanager.load(host, module); + end + end end end diff --git a/plugins/mod_dialback.lua b/plugins/mod_dialback.lua index 87ac303b..e7804962 100644 --- a/plugins/mod_dialback.lua +++ b/plugins/mod_dialback.lua @@ -8,7 +8,7 @@ local log = require "util.logger".init("mod_dialback"); local xmlns_dialback = "jabber:server:dialback"; -add_handler({"s2sin_unauthed", "s2sin"}, "verify", xmlns_dialback, +module:add_handler({"s2sin_unauthed", "s2sin"}, "verify", xmlns_dialback, function (origin, stanza) -- We are being asked to verify the key, to ensure it was generated by us log("debug", "verifying dialback key..."); @@ -26,7 +26,7 @@ add_handler({"s2sin_unauthed", "s2sin"}, "verify", xmlns_dialback, origin.sends2s(format("<db:verify from='%s' to='%s' id='%s' type='%s'>%s</db:verify>", attr.to, attr.from, attr.id, type, stanza[1])); end); -add_handler("s2sin_unauthed", "result", xmlns_dialback, +module:add_handler("s2sin_unauthed", "result", xmlns_dialback, function (origin, stanza) -- he wants to be identified through dialback -- We need to check the key with the Authoritative server @@ -42,7 +42,7 @@ add_handler("s2sin_unauthed", "result", xmlns_dialback, hosts[origin.to_host].s2sout[origin.from_host].dialback_verifying = origin; end); -add_handler({ "s2sout_unauthed", "s2sout" }, "verify", xmlns_dialback, +module:add_handler({ "s2sout_unauthed", "s2sout" }, "verify", xmlns_dialback, function (origin, stanza) if origin.dialback_verifying then local valid; @@ -64,7 +64,7 @@ add_handler({ "s2sout_unauthed", "s2sout" }, "verify", xmlns_dialback, end end); -add_handler({ "s2sout_unauthed", "s2sout" }, "result", xmlns_dialback, +module:add_handler({ "s2sout_unauthed", "s2sout" }, "result", xmlns_dialback, function (origin, stanza) if stanza.attr.type == "valid" then s2s_make_authenticated(origin); diff --git a/plugins/mod_disco.lua b/plugins/mod_disco.lua index fd93ecf3..fd9f2836 100644 --- a/plugins/mod_disco.lua +++ b/plugins/mod_disco.lua @@ -4,9 +4,9 @@ local discomanager_handle = require "core.discomanager".handle; require "core.discomanager".set("disco", "http://jabber.org/protocol/disco#info");
require "core.discomanager".set("disco", "http://jabber.org/protocol/disco#items");
-add_iq_handler({"c2s", "s2sin"}, "http://jabber.org/protocol/disco#info", function (session, stanza)
+module:add_iq_handler({"c2s", "s2sin"}, "http://jabber.org/protocol/disco#info", function (session, stanza)
session.send(discomanager_handle(stanza));
end);
-add_iq_handler({"c2s", "s2sin"}, "http://jabber.org/protocol/disco#items", function (session, stanza)
+module:add_iq_handler({"c2s", "s2sin"}, "http://jabber.org/protocol/disco#items", function (session, stanza)
session.send(discomanager_handle(stanza));
end);
diff --git a/plugins/mod_legacyauth.lua b/plugins/mod_legacyauth.lua index 02621af7..81e2ff7f 100644 --- a/plugins/mod_legacyauth.lua +++ b/plugins/mod_legacyauth.lua @@ -4,7 +4,7 @@ local t_concat = table.concat; require "core.discomanager".set("legacyauth", "jabber:iq:auth"); -add_iq_handler("c2s_unauthed", "jabber:iq:auth", +module:add_iq_handler("c2s_unauthed", "jabber:iq:auth", function (session, stanza) local username = stanza.tags[1]:child_with_name("username"); local password = stanza.tags[1]:child_with_name("password"); @@ -43,4 +43,4 @@ add_iq_handler("c2s_unauthed", "jabber:iq:auth", end end - end);
\ No newline at end of file + end); diff --git a/plugins/mod_ping.lua b/plugins/mod_ping.lua index c13282ff..8306078c 100644 --- a/plugins/mod_ping.lua +++ b/plugins/mod_ping.lua @@ -3,7 +3,7 @@ local st = require "util.stanza"; require "core.discomanager".set("ping", "urn:xmpp:ping");
-add_iq_handler({"c2s", "s2sin"}, "urn:xmpp:ping",
+module:add_iq_handler({"c2s", "s2sin"}, "urn:xmpp:ping",
function(session, stanza)
if stanza.attr.type == "get" then
session.send(st.reply(stanza));
diff --git a/plugins/mod_private.lua b/plugins/mod_private.lua index f07f8197..dd717d8d 100644 --- a/plugins/mod_private.lua +++ b/plugins/mod_private.lua @@ -6,7 +6,7 @@ local datamanager = require "util.datamanager" require "core.discomanager".set("private", "jabber:iq:private"); -add_iq_handler("c2s", "jabber:iq:private", +module:add_iq_handler("c2s", "jabber:iq:private", function (session, stanza) local type = stanza.attr.type; local query = stanza.tags[1]; diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua index 0974725d..5769bd80 100644 --- a/plugins/mod_register.lua +++ b/plugins/mod_register.lua @@ -6,7 +6,7 @@ local datamanager_store = require "util.datamanager".store; require "core.discomanager".set("register", "jabber:iq:register"); -add_iq_handler("c2s", "jabber:iq:register", function (session, stanza) +module:add_iq_handler("c2s", "jabber:iq:register", function (session, stanza) if stanza.tags[1].name == "query" then local query = stanza.tags[1]; if stanza.attr.type == "get" then @@ -73,7 +73,7 @@ add_iq_handler("c2s", "jabber:iq:register", function (session, stanza) end; end); -add_iq_handler("c2s_unauthed", "jabber:iq:register", function (session, stanza) +module:add_iq_handler("c2s_unauthed", "jabber:iq:register", function (session, stanza) if stanza.tags[1].name == "query" then local query = stanza.tags[1]; if stanza.attr.type == "get" then diff --git a/plugins/mod_roster.lua b/plugins/mod_roster.lua index 23223a65..0b52e43e 100644 --- a/plugins/mod_roster.lua +++ b/plugins/mod_roster.lua @@ -11,7 +11,7 @@ local rm_roster_push = require "core.rostermanager".roster_push; require "core.discomanager".set("roster", "jabber:iq:roster"); -add_iq_handler("c2s", "jabber:iq:roster", +module:add_iq_handler("c2s", "jabber:iq:roster", function (session, stanza) if stanza.tags[1].name == "query" then if stanza.attr.type == "get" then @@ -103,4 +103,4 @@ add_iq_handler("c2s", "jabber:iq:roster", return true; end end - end);
\ No newline at end of file + end); diff --git a/plugins/mod_saslauth.lua b/plugins/mod_saslauth.lua index 7ca4308b..f549d0b9 100644 --- a/plugins/mod_saslauth.lua +++ b/plugins/mod_saslauth.lua @@ -79,14 +79,14 @@ function sasl_handler(session, stanza) session.send(s); end -add_handler("c2s_unauthed", "auth", xmlns_sasl, sasl_handler); -add_handler("c2s_unauthed", "abort", xmlns_sasl, sasl_handler); -add_handler("c2s_unauthed", "response", xmlns_sasl, sasl_handler); +module:add_handler("c2s_unauthed", "auth", xmlns_sasl, sasl_handler); +module:add_handler("c2s_unauthed", "abort", xmlns_sasl, sasl_handler); +module:add_handler("c2s_unauthed", "response", xmlns_sasl, sasl_handler); local mechanisms_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-sasl' }; local bind_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-bind' }; local xmpp_session_attr = { xmlns='urn:ietf:params:xml:ns:xmpp-session' }; -add_event_hook("stream-features", +module:add_event_hook("stream-features", function (session, features) if not session.username then features:tag("mechanisms", mechanisms_attr); @@ -100,7 +100,7 @@ add_event_hook("stream-features", end end); -add_iq_handler("c2s", "urn:ietf:params:xml:ns:xmpp-bind", +module:add_iq_handler("c2s", "urn:ietf:params:xml:ns:xmpp-bind", function (session, stanza) log("debug", "Client tried to bind to a resource"); local resource; @@ -123,7 +123,7 @@ add_iq_handler("c2s", "urn:ietf:params:xml:ns:xmpp-bind", end end); -add_iq_handler("c2s", "urn:ietf:params:xml:ns:xmpp-session", +module:add_iq_handler("c2s", "urn:ietf:params:xml:ns:xmpp-session", function (session, stanza) log("debug", "Client tried to bind to a resource"); session.send(st.reply(stanza)); diff --git a/plugins/mod_selftests.lua b/plugins/mod_selftests.lua index 8aa70952..4d44d2fd 100644 --- a/plugins/mod_selftests.lua +++ b/plugins/mod_selftests.lua @@ -36,7 +36,7 @@ if tests_jid and host then local our_origin = hosts[host]; - add_event_hook("server-started", + module:add_event_hook("server-started", function () local id = st.new_id(); local ping_attr = { xmlns = 'urn:xmpp:ping' }; diff --git a/plugins/mod_time.lua b/plugins/mod_time.lua index bf079692..68224421 100644 --- a/plugins/mod_time.lua +++ b/plugins/mod_time.lua @@ -7,7 +7,7 @@ local legacy = require "util.datetime".legacy; require "core.discomanager".set("time", "urn:xmpp:time");
-add_iq_handler({"c2s", "s2sin"}, "urn:xmpp:time",
+module:add_iq_handler({"c2s", "s2sin"}, "urn:xmpp:time",
function(session, stanza)
if stanza.attr.type == "get" then
session.send(st.reply(stanza):tag("time", {xmlns="urn:xmpp:time"})
@@ -20,7 +20,7 @@ add_iq_handler({"c2s", "s2sin"}, "urn:xmpp:time", require "core.discomanager".set("time", "jabber:iq:time");
-add_iq_handler({"c2s", "s2sin"}, "jabber:iq:time",
+module:add_iq_handler({"c2s", "s2sin"}, "jabber:iq:time",
function(session, stanza)
if stanza.attr.type == "get" then
session.send(st.reply(stanza):tag("query", {xmlns="jabber:iq:time"})
diff --git a/plugins/mod_tls.lua b/plugins/mod_tls.lua index cc46d556..d5f3157b 100644 --- a/plugins/mod_tls.lua +++ b/plugins/mod_tls.lua @@ -9,7 +9,7 @@ local log = require "util.logger".init("mod_starttls"); local xmlns_starttls ='urn:ietf:params:xml:ns:xmpp-tls'; -add_handler("c2s_unauthed", "starttls", xmlns_starttls, +module:add_handler("c2s_unauthed", "starttls", xmlns_starttls, function (session, stanza) if session.conn.starttls then session.send(st.stanza("proceed", { xmlns = xmlns_starttls })); @@ -25,7 +25,7 @@ add_handler("c2s_unauthed", "starttls", xmlns_starttls, end); local starttls_attr = { xmlns = xmlns_starttls }; -add_event_hook("stream-features", +module:add_event_hook("stream-features", function (session, features) if session.conn.starttls then features:tag("starttls", starttls_attr):up(); diff --git a/plugins/mod_uptime.lua b/plugins/mod_uptime.lua index 9c2cb45d..4b4c28d1 100644 --- a/plugins/mod_uptime.lua +++ b/plugins/mod_uptime.lua @@ -8,7 +8,7 @@ local start_time = os.time(); require "core.discomanager".set("uptime", "jabber:iq:last");
-add_iq_handler({"c2s", "s2sin"}, "jabber:iq:last",
+module:add_iq_handler({"c2s", "s2sin"}, "jabber:iq:last",
function (origin, stanza)
if stanza.tags[1].name == "query" then
if stanza.attr.type == "get" then
diff --git a/plugins/mod_vcard.lua b/plugins/mod_vcard.lua index 1d9b3d63..844a2406 100644 --- a/plugins/mod_vcard.lua +++ b/plugins/mod_vcard.lua @@ -10,7 +10,7 @@ local jid_split = jid.split; require "core.discomanager".set("vcard", "vcard-temp"); -add_iq_handler({"c2s", "s2sin"}, "vcard-temp", +module:add_iq_handler({"c2s", "s2sin"}, "vcard-temp", function (session, stanza) if stanza.tags[1].name == "vCard" then local to = stanza.attr.to; @@ -46,7 +46,7 @@ add_iq_handler({"c2s", "s2sin"}, "vcard-temp", end); local feature_vcard_attr = { var='vcard-temp' }; -add_event_hook("stream-features", +module:add_event_hook("stream-features", function (session, features) if session.type == "c2s" then features:tag("feature", feature_vcard_attr):up(); diff --git a/plugins/mod_version.lua b/plugins/mod_version.lua index 2f68fa07..11278a53 100644 --- a/plugins/mod_version.lua +++ b/plugins/mod_version.lua @@ -16,5 +16,5 @@ local function handle_version_request(session, stanza) end end -add_iq_handler("c2s", xmlns_version, handle_version_request); -add_iq_handler("s2sin", xmlns_version, handle_version_request); +module:add_iq_handler("c2s", xmlns_version, handle_version_request); +module:add_iq_handler("s2sin", xmlns_version, handle_version_request); |