diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/componentmanager.lua | 39 | ||||
-rw-r--r-- | core/configmanager.lua | 14 | ||||
-rw-r--r-- | core/hostmanager.lua | 1 | ||||
-rw-r--r-- | core/modulemanager.lua | 78 | ||||
-rw-r--r-- | core/s2smanager.lua | 4 |
5 files changed, 110 insertions, 26 deletions
diff --git a/core/componentmanager.lua b/core/componentmanager.lua index f8db2d2c..0c33e7f6 100644 --- a/core/componentmanager.lua +++ b/core/componentmanager.lua @@ -21,14 +21,43 @@ local log = require "util.logger".init("componentmanager"); -local module_load = require "core.modulemanager".load; -local module_unload = require "core.modulemanager".unload;
+local configmanager = require "core.configmanager"; +local eventmanager = require "core.eventmanager"; +local modulemanager = require "core.modulemanager";
local jid_split = require "util.jid".split;
-local hosts = hosts;
+local hosts = hosts; + +local pairs, type, tostring = pairs, type, tostring;
local components = {};
module "componentmanager"
+ +function load_enabled_components(config) + local defined_hosts = config or configmanager.getconfig(); + + for host, host_config in pairs(defined_hosts) do + if host ~= "*" and ((host_config.core.enabled == nil or host_config.core.enabled) and type(host_config.core.component_module) == "string") then + hosts[host] = { type = "component", host = host, connected = true, s2sout = {} }; + modulemanager.load(host, "dialback"); + local ok, err = modulemanager.load(host, host_config.core.component_module); + if not ok then + log("error", "Error loading %s component %s: %s", tostring(host_config.core.component_module), tostring(host), tostring(err)); + else + log("info", "Activated %s component: %s", host_config.core.component_module, host); + end + + local ok, component_handler = modulemanager.call_module_method(modulemanager.get_module(host, host_config.core.component_module), "load_component"); + if not ok then + log("error", "Error loading %s component %s: %s", tostring(host_config.core.component_module), tostring(host), tostring(component_handler)); + else + components[host] = component_handler; + end + end + end +end + +eventmanager.add_event_hook("server-starting", load_enabled_components); function handle_stanza(origin, stanza)
local node, host = jid_split(stanza.attr.to);
@@ -50,7 +79,7 @@ function register_component(host, component) components[host] = component;
hosts[host] = { type = "component", host = host, connected = true, s2sout = {} }; -- FIXME only load for a.b.c if b.c has dialback, and/or check in config - module_load(host, "dialback");
+ modulemanager.load(host, "dialback");
log("debug", "component added: "..host);
return hosts[host];
else
@@ -60,7 +89,7 @@ end function deregister_component(host) if components[host] then - module_unload(host, "dialback"); + modulemanager.unload(host, "dialback"); components[host] = nil; hosts[host] = nil; log("debug", "component removed: "..host); diff --git a/core/configmanager.lua b/core/configmanager.lua index a6e86347..a50e7223 100644 --- a/core/configmanager.lua +++ b/core/configmanager.lua @@ -107,7 +107,8 @@ do parsers.lua = {}; function parsers.lua.load(data) local env; - env = setmetatable({ Host = true; host = true; }, { __index = function (t, k) + -- The ' = true' are needed so as not to set off __newindex when we assign the functions below + env = setmetatable({ Host = true; host = true; Component = true, component = true }, { __index = function (t, k) return rawget(_G, k) or function (settings_table) config[__currenthost or "*"][k] = settings_table; @@ -119,10 +120,21 @@ do function env.Host(name) rawset(env, "__currenthost", name); + -- Needs at least one setting to logically exist :) set(name or "*", "core", "defined", true); end env.host = env.Host; + function env.Component(name) + return function (module) + set(name, "core", "component_module", module); + -- Don't load the global modules by default + set(name, "core", "modules_enable", false); + rawset(env, "__currenthost", name); + end + end + env.component = env.Component; + local chunk, err = loadstring(data); if not chunk then diff --git a/core/hostmanager.lua b/core/hostmanager.lua index 64bb13f7..1fec9799 100644 --- a/core/hostmanager.lua +++ b/core/hostmanager.lua @@ -17,6 +17,7 @@ local function load_enabled_hosts(config) activate(host, host_config); end end + eventmanager.fire_event("hosts-activated", defined_hosts); end eventmanager.add_event_hook("server-starting", load_enabled_hosts); diff --git a/core/modulemanager.lua b/core/modulemanager.lua index e783e9b4..8292eaa5 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -29,10 +29,12 @@ local config = require "core.configmanager"; local multitable_new = require "util.multitable".new; local register_actions = require "core.actions".register; +local hosts = hosts; + local loadfile, pcall = loadfile, pcall; local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; local pairs, ipairs = pairs, ipairs; -local t_insert = table.insert; +local t_insert, t_concat = table.insert, table.concat; local type = type; local next = next; local rawget = rawget; @@ -107,7 +109,7 @@ function load(host, module_name, config) end - local mod, err = loadfile(plugin_dir.."mod_"..module_name..".lua"); + local mod, err = loadfile(get_module_filename(module_name)); if not mod then log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); return nil, err; @@ -132,18 +134,22 @@ function load(host, module_name, config) return true; end +function get_module(host, name) + return modulemap[host] and modulemap[host][name]; +end + function is_loaded(host, name) return modulemap[host] and modulemap[host][name] and true; end function unload(host, name, ...) - local mod = modulemap[host] and modulemap[host][name]; + local mod = get_module(host, name); if not mod then return nil, "module-not-loaded"; end - if type(mod.module.unload) == "function" then - local ok, err = pcall(mod.module.unload, ...) + if module_has_method(mod, "unload") then + local ok, err = call_module_method(mod, "unload"); if (not ok) and err then - log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); + log("warn", "Non-fatal error unloading module '%s' on '%s': %s", name, host, err); end end modulemap[host][name] = nil; @@ -161,36 +167,45 @@ function unload(host, name, ...) end function reload(host, name, ...) - local mod = modulemap[host] and modulemap[host][name]; + local mod = get_module(host, name); if not mod then return nil, "module-not-loaded"; end - local _mod, err = loadfile(plugin_dir.."mod_"..name..".lua"); -- checking for syntax errors + local _mod, err = loadfile(get_module_filename(name)); -- checking for syntax errors if not _mod then log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); return nil, err; end local saved; - if type(mod.module.save) == "function" then - local ok, err = pcall(mod.module.save) - if (not ok) and err then - log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); + + if module_has_method(mod, "save") then + local ok, ret, err = call_module_method(mod, "save"); + if ok then + saved = ret; else - saved = err; + log("warn", "Error saving module '%s:%s' state: %s", host, module, ret); + if not config.get(host, "core", "force_module_reload") then + log("warn", "Aborting reload due to error, set force_module_reload to ignore this"); + return nil, "save-state-failed"; + else + log("warn", "Continuing with reload (using the force)"); + end end end unload(host, name, ...); - if load(host, name, ...) then - mod = modulemap[host] and modulemap[host][name]; - if type(mod.module.restore) == "function" then - local ok, err = pcall(mod.module.restore, saved or {}) + local ok, err = load(host, name, ...); + if ok then + mod = get_module(host, name); + if module_has_method(mod, "restore") then + local ok, err = call_module_method(mod, "restore", saved or {}) if (not ok) and err then - log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); + log("warn", "Error restoring module '%s' from '%s': %s", name, host, err); end end return true; end + return ok, err; end function handle_stanza(host, origin, stanza) @@ -214,6 +229,25 @@ function handle_stanza(host, origin, stanza) end end +function module_has_method(module, method) + return type(module.module[method]) == "function"; +end + +function call_module_method(module, method, ...) + if module_has_method(module, method) then + local f = module.module[method]; + return pcall(f, ...); + else + return false, "no-such-method"; + end +end + +local _modulepath = { plugin_dir, "mod_", nil, ".lua"}; +function get_module_filename(name) + _modulepath[3] = name; + return t_concat(_modulepath); +end + ----- API functions exposed to modules ----------- -- Must all be in api.* @@ -227,6 +261,14 @@ function api:get_host() return self.host; end +function api:get_host_type() + return hosts[self.host].type; +end + +function api:set_global() + self.host = "*"; +end + local function _add_handler(module, origin_type, tag, xmlns, handler) local handlers = stanza_handlers:get(module.host, origin_type, tag, xmlns); local msg = (tag == "iq") and "namespace" or "payload namespace"; diff --git a/core/s2smanager.lua b/core/s2smanager.lua index bc1abfe8..5243085c 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -31,7 +31,7 @@ local tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber local idna_to_ascii = require "util.encodings".idna.to_ascii; local connlisteners_get = require "net.connlisteners".get; -local wraptlsclient = require "net.server".wraptlsclient; +local wrapclient = require "net.server".wrapclient; local modulemanager = require "core.modulemanager"; local st = require "stanza"; local stanza = st.stanza; @@ -196,7 +196,7 @@ function attempt_connection(host_session, err) end local cl = connlisteners_get("xmppserver"); - conn = wraptlsclient(cl, conn, connect_host, connect_port, 0, cl.default_mode or 1, hosts[from_host].ssl_ctx ); + conn = wrapclient(conn, connect_host, connect_port, cl, cl.default_mode or 1, hosts[from_host].ssl_ctx, false ); host_session.conn = conn; -- Register this outgoing connection so that xmppserver_listener knows about it |