diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/certmanager.lua | 1 | ||||
-rw-r--r-- | core/configmanager.lua | 42 | ||||
-rw-r--r-- | core/hostmanager.lua | 12 | ||||
-rw-r--r-- | core/loggingmanager.lua | 11 | ||||
-rw-r--r-- | core/moduleapi.lua | 105 | ||||
-rw-r--r-- | core/modulemanager.lua | 38 | ||||
-rw-r--r-- | core/portmanager.lua | 1 | ||||
-rw-r--r-- | core/rostermanager.lua | 7 | ||||
-rw-r--r-- | core/s2smanager.lua | 6 | ||||
-rw-r--r-- | core/sessionmanager.lua | 10 | ||||
-rw-r--r-- | core/stanza_router.lua | 10 | ||||
-rw-r--r-- | core/storagemanager.lua | 37 | ||||
-rw-r--r-- | core/usermanager.lua | 3 |
13 files changed, 145 insertions, 138 deletions
diff --git a/core/certmanager.lua b/core/certmanager.lua index dac4baa4..5282a6f5 100644 --- a/core/certmanager.lua +++ b/core/certmanager.lua @@ -55,6 +55,7 @@ local luasec_has = softreq"ssl.config" or { }; local _ENV = nil; +-- luacheck: std none -- Global SSL options if not overridden per-host local global_ssl_config = configmanager.get("*", "ssl"); diff --git a/core/configmanager.lua b/core/configmanager.lua index 5a544375..1e67da9b 100644 --- a/core/configmanager.lua +++ b/core/configmanager.lua @@ -7,12 +7,10 @@ -- local _G = _G; -local setmetatable, rawget, rawset, io, error, dofile, type, pairs, table = - setmetatable, rawget, rawset, io, error, dofile, type, pairs, table; +local setmetatable, rawget, rawset, io, os, error, dofile, type, pairs = + setmetatable, rawget, rawset, io, os, error, dofile, type, pairs; local format, math_max = string.format, math.max; -local fire_event = prosody and prosody.events.fire_event or function () end; - local envload = require"util.envload".envload; local deps = require"util.dependencies"; local resolve_relative_path = require"util.paths".resolve_relative_path; @@ -24,10 +22,11 @@ local nameprep = encodings and encodings.stringprep.nameprep or function (host) local _M = {}; local _ENV = nil; +-- luacheck: std none _M.resolve_relative_path = resolve_relative_path; -- COMPAT -local parsers = {}; +local parser = nil; local config_mt = { __index = function (t, _) return rawget(t, "*"); end}; local config = setmetatable({ ["*"] = { } }, config_mt); @@ -77,19 +76,14 @@ end function _M.load(filename, config_format) config_format = config_format or filename:match("%w+$"); - if parsers[config_format] and parsers[config_format].load then + if config_format == "lua" then local f, err = io.open(filename); if f then local new_config = setmetatable({ ["*"] = { } }, config_mt); - local ok, err = parsers[config_format].load(f:read("*a"), filename, new_config); + local ok, err = parser.load(f:read("*a"), filename, new_config); f:close(); if ok then config = new_config; - fire_event("config-reloaded", { - filename = filename, - format = config_format, - config = config - }); end return ok, "parser", err; end @@ -103,26 +97,11 @@ function _M.load(filename, config_format) end end -function _M.addparser(config_format, parser) - if config_format and parser then - parsers[config_format] = parser; - end -end - --- _M needed to avoid name clash with local 'parsers' -function _M.parsers() - local p = {}; - for config_format in pairs(parsers) do - table.insert(p, config_format); - end - return p; -end - -- Built-in Lua parser do local pcall = _G.pcall; - parsers.lua = {}; - function parsers.lua.load(data, config_file, config_table) + parser = {}; + function parser.load(data, config_file, config_table) local env; -- The ' = true' are needed so as not to set off __newindex when we assign the functions below env = setmetatable({ @@ -130,6 +109,9 @@ do Component = true, component = true, Include = true, include = true, RunScript = true }, { __index = function (_, k) + if k:match("^ENV_") then + return os.getenv(k:sub(5)); + end return rawget(_G, k); end, __newindex = function (_, k, v) @@ -211,7 +193,7 @@ do file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file); local f, err = io.open(file); if f then - local ret, err = parsers.lua.load(f:read("*a"), file, config_table); + local ret, err = parser.load(f:read("*a"), file, config_table); if not ret then error(err:gsub("%[string.-%]", file), 0); end end if not f then error("Error loading included "..file..": "..err, 0); end diff --git a/core/hostmanager.lua b/core/hostmanager.lua index 106a8ef2..9acca517 100644 --- a/core/hostmanager.lua +++ b/core/hostmanager.lua @@ -12,8 +12,6 @@ local events_new = require "util.events".new; local disco_items = require "util.multitable".new(); local NULL = {}; -local jid_split = require "util.jid".split; - local log = require "util.logger".init("hostmanager"); local hosts = prosody.hosts; @@ -24,11 +22,12 @@ end local incoming_s2s = _G.prosody.incoming_s2s; local core_route_stanza = _G.prosody.core_route_stanza; -local pairs, select, rawget = pairs, select, rawget; +local pairs, rawget = pairs, rawget; local tostring, type = tostring, type; local setmetatable = setmetatable; local _ENV = nil; +-- luacheck: std none local host_mt = { } function host_mt:__tostring() @@ -71,13 +70,6 @@ end prosody_events.add_handler("server-starting", load_enabled_hosts); local function host_send(stanza) - local name, stanza_type = stanza.name, stanza.attr.type; - if stanza_type == "error" or (name == "iq" and stanza_type == "result") then - local dest_host_name = select(2, jid_split(stanza.attr.to)); - local dest_host = hosts[dest_host_name] or { type = "unknown" }; - log("warn", "Unhandled response sent to %s host %s: %s", dest_host.type, dest_host_name, tostring(stanza)); - return; - end core_route_stanza(nil, stanza); end diff --git a/core/loggingmanager.lua b/core/loggingmanager.lua index 004f4c3b..cfa8246a 100644 --- a/core/loggingmanager.lua +++ b/core/loggingmanager.lua @@ -5,7 +5,6 @@ -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- --- luacheck: globals log prosody.log local format = require "util.format".format; local setmetatable, rawset, pairs, ipairs, type = @@ -18,12 +17,9 @@ local getstyle, getstring = require "util.termcolours".getstyle, require "util.t local config = require "core.configmanager"; local logger = require "util.logger"; -local prosody = prosody; - -_G.log = logger.init("general"); -prosody.log = logger.init("general"); local _ENV = nil; +-- luacheck: std none -- The log config used if none specified in the config file (see reload_logging for initialization) local default_logging; @@ -154,13 +150,8 @@ local function reload_logging() for name, sink_maker in pairs(old_sink_types) do log_sink_types[name] = sink_maker; end - - prosody.events.fire_event("logging-reloaded"); end -reload_logging(); -prosody.events.add_handler("config-reloaded", reload_logging); - --- Definition of built-in logging sinks --- -- Null sink, must enter log_sink_types *first* diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 7d954c1f..10f9f04d 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -6,7 +6,6 @@ -- COPYING file in the source package for more information. -- -local config = require "core.configmanager"; local array = require "util.array"; local set = require "util.set"; local it = require "util.iterators"; @@ -14,15 +13,15 @@ local logger = require "util.logger"; local pluginloader = require "util.pluginloader"; local timer = require "util.timer"; local resolve_relative_path = require"util.paths".resolve_relative_path; -local measure = require "core.statsmanager".measure; local st = require "util.stanza"; local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; local error, setmetatable, type = error, setmetatable, type; local ipairs, pairs, select = ipairs, pairs, select; -local unpack = table.unpack or unpack; --luacheck: ignore 113 local tonumber, tostring = tonumber, tostring; local require = require; +local pack = table.pack or function(...) return {n=select("#",...), ...}; end -- table.pack is only in 5.2 +local unpack = table.unpack or unpack; --luacheck: ignore 113 -- renamed in 5.2 local prosody = prosody; local hosts = prosody.hosts; @@ -70,20 +69,6 @@ end function api:add_extension(data) self:add_item("extension", data); end -function api:has_feature(xmlns) - for _, feature in ipairs(self:get_host_items("feature")) do - if feature == xmlns then return true; end - end - return false; -end -function api:has_identity(category, identity_type, name) - for _, id in ipairs(self:get_host_items("identity")) do - if id.category == category and id.type == identity_type and id.name == name then - return true; - end - end - return false; -end function api:fire_event(...) return (hosts[self.host] or prosody).events.fire_event(...); @@ -144,6 +129,9 @@ end function api:depends(name) local modulemanager = require"core.modulemanager"; + if self:get_option_inherited_set("modules_disabled", {}):contains(name) then + error("Dependency on disabled module mod_"..name); + end if not self.dependencies then self.dependencies = {}; self:hook("module-reloaded", function (event) @@ -176,36 +164,36 @@ function api:depends(name) return mod; end --- Returns one or more shared tables at the specified virtual paths --- Intentionally does not allow the table at a path to be _set_, it --- is auto-created if it does not exist. -function api:shared(...) - if not self.shared_data then self.shared_data = {}; end - local paths = { n = select("#", ...), ... }; - local data_array = {}; - local default_path_components = { self.host, self.name }; - for i = 1, paths.n do - local path = paths[i]; - if path:sub(1,1) ~= "/" then -- Prepend default components - local n_components = select(2, path:gsub("/", "%1")); - path = (n_components<#default_path_components and "/" or "") - ..t_concat(default_path_components, "/", 1, #default_path_components-n_components).."/"..path; - end - local shared = shared_data[path]; - if not shared then - shared = {}; - if path:match("%-cache$") then - setmetatable(shared, { __mode = "kv" }); - end - shared_data[path] = shared; +local function get_shared_table_from_path(module, tables, path) + if path:sub(1,1) ~= "/" then -- Prepend default components + local default_path_components = { module.host, module.name }; + local n_components = select(2, path:gsub("/", "%1")); + path = (n_components<#default_path_components and "/" or "") + ..t_concat(default_path_components, "/", 1, #default_path_components-n_components).."/"..path; + end + local shared = tables[path]; + if not shared then + shared = {}; + if path:match("%-cache$") then + setmetatable(shared, { __mode = "kv" }); end - t_insert(data_array, shared); - self.shared_data[path] = shared; + tables[path] = shared; end - return unpack(data_array); + return shared; +end + +-- Returns a shared table at the specified virtual path +-- Intentionally does not allow the table to be _set_, it +-- is auto-created if it does not exist. +function api:shared(path) + if not self.shared_data then self.shared_data = {}; end + local shared = get_shared_table_from_path(self, shared_data, path); + self.shared_data[path] = shared; + return shared; end function api:get_option(name, default_value) + local config = require "core.configmanager"; local value = config.get(self.host, name); if value == nil then value = default_value; @@ -299,7 +287,7 @@ end function api:get_option_path(name, default, parent) if parent == nil then - parent = parent or self:get_directory(); + parent = self:get_directory(); elseif prosody.paths[parent] then parent = prosody.paths[parent]; end @@ -377,15 +365,33 @@ function api:broadcast(jids, stanza, iter) for jid in (iter or it.values)(jids) do local new_stanza = st.clone(stanza); new_stanza.attr.to = jid; - core_post_stanza(hosts[self.host], new_stanza); + self:send(new_stanza); end end -function api:add_timer(delay, callback) - return timer.add_task(delay, function (t) - if self.loaded == false then return; end - return callback(t); - end); +local timer_methods = { } +local timer_mt = { + __index = timer_methods; +} +function timer_methods:stop( ) + timer.stop(self.id); +end +timer_methods.disarm = timer_methods.stop +function timer_methods:reschedule(delay) + timer.reschedule(self.id, delay) +end + +local function timer_callback(now, id, t) --luacheck: ignore 212/id + if t.module_env.loaded == false then return; end + return t.callback(now, unpack(t, 1, t.n)); +end + +function api:add_timer(delay, callback, ...) + local t = pack(...) + t.module_env = self; + t.callback = callback; + t.id = timer.add_task(delay, timer_callback, t); + return setmetatable(t, timer_mt); end local path_sep = package.config:sub(1,1); @@ -403,6 +409,7 @@ function api:open_store(name, store_type) end function api:measure(name, stat_type) + local measure = require "core.statsmanager".measure; return measure(stat_type, "/"..self.host.."/mod_"..self.name.."/"..name); end diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 771f6fb1..17602459 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -15,21 +15,13 @@ local set = require "util.set"; local new_multitable = require "util.multitable".new; local api = require "core.moduleapi"; -- Module API container -local hosts = hosts; local prosody = prosody; +local hosts = prosody.hosts; -local xpcall = xpcall; -local setmetatable, rawget = setmetatable, rawget; -local ipairs, pairs, type, tostring, t_insert = ipairs, pairs, type, tostring, table.insert; - +local xpcall = require "util.xpcall".xpcall; local debug_traceback = debug.traceback; -local select = select; -local unpack = table.unpack or unpack; --luacheck: ignore 113 -local pcall = function(f, ...) - local n = select("#", ...); - local params = {...}; - return xpcall(function() return f(unpack(params, 1, n)) end, function(e) return tostring(e).."\n"..debug_traceback(); end); -end +local setmetatable, rawget = setmetatable, rawget; +local ipairs, pairs, type, t_insert = ipairs, pairs, type, table.insert; local autoload_modules = {prosody.platform, "presence", "message", "iq", "offline", "c2s", "s2s", "s2s_auth_certs"}; local component_inheritable_modules = {"tls", "saslauth", "dialback", "iq", "s2s"}; @@ -38,6 +30,7 @@ local component_inheritable_modules = {"tls", "saslauth", "dialback", "iq", "s2s local _G = _G; local _ENV = nil; +-- luacheck: std none local load_modules_for_host, load, unload, reload, get_module, get_items; local get_modules, is_loaded, module_has_method, call_module_method; @@ -45,8 +38,8 @@ local get_modules, is_loaded, module_has_method, call_module_method; -- [host] = { [module] = module_env } local modulemap = { ["*"] = {} }; --- Load modules when a host is activated -function load_modules_for_host(host) +-- Get the list of modules to be loaded on a host +local function get_modules_for_host(host) local component = config.get(host, "component_module"); local global_modules_enabled = config.get("*", "modules_enabled"); @@ -70,8 +63,16 @@ function load_modules_for_host(host) modules:add("admin_telnet"); end - if component then - load(host, component); + return modules, component; +end + +-- Load modules when a host is activated +function load_modules_for_host(host) + local modules, component_module = get_modules_for_host(host); + + -- Ensure component module is loaded first + if component_module then + load(host, component_module); end for module in modules do load(host, module); @@ -174,7 +175,7 @@ local function do_load_module(host, module_name, state) api_instance.path = err; modulemap[host][module_name] = pluginenv; - local ok, err = pcall(mod); + local ok, err = xpcall(mod, debug_traceback); if ok then -- Call module's "load" if module_has_method(pluginenv, "load") then @@ -316,13 +317,14 @@ end function call_module_method(module, method, ...) local f = rawget(module.module, method); if type(f) == "function" then - return pcall(f, ...); + return xpcall(f, debug_traceback, ...); else return false, "no-such-method"; end end return { + get_modules_for_host = get_modules_for_host; load_modules_for_host = load_modules_for_host; load = load; unload = unload; diff --git a/core/portmanager.lua b/core/portmanager.lua index 5b6476f3..1ed37da0 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -15,6 +15,7 @@ local prosody = prosody; local fire_event = prosody.events.fire_event; local _ENV = nil; +-- luacheck: std none --- Config diff --git a/core/rostermanager.lua b/core/rostermanager.lua index 65be0de0..61b08002 100644 --- a/core/rostermanager.lua +++ b/core/rostermanager.lua @@ -11,11 +11,13 @@ local log = require "util.logger".init("rostermanager"); +local new_id = require "util.id".short; + local pairs = pairs; local tostring = tostring; local type = type; -local hosts = hosts; +local hosts = prosody.hosts; local bare_sessions = prosody.bare_sessions; local um_user_exists = require "core.usermanager".user_exists; @@ -23,6 +25,7 @@ local st = require "util.stanza"; local storagemanager = require "core.storagemanager"; local _ENV = nil; +-- luacheck: std none local save_roster; -- forward declaration @@ -60,7 +63,7 @@ local function roster_push(username, host, jid) local roster = jid and hosts[host] and hosts[host].sessions[username] and hosts[host].sessions[username].roster; if roster then local item = hosts[host].sessions[username].roster[jid]; - local stanza = st.iq({type="set"}); + local stanza = st.iq({type="set", id=new_id()}); stanza:tag("query", {xmlns = "jabber:iq:roster", ver = tostring(roster[false].version or "1") }); if item then stanza:tag("item", {jid = jid, subscription = item.subscription, name = item.name, ask = item.ask}); diff --git a/core/s2smanager.lua b/core/s2smanager.lua index d84572f3..58269c49 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -17,12 +17,13 @@ local logger_init = require "util.logger".init; local log = logger_init("s2smanager"); local prosody = _G.prosody; -incoming_s2s = {}; +local incoming_s2s = {}; +_G.incoming_s2s = incoming_s2s; prosody.incoming_s2s = incoming_s2s; -local incoming_s2s = incoming_s2s; local fire_event = prosody.events.fire_event; local _ENV = nil; +-- luacheck: std none local function new_incoming(conn) local session = { conn = conn, type = "s2sin_unauthed", direction = "incoming", hosts = {} }; @@ -64,6 +65,7 @@ local function retire_session(session, reason) function session.send(data) log("debug", "Discarding data sent to resting session: %s", tostring(data)); end function session.data(data) log("debug", "Discarding data received from resting session: %s", tostring(data)); end + session.thread = { run = function (_, data) return session.data(data) end }; session.sends2s = session.send; return setmetatable(session, resting_session); end diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index bdaafcb6..2843001a 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -10,7 +10,7 @@ local tostring, setmetatable = tostring, setmetatable; local pairs, next= pairs, next; -local hosts = hosts; +local hosts = prosody.hosts; local full_sessions = prosody.full_sessions; local bare_sessions = prosody.bare_sessions; @@ -20,12 +20,13 @@ local rm_load_roster = require "core.rostermanager".load_roster; local config_get = require "core.configmanager".get; local resourceprep = require "util.encodings".stringprep.resourceprep; local nodeprep = require "util.encodings".stringprep.nodeprep; -local uuid_generate = require "util.uuid".generate; +local generate_identifier = require "util.id".short; local initialize_filters = require "util.filters".initialize; local gettime = require "socket".gettime; local _ENV = nil; +-- luacheck: std none local function new_session(conn) local session = { conn = conn, type = "c2s_unauthed", conntime = gettime() }; @@ -74,6 +75,7 @@ local function retire_session(session) function session.send(data) log("debug", "Discarding data sent to resting session: %s", tostring(data)); return false; end function session.data(data) log("debug", "Discarding data received from resting session: %s", tostring(data)); end + session.thread = { run = function (_, data) return session.data(data) end }; return setmetatable(session, resting_session); end @@ -137,7 +139,7 @@ local function bind_resource(session, resource) end resource = resourceprep(resource); - resource = resource ~= "" and resource or uuid_generate(); + resource = resource ~= "" and resource or generate_identifier(); --FIXME: Randomly-generated resources must be unique per-user, and never conflict with existing if not hosts[session.host].sessions[session.username] then @@ -151,7 +153,7 @@ local function bind_resource(session, resource) local policy = config_get(session.host, "conflict_resolve"); local increment; if policy == "random" then - resource = uuid_generate(); + resource = generate_identifier(); increment = true; elseif policy == "increment" then increment = true; -- TODO ping old resource diff --git a/core/stanza_router.lua b/core/stanza_router.lua index 4caa89b6..f5a34f59 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -19,16 +19,6 @@ local bare_sessions = _G.prosody.bare_sessions; local core_post_stanza, core_process_stanza, core_route_stanza; -function deprecated_warning(f) - _G[f] = function(...) - log("warn", "Using the global %s() is deprecated, use module:send() or prosody.%s(). %s", f, f, debug.traceback()); - return prosody[f](...); - end -end -deprecated_warning"core_post_stanza"; -deprecated_warning"core_process_stanza"; -deprecated_warning"core_route_stanza"; - local valid_stanzas = { message = true, presence = true, iq = true }; local function handle_unhandled_stanza(host, origin, stanza) --luacheck: ignore 212/host local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns or "jabber:client", origin.type; diff --git a/core/storagemanager.lua b/core/storagemanager.lua index c93438af..dea71733 100644 --- a/core/storagemanager.lua +++ b/core/storagemanager.lua @@ -1,17 +1,21 @@ local type, pairs = type, pairs; local setmetatable = setmetatable; +local rawset = rawset; local config = require "core.configmanager"; local datamanager = require "util.datamanager"; local modulemanager = require "core.modulemanager"; local multitable = require "util.multitable"; -local hosts = hosts; local log = require "util.logger".init("storagemanager"); +local async = require "util.async"; +local debug = debug; local prosody = prosody; +local hosts = prosody.hosts; local _ENV = nil; +-- luacheck: std none local olddm = {}; -- maintain old datamanager, for backwards compatibility for k,v in pairs(datamanager) do olddm[k] = v; end @@ -28,8 +32,34 @@ local null_storage_driver = setmetatable( } ); +local async_check = config.get("*", "storage_async_check") == true; + local stores_available = multitable.new(); +local function check_async_wrapper(event) + local store = event.store; + event.store = setmetatable({}, { + __index = function (t, method_name) + local original_method = store[method_name]; + if type(original_method) ~= "function" then + if original_method then + rawset(t, method_name, original_method); + end + return original_method; + end + local wrapped_method = function (...) + if not async.ready() then + log("warn", "ASYNC-01: Attempt to access storage outside async context, " + .."see https://prosody.im/doc/developers/async - %s", debug.traceback()); + end + return original_method(...); + end + rawset(t, method_name, wrapped_method); + return wrapped_method; + end; + }); +end + local function initialize_host(host) local host_session = hosts[host]; host_session.events.add_handler("item-added/storage-provider", function (event) @@ -41,6 +71,9 @@ local function initialize_host(host) local item = event.item; stores_available:set(host, item.name, nil); end); + if async_check then + host_session.events.add_handler("store-opened", check_async_wrapper); + end end prosody.events.add_handler("host-activated", initialize_host, 101); @@ -137,7 +170,7 @@ local map_shim_mt = { }; } -local open; +local open; -- forward declaration local function create_map_shim(host, store) local keyval_store, err = open(host, store, "keyval"); diff --git a/core/usermanager.lua b/core/usermanager.lua index f795e8ae..bb5669cf 100644 --- a/core/usermanager.lua +++ b/core/usermanager.lua @@ -13,17 +13,18 @@ local ipairs = ipairs; local jid_bare = require "util.jid".bare; local jid_prep = require "util.jid".prep; local config = require "core.configmanager"; -local hosts = hosts; local sasl_new = require "util.sasl".new; local storagemanager = require "core.storagemanager"; local prosody = _G.prosody; +local hosts = prosody.hosts; local setmetatable = setmetatable; local default_provider = "internal_plain"; local _ENV = nil; +-- luacheck: std none local function new_null_provider() local function dummy() return nil, "method not implemented"; end; |