From 9be7bd1055aabdbbc663005ad11bc4b9cc1215f2 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Sat, 22 Oct 2011 18:29:23 +0200 Subject: s2smanager, xmppserver_listener: Support for connecting to other servers via IPv6 --- core/s2smanager.lua | 143 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 37 deletions(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 974b2f4f..c7eb9578 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -16,8 +16,8 @@ local socket = require "socket"; local format = string.format; local t_insert, t_sort = table.insert, table.sort; local get_traceback = debug.traceback; -local tostring, pairs, ipairs, getmetatable, newproxy, error, tonumber, setmetatable - = tostring, pairs, ipairs, getmetatable, newproxy, error, tonumber, setmetatable; +local tostring, pairs, ipairs, getmetatable, newproxy, next, error, tonumber, setmetatable + = tostring, pairs, ipairs, getmetatable, newproxy, next, error, tonumber, setmetatable; local idna_to_ascii = require "util.encodings".idna.to_ascii; local connlisteners_get = require "net.connlisteners".get; @@ -28,6 +28,8 @@ local st = require "stanza"; local stanza = st.stanza; local nameprep = require "util.encodings".stringprep.nameprep; local cert_verify_identity = require "util.x509".verify_identity; +local new_ip = require "util.ip".new_ip; +local rfc3484_dest = require "util.rfc3484".destination; local fire_event = prosody.events.fire_event; local uuid_gen = require "util.uuid".generate; @@ -43,6 +45,7 @@ local config = require "core.configmanager"; local connect_timeout = config.get("*", "core", "s2s_timeout") or 60; local dns_timeout = config.get("*", "core", "dns_timeout") or 15; local max_dns_depth = config.get("*", "core", "dns_max_depth") or 3; +local sources; dns.settimeout(dns_timeout); @@ -265,6 +268,8 @@ function attempt_connection(host_session, err) end, "_xmpp-server._tcp."..connect_host..".", "SRV"); return true; -- Attempt in progress + elseif host_session.ip_hosts then + return try_connect(host_session, connect_host, connect_port, err); elseif host_session.srv_hosts and #host_session.srv_hosts > host_session.srv_choice then -- Not our first attempt, and we also have SRV host_session.srv_choice = host_session.srv_choice + 1; local srv_choice = host_session.srv_hosts[host_session.srv_choice]; @@ -285,54 +290,118 @@ function attempt_connection(host_session, err) return try_connect(host_session, connect_host, connect_port); end -function try_connect(host_session, connect_host, connect_port) +function try_next_ip(host_session, connect_port) + host_session.connecting = nil; + host_session.ip_choice = host_session.ip_choice + 1; + local ip = host_session.ip_hosts[host_session.ip_choice]; + local ok, err= make_connect(host_session, ip, connect_port); + if not ok then + if not attempt_connection(host_session, err or "closed") then + err = err and (": "..err) or ""; + destroy_session(host_session, "Connection failed"..err); + end + end +end + +function try_connect(host_session, connect_host, connect_port, err) host_session.connecting = true; - local handle; - handle = adns.lookup(function (reply, err) - handle = nil; - host_session.connecting = nil; - - -- COMPAT: This is a compromise for all you CNAME-(ab)users :) - if not (reply and reply[#reply] and reply[#reply].a) then - local count = max_dns_depth; - reply = dns.peek(connect_host, "CNAME", "IN"); - while count > 0 and reply and reply[#reply] and not reply[#reply].a and reply[#reply].cname do - log("debug", "Looking up %s (DNS depth is %d)", tostring(reply[#reply].cname), count); - reply = dns.peek(reply[#reply].cname, "A", "IN") or dns.peek(reply[#reply].cname, "CNAME", "IN"); - count = count - 1; + + if not err then + local IPs = {}; + host_session.ip_hosts = IPs; + local handle4, handle6; + local has_other = false; + + if not sources then + sources = {}; + local cfg_sources = connlisteners_get("xmppserver").default_interface or config.get("*", "core", "interface"); + for i, source in ipairs(cfg_sources) do + if source == "*" then + sources[i] = new_ip("0.0.0.0", "IPv4"); + else + sources[i] = new_ip(source, (source:find(":") and "IPv6") or "IPv4"); + end end end - -- end of CNAME resolving - - if reply and reply[#reply] and reply[#reply].a then - log("debug", "DNS reply for %s gives us %s", connect_host, reply[#reply].a); - local ok, err = make_connect(host_session, reply[#reply].a, connect_port); - if not ok then - if not attempt_connection(host_session, err or "closed") then - err = err and (": "..err) or ""; - destroy_session(host_session, "Connection failed"..err); + + handle4 = adns.lookup(function (reply, err) + handle4 = nil; + + -- COMPAT: This is a compromise for all you CNAME-(ab)users :) + if not (reply and reply[#reply] and reply[#reply].a) then + local count = max_dns_depth; + reply = dns.peek(connect_host, "CNAME", "IN"); + while count > 0 and reply and reply[#reply] and not reply[#reply].a and reply[#reply].cname do + log("debug", "Looking up %s (DNS depth is %d)", tostring(reply[#reply].cname), count); + reply = dns.peek(reply[#reply].cname, "A", "IN") or dns.peek(reply[#reply].cname, "CNAME", "IN"); + count = count - 1; end end - else - log("debug", "DNS lookup failed to get a response for %s", connect_host); - if not attempt_connection(host_session, "name resolution failed") then -- Retry if we can - log("debug", "No other records to try for %s - destroying", host_session.to_host); - err = err and (": "..err) or ""; - destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't + -- end of CNAME resolving + + if reply and reply[#reply] and reply[#reply].a then + for _, ip in ipairs(reply) do + log("debug", "DNS reply for %s gives us %s", connect_host, ip.a); + IPs[#IPs+1] = new_ip(ip.a, "IPv4"); + end + end + + if has_other then + rfc3484_dest(host_session.ip_hosts, sources); + host_session.ip_choice = 0; + try_next_ip(host_session, connect_port); + else + has_other = true; + end + end, connect_host, "A", "IN"); + + handle6 = adns.lookup(function (reply, err) + handle6 = nil; + + if reply and reply[#reply] and reply[#reply].aaaa then + for _, ip in ipairs(reply) do + log("debug", "DNS reply for %s gives us %s", connect_host, ip.aaaa); + IPs[#IPs+1] = new_ip(ip.aaaa, "IPv6"); + end end + + if has_other then + rfc3484_dest(host_session.ip_hosts, sources); + host_session.ip_choice = 0; + try_next_ip(host_session, connect_port); + else + has_other = true; + end + end, connect_host, "AAAA", "IN"); + + return true; + elseif host_session.ip_hosts and #host_session.ip_hosts > host_session.ip_choice then -- Not our first attempt, and we also have IPs left to try + try_next_ip(host_session, connect_port); + else + host_session.ip_hosts = nil; + if not attempt_connection(host_session, "out of IP addresses") then -- Retry if we can + log("debug", "No other records to try for %s - destroying", host_session.to_host); + err = err and (": "..err) or ""; + destroy_session(host_session, "Connecting failed"..err); -- End of the line, we can't + return false; end - end, connect_host, "A", "IN"); + end return true; end function make_connect(host_session, connect_host, connect_port) - (host_session.log or log)("info", "Beginning new connection attempt to %s (%s:%d)", host_session.to_host, connect_host, connect_port); + (host_session.log or log)("info", "Beginning new connection attempt to %s ([%s]:%d)", host_session.to_host, connect_host.addr, connect_port); -- Ok, we're going to try to connect local from_host, to_host = host_session.from_host, host_session.to_host; - local conn, handler = socket.tcp(); + local conn, handler; + if connect_host.proto == "IPv4" then + conn, handler = socket.tcp(); + else + conn, handler = socket.tcp6(); + end if not conn then log("warn", "Failed to create outgoing connection, system error: %s", handler); @@ -340,14 +409,14 @@ function make_connect(host_session, connect_host, connect_port) end conn:settimeout(0); - local success, err = conn:connect(connect_host, connect_port); + local success, err = conn:connect(connect_host.addr, connect_port); if not success and err ~= "timeout" then - log("warn", "s2s connect() to %s (%s:%d) failed: %s", host_session.to_host, connect_host, connect_port, err); + log("warn", "s2s connect() to %s (%s:%d) failed: %s", host_session.to_host, connect_host.addr, connect_port, err); return false, err; end local cl = connlisteners_get("xmppserver"); - conn = wrapclient(conn, connect_host, connect_port, cl, cl.default_mode or 1 ); + conn = wrapclient(conn, connect_host.addr, connect_port, cl, cl.default_mode or 1 ); host_session.conn = conn; local filter = initialize_filters(host_session); -- cgit v1.2.3 From a71b4036179108e3de89a8859f1e2d90f4407451 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Wed, 26 Oct 2011 02:03:33 +0200 Subject: s2smanager, net.dns: Fix handling for NXNAME and SRV target of "." --- core/s2smanager.lua | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index c7eb9578..b930ceab 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -246,6 +246,11 @@ function attempt_connection(host_session, err) for _, record in ipairs(answer) do t_insert(srv_hosts, record.srv); end + if #srv_hosts == 1 and srv_hosts[1].target == "." then + log("debug", to_host.." does not provide a XMPP service"); + destroy_session(host_session, err); -- Nothing to see here + return; + end t_sort(srv_hosts, compare_srv_priorities); local srv_choice = srv_hosts[1]; @@ -347,9 +352,19 @@ function try_connect(host_session, connect_host, connect_port, err) end if has_other then - rfc3484_dest(host_session.ip_hosts, sources); - host_session.ip_choice = 0; - try_next_ip(host_session, connect_port); + if #IPs > 0 then + rfc3484_dest(host_session.ip_hosts, sources); + host_session.ip_choice = 0; + try_next_ip(host_session, connect_port); + else + log("debug", "DNS lookup failed to get a response for %s", connect_host); + host_session.ip_hosts = nil; + if not attempt_connection(host_session, "name resolution failed") then -- Retry if we can + log("debug", "No other records to try for %s - destroying", host_session.to_host); + err = err and (": "..err) or ""; + destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't + end + end else has_other = true; end @@ -366,9 +381,19 @@ function try_connect(host_session, connect_host, connect_port, err) end if has_other then - rfc3484_dest(host_session.ip_hosts, sources); - host_session.ip_choice = 0; - try_next_ip(host_session, connect_port); + if #IPs > 0 then + rfc3484_dest(host_session.ip_hosts, sources); + host_session.ip_choice = 0; + try_next_ip(host_session, connect_port); + else + log("debug", "DNS lookup failed to get a response for %s", connect_host); + host_session.ip_hosts = nil; + if not attempt_connection(host_session, "name resolution failed") then -- Retry if we can + log("debug", "No other records to try for %s - destroying", host_session.to_host); + err = err and (": "..err) or ""; + destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't + end + end else has_other = true; end -- cgit v1.2.3 From a6418c6df20dd9ad4c906c5ee7ef318f2c4219c2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 22 Nov 2011 17:56:52 +0000 Subject: loggingmanager: Remove unused 'critical' level --- core/loggingmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/loggingmanager.lua b/core/loggingmanager.lua index 88f2bbbf..426425c1 100644 --- a/core/loggingmanager.lua +++ b/core/loggingmanager.lua @@ -41,7 +41,7 @@ local logging_config; local apply_sink_rules; local log_sink_types = setmetatable({}, { __newindex = function (t, k, v) rawset(t, k, v); apply_sink_rules(k); end; }); local get_levels; -local logging_levels = { "debug", "info", "warn", "error", "critical" } +local logging_levels = { "debug", "info", "warn", "error" } -- Put a rule into action. Requires that the sink type has already been registered. -- This function is called automatically when a new sink type is added [see apply_sink_rules()] -- cgit v1.2.3 From 5a887a9e66c45c82c375c8abfcc4b43a410cac43 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 28 Nov 2011 14:30:12 +0000 Subject: s2smanager: Use config over xmppserver's default interface --- core/s2smanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index b930ceab..77a1b040 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -319,7 +319,7 @@ function try_connect(host_session, connect_host, connect_port, err) if not sources then sources = {}; - local cfg_sources = connlisteners_get("xmppserver").default_interface or config.get("*", "core", "interface"); + local cfg_sources = config.get("*", "core", "interface") or connlisteners_get("xmppserver").default_interface; for i, source in ipairs(cfg_sources) do if source == "*" then sources[i] = new_ip("0.0.0.0", "IPv4"); -- cgit v1.2.3 From d4584664f787d8e3d0c92979e34b575f37e16df8 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Wed, 7 Dec 2011 23:37:56 +0100 Subject: s2smanager: Store port specified by SRV records --- core/s2smanager.lua | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 77a1b040..08c1543b 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -295,11 +295,11 @@ function attempt_connection(host_session, err) return try_connect(host_session, connect_host, connect_port); end -function try_next_ip(host_session, connect_port) +function try_next_ip(host_session) host_session.connecting = nil; host_session.ip_choice = host_session.ip_choice + 1; local ip = host_session.ip_hosts[host_session.ip_choice]; - local ok, err= make_connect(host_session, ip, connect_port); + local ok, err= make_connect(host_session, ip.ip, ip.port); if not ok then if not attempt_connection(host_session, err or "closed") then err = err and (": "..err) or ""; @@ -354,8 +354,11 @@ function try_connect(host_session, connect_host, connect_port, err) if has_other then if #IPs > 0 then rfc3484_dest(host_session.ip_hosts, sources); + for i = 1, #IPs do + IPs[i] = {ip = IPs[i], port = connect_port}; + end host_session.ip_choice = 0; - try_next_ip(host_session, connect_port); + try_next_ip(host_session); else log("debug", "DNS lookup failed to get a response for %s", connect_host); host_session.ip_hosts = nil; @@ -383,8 +386,11 @@ function try_connect(host_session, connect_host, connect_port, err) if has_other then if #IPs > 0 then rfc3484_dest(host_session.ip_hosts, sources); + for i = 1, #IPs do + IPs[i] = {ip = IPs[i], port = connect_port}; + end host_session.ip_choice = 0; - try_next_ip(host_session, connect_port); + try_next_ip(host_session); else log("debug", "DNS lookup failed to get a response for %s", connect_host); host_session.ip_hosts = nil; @@ -401,7 +407,7 @@ function try_connect(host_session, connect_host, connect_port, err) return true; elseif host_session.ip_hosts and #host_session.ip_hosts > host_session.ip_choice then -- Not our first attempt, and we also have IPs left to try - try_next_ip(host_session, connect_port); + try_next_ip(host_session); else host_session.ip_hosts = nil; if not attempt_connection(host_session, "out of IP addresses") then -- Retry if we can -- cgit v1.2.3 From 76628c7453e56d5e156214c142ca05f9908c0191 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 10 Dec 2011 17:21:19 +0000 Subject: configmanager: get(): Make section (core) optional (hurrah) --- core/configmanager.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core') diff --git a/core/configmanager.lua b/core/configmanager.lua index 85919492..e2253171 100644 --- a/core/configmanager.lua +++ b/core/configmanager.lua @@ -41,6 +41,9 @@ function getconfig() end function get(host, section, key) + if not key then + section, key = "core", section; + end local sec = config[host][section]; if sec then return sec[key]; -- cgit v1.2.3 From 568f00002d9de66b8026f99728158bfca86336b4 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 13 Dec 2011 13:34:21 +0000 Subject: modulemanager: Remove 'config' from module environments (no modules use it that I'm aware of) --- core/modulemanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 2d1eeb77..c4d95695 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -117,7 +117,7 @@ function load(host, module_name, config) end local _log = logger.init(host..":"..module_name); - local api_instance = setmetatable({ name = module_name, host = host, path = err, config = config, _log = _log, log = function (self, ...) return _log(...); end }, { __index = api }); + local api_instance = setmetatable({ name = module_name, host = host, path = err, _log = _log, log = function (self, ...) return _log(...); end }, { __index = api }); local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); api_instance.environment = pluginenv; -- cgit v1.2.3 From 8143f5ff1078d206364f661eeb04d8a071d34022 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 13 Dec 2011 15:40:37 +0000 Subject: s2smanager: Remove unused reference to modulemanager --- core/s2smanager.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 08c1543b..df5523e1 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -23,7 +23,6 @@ local idna_to_ascii = require "util.encodings".idna.to_ascii; local connlisteners_get = require "net.connlisteners".get; local initialize_filters = require "util.filters".initialize; local wrapclient = require "net.server".wrapclient; -local modulemanager = require "core.modulemanager"; local st = require "stanza"; local stanza = st.stanza; local nameprep = require "util.encodings".stringprep.nameprep; -- cgit v1.2.3 From c60f52cc4dcd079eb3a3f76d5fe998fd6644b8b6 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 13 Dec 2011 15:42:21 +0000 Subject: sessionmanager: Remove unused reference to modulemanager --- core/sessionmanager.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'core') diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 1de6c41a..b1ec819f 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -16,7 +16,6 @@ local hosts = hosts; local full_sessions = full_sessions; local bare_sessions = bare_sessions; -local modulemanager = require "core.modulemanager"; local logger = require "util.logger"; local log = logger.init("sessionmanager"); local error = error; -- cgit v1.2.3 From 06aa3c416e58c67413522dd379f834262ca1b2fd Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Wed, 14 Dec 2011 06:46:24 +0500 Subject: s2smanager: Don't throw an error when the "interface" config option is a string (which it is by default). --- core/s2smanager.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index df5523e1..240b9ba8 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -319,6 +319,9 @@ function try_connect(host_session, connect_host, connect_port, err) if not sources then sources = {}; local cfg_sources = config.get("*", "core", "interface") or connlisteners_get("xmppserver").default_interface; + if type(cfg_sources) == "string" then + cfg_sources = { cfg_sources }; + end for i, source in ipairs(cfg_sources) do if source == "*" then sources[i] = new_ip("0.0.0.0", "IPv4"); -- cgit v1.2.3 From 5f61bd217ce1a516cdb0817e10a8d15966734e0e Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Wed, 14 Dec 2011 07:19:58 +0500 Subject: usermanager: Prep admin JIDs (fixes issue#276). --- core/usermanager.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/usermanager.lua b/core/usermanager.lua index 0152afd7..9e5a016c 100644 --- a/core/usermanager.lua +++ b/core/usermanager.lua @@ -11,6 +11,7 @@ local log = require "util.logger".init("usermanager"); local type = type; 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; @@ -97,6 +98,7 @@ end function is_admin(jid, host) if host and not hosts[host] then return false; end + if type(jid) ~= "string" then return false; end local is_admin; jid = jid_bare(jid); @@ -108,7 +110,7 @@ function is_admin(jid, host) if host_admins and host_admins ~= global_admins then if type(host_admins) == "table" then for _,admin in ipairs(host_admins) do - if admin == jid then + if jid_prep(admin) == jid then is_admin = true; break; end @@ -121,7 +123,7 @@ function is_admin(jid, host) if not is_admin and global_admins then if type(global_admins) == "table" then for _,admin in ipairs(global_admins) do - if admin == jid then + if jid_prep(admin) == jid then is_admin = true; break; end -- cgit v1.2.3 From d9a74e419644cd8caa619cc7f544256ce1ca9008 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 16 Dec 2011 16:01:59 +0000 Subject: hostmanager: Add send() method to hosts --- core/hostmanager.lua | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'core') diff --git a/core/hostmanager.lua b/core/hostmanager.lua index 9e74cd6b..0dd1d426 100644 --- a/core/hostmanager.lua +++ b/core/hostmanager.lua @@ -53,6 +53,17 @@ end prosody_events.add_handler("server-starting", load_enabled_hosts); +local function host_send(stanza) + local name, type = stanza.name, stanza.attr.type; + if type == "error" or (name == "iq" and 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 + function activate(host, host_config) if hosts[host] then return nil, "The host "..host.." is already activated"; end host_config = host_config or configmanager.getconfig()[host]; @@ -63,6 +74,7 @@ function activate(host, host_config) events = events_new(); dialback_secret = configmanager.get(host, "core", "dialback_secret") or uuid_gen(); disallow_s2s = configmanager.get(host, "core", "disallow_s2s"); + send = host_send; }; if not host_config.core.component_module then -- host host_session.type = "local"; -- cgit v1.2.3 From f5b0bf49fd4c6cc8ca82e356332620e9eb50cfb0 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 20 Dec 2011 17:36:38 +0000 Subject: s2smanager: Fix missing import of 'type' (thanks darkrain) --- core/s2smanager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 240b9ba8..f44921c3 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -16,8 +16,8 @@ local socket = require "socket"; local format = string.format; local t_insert, t_sort = table.insert, table.sort; local get_traceback = debug.traceback; -local tostring, pairs, ipairs, getmetatable, newproxy, next, error, tonumber, setmetatable - = tostring, pairs, ipairs, getmetatable, newproxy, next, error, tonumber, setmetatable; +local tostring, pairs, ipairs, getmetatable, newproxy, type, error, tonumber, setmetatable + = tostring, pairs, ipairs, getmetatable, newproxy, type, error, tonumber, setmetatable; local idna_to_ascii = require "util.encodings".idna.to_ascii; local connlisteners_get = require "net.connlisteners".get; -- cgit v1.2.3 From 36542853efea8ca4a4767996408e46b1657ec93e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 18:41:55 +0000 Subject: modulemanager: Move in-module API functions to core.moduleapi (half the file size, yay) --- core/moduleapi.lua | 239 +++++++++++++++++++++++++++++++++++++++++++++++++ core/modulemanager.lua | 213 +------------------------------------------ 2 files changed, 240 insertions(+), 212 deletions(-) create mode 100644 core/moduleapi.lua (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua new file mode 100644 index 00000000..ee960709 --- /dev/null +++ b/core/moduleapi.lua @@ -0,0 +1,239 @@ +-- Prosody IM +-- Copyright (C) 2008-2012 Matthew Wild +-- Copyright (C) 2008-2012 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + +local config = require "core.configmanager"; +local modulemanager = require "modulemanager"; +local array = require "util.array"; +local set = require "util.set"; +local logger = require "util.logger"; +local pluginloader = require "util.pluginloader"; + +local multitable_new = require "util.multitable".new; + +local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; +local error, setmetatable, setfenv, type = error, setmetatable, setfenv, type; +local ipairs, pairs, select, unpack = ipairs, pairs, select, unpack; +local tonumber, tostring = tonumber, tostring; + +local prosody = prosody; +local hosts = prosody.hosts; + +-- Registry of shared module data +local shared_data = setmetatable({}, { __mode = "v" }); + +local NULL = {}; + +local 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 + +function api:get_host_type() + return hosts[self.host].type; +end + +function api:set_global() + self.host = "*"; + -- Update the logger + local _log = logger.init("mod_"..self.name); + self.log = function (self, ...) return _log(...); end; + self._log = _log; +end + +function api:add_feature(xmlns) + self:add_item("feature", xmlns); +end +function api:add_identity(category, type, name) + self:add_item("identity", {category = category, type = type, name = name}); +end +function api:add_extension(data) + self:add_item("extension", data); +end + +function api:fire_event(...) + return (hosts[self.host] or prosody).events.fire_event(...); +end + +function api:hook(event, handler, priority) + hooks:set(self.host, self.name, event, handler, true); + (hosts[self.host] or prosody).events.add_handler(event, handler, priority); +end + +function api:hook_global(event, handler, priority) + hooks:set("*", self.name, event, handler, true); + prosody.events.add_handler(event, handler, priority); +end + +function api:hook_stanza(xmlns, name, handler, priority) + if not handler and type(name) == "function" then + -- If only 2 options then they specified no xmlns + xmlns, name, handler, priority = nil, xmlns, name, handler; + elseif not (handler and name) then + self:log("warn", "Error: Insufficient parameters to module:hook_stanza()"); + return; + end + return self:hook("stanza/"..(xmlns and (xmlns..":") or "")..name, function (data) return handler(data.origin, data.stanza, data); end, priority); +end + +function api:require(lib) + local f, n = pluginloader.load_code(self.name, lib..".lib.lua"); + if not f then + f, n = pluginloader.load_code(lib, lib..".lib.lua"); + end + if not f then error("Failed to load plugin library '"..lib.."', error: "..n); end -- FIXME better error message + setfenv(f, self.environment); + return f(); +end + +function api:get_option(name, default_value) + local value = config.get(self.host, self.name, name); + if value == nil then + value = config.get(self.host, "core", name); + if value == nil then + value = default_value; + end + end + return value; +end + +function api:get_option_string(name, default_value) + local value = self:get_option(name, default_value); + if type(value) == "table" then + if #value > 1 then + self:log("error", "Config option '%s' does not take a list, using just the first item", name); + end + value = value[1]; + end + if value == nil then + return nil; + end + return tostring(value); +end + +function api:get_option_number(name, ...) + local value = self:get_option(name, ...); + if type(value) == "table" then + if #value > 1 then + self:log("error", "Config option '%s' does not take a list, using just the first item", name); + end + value = value[1]; + end + local ret = tonumber(value); + if value ~= nil and ret == nil then + self:log("error", "Config option '%s' not understood, expecting a number", name); + end + return ret; +end + +function api:get_option_boolean(name, ...) + local value = self:get_option(name, ...); + if type(value) == "table" then + if #value > 1 then + self:log("error", "Config option '%s' does not take a list, using just the first item", name); + end + value = value[1]; + end + if value == nil then + return nil; + end + local ret = value == true or value == "true" or value == 1 or nil; + if ret == nil then + ret = (value == false or value == "false" or value == 0); + if ret then + ret = false; + else + ret = nil; + end + end + if ret == nil then + self:log("error", "Config option '%s' not understood, expecting true/false", name); + end + return ret; +end + +function api:get_option_array(name, ...) + local value = self:get_option(name, ...); + + if value == nil then + return nil; + end + + if type(value) ~= "table" then + return array{ value }; -- Assume any non-list is a single-item list + end + + return array():append(value); -- Clone +end + +function api:get_option_set(name, ...) + local value = self:get_option_array(name, ...); + + if value == nil then + return nil; + end + + return set.new(value); +end + +local module_items = multitable_new(); +function api:add_item(key, value) + self.items = self.items or {}; + self.items[key] = self.items[key] or {}; + t_insert(self.items[key], value); + self:fire_event("item-added/"..key, {source = self, item = value}); +end +function api:remove_item(key, value) + local t = self.items and self.items[key] or NULL; + for i = #t,1,-1 do + if t[i] == value then + t_remove(self.items[key], i); + self:fire_event("item-removed/"..key, {source = self, item = value}); + return value; + end + end +end + +function api:get_host_items(key) + local result = {}; + for mod_name, module in pairs(modulemanager.get_modules(self.host)) do + module = module.module; + if module.items then + for _, item in ipairs(module.items[key] or NULL) do + t_insert(result, item); + end + end + end + for mod_name, module in pairs(modulemanager.get_modules("*")) do + module = module.module; + if module.items then + for _, item in ipairs(module.items[key] or NULL) do + t_insert(result, item); + end + end + end + return result; +end + +function api:handle_items(type, added_cb, removed_cb, existing) + self:hook("item-added/"..type, added_cb); + self:hook("item-removed/"..type, removed_cb); + if existing ~= false then + for _, item in ipairs(self:get_host_items(type)) do + added_cb({ item = item }); + end + end +end + +return api; diff --git a/core/modulemanager.lua b/core/modulemanager.lua index c4d95695..bbe24e32 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -45,8 +45,7 @@ local _G = _G; module "modulemanager" -api = {}; -local api = api; -- Module API container +local api = _G.require "core.moduleapi"; -- Module API container local modulemap = { ["*"] = {} }; @@ -253,214 +252,4 @@ function call_module_method(module, method, ...) end 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 - -function api:get_host_type() - return hosts[self.host].type; -end - -function api:set_global() - self.host = "*"; - -- Update the logger - local _log = logger.init("mod_"..self.name); - self.log = function (self, ...) return _log(...); end; - self._log = _log; -end - -function api:add_feature(xmlns) - self:add_item("feature", xmlns); -end -function api:add_identity(category, type, name) - self:add_item("identity", {category = category, type = type, name = name}); -end -function api:add_extension(data) - self:add_item("extension", data); -end - -function api:fire_event(...) - return (hosts[self.host] or prosody).events.fire_event(...); -end - -function api:hook(event, handler, priority) - hooks:set(self.host, self.name, event, handler, true); - (hosts[self.host] or prosody).events.add_handler(event, handler, priority); -end - -function api:hook_global(event, handler, priority) - hooks:set("*", self.name, event, handler, true); - prosody.events.add_handler(event, handler, priority); -end - -function api:hook_stanza(xmlns, name, handler, priority) - if not handler and type(name) == "function" then - -- If only 2 options then they specified no xmlns - xmlns, name, handler, priority = nil, xmlns, name, handler; - elseif not (handler and name) then - self:log("warn", "Error: Insufficient parameters to module:hook_stanza()"); - return; - end - return api.hook(self, "stanza/"..(xmlns and (xmlns..":") or "")..name, function (data) return handler(data.origin, data.stanza, data); end, priority); -end - -function api:require(lib) - local f, n = pluginloader.load_code(self.name, lib..".lib.lua"); - if not f then - f, n = pluginloader.load_code(lib, lib..".lib.lua"); - end - if not f then error("Failed to load plugin library '"..lib.."', error: "..n); end -- FIXME better error message - setfenv(f, self.environment); - return f(); -end - -function api:get_option(name, default_value) - local value = config.get(self.host, self.name, name); - if value == nil then - value = config.get(self.host, "core", name); - if value == nil then - value = default_value; - end - end - return value; -end - -function api:get_option_string(name, default_value) - local value = self:get_option(name, default_value); - if type(value) == "table" then - if #value > 1 then - self:log("error", "Config option '%s' does not take a list, using just the first item", name); - end - value = value[1]; - end - if value == nil then - return nil; - end - return tostring(value); -end - -function api:get_option_number(name, ...) - local value = self:get_option(name, ...); - if type(value) == "table" then - if #value > 1 then - self:log("error", "Config option '%s' does not take a list, using just the first item", name); - end - value = value[1]; - end - local ret = tonumber(value); - if value ~= nil and ret == nil then - self:log("error", "Config option '%s' not understood, expecting a number", name); - end - return ret; -end - -function api:get_option_boolean(name, ...) - local value = self:get_option(name, ...); - if type(value) == "table" then - if #value > 1 then - self:log("error", "Config option '%s' does not take a list, using just the first item", name); - end - value = value[1]; - end - if value == nil then - return nil; - end - local ret = value == true or value == "true" or value == 1 or nil; - if ret == nil then - ret = (value == false or value == "false" or value == 0); - if ret then - ret = false; - else - ret = nil; - end - end - if ret == nil then - self:log("error", "Config option '%s' not understood, expecting true/false", name); - end - return ret; -end - -function api:get_option_array(name, ...) - local value = self:get_option(name, ...); - - if value == nil then - return nil; - end - - if type(value) ~= "table" then - return array{ value }; -- Assume any non-list is a single-item list - end - - return array():append(value); -- Clone -end - -function api:get_option_set(name, ...) - local value = self:get_option_array(name, ...); - - if value == nil then - return nil; - end - - return set.new(value); -end - -local t_remove = _G.table.remove; -local module_items = multitable_new(); -function api:add_item(key, value) - self.items = self.items or {}; - self.items[key] = self.items[key] or {}; - t_insert(self.items[key], value); - self:fire_event("item-added/"..key, {source = self, item = value}); -end -function api:remove_item(key, value) - local t = self.items and self.items[key] or NULL; - for i = #t,1,-1 do - if t[i] == value then - t_remove(self.items[key], i); - self:fire_event("item-removed/"..key, {source = self, item = value}); - return value; - end - end -end - -function api:get_host_items(key) - local result = {}; - for mod_name, module in pairs(modulemap[self.host]) do - module = module.module; - if module.items then - for _, item in ipairs(module.items[key] or NULL) do - t_insert(result, item); - end - end - end - for mod_name, module in pairs(modulemap["*"]) do - module = module.module; - if module.items then - for _, item in ipairs(module.items[key] or NULL) do - t_insert(result, item); - end - end - end - return result; -end - -function api:handle_items(type, added_cb, removed_cb, existing) - self:hook("item-added/"..type, added_cb); - self:hook("item-removed/"..type, removed_cb); - if existing ~= false then - for _, item in ipairs(self:get_host_items(type)) do - added_cb({ item = item }); - end - end -end - return _M; -- cgit v1.2.3 From 184f681d3f1d8eef901e16f8d5bdc0c5a6c11edf Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 18:46:17 +0000 Subject: modulemanager: Some reorganisation. Only external change is (should be) that module-unloaded and module-loaded are no longer fired when reloading a module, the new event module-reloaded is fired instead. --- core/modulemanager.lua | 156 +++++++++++++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 62 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index bbe24e32..1846e0f0 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -90,7 +90,45 @@ end prosody_events.add_handler("host-activated", load_modules_for_host); -- -function load(host, module_name, config) +--- Private helpers --- + +local function do_unload_module(host, name) + local mod = get_module(host, name); + if not mod then return nil, "module-not-loaded"; end + + 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' on '%s': %s", name, host, err); + end + end + -- unhook event handlers hooked by module:hook + for event, handlers in pairs(hooks:get(host, name) or NULL) do + for handler in pairs(handlers or NULL) do + (hosts[host] or prosody).events.remove_handler(event, handler); + end + end + -- unhook event handlers hooked by module:hook_global + for event, handlers in pairs(hooks:get("*", name) or NULL) do + for handler in pairs(handlers or NULL) do + prosody.events.remove_handler(event, handler); + end + end + hooks:remove(host, name); + if mod.module.items then -- remove items + for key,t in pairs(mod.module.items) do + for i = #t,1,-1 do + local value = t[i]; + t[i] = nil; + hosts[host].events.fire_event("item-removed/"..key, {source = mod.module, item = value}); + end + end + end + modulemap[host][name] = nil; + return true; +end + +local function do_load_module(host, module_name) if not (host and module_name) then return nil, "insufficient-parameters"; elseif not hosts[host] then @@ -116,7 +154,9 @@ function load(host, module_name, config) end local _log = logger.init(host..":"..module_name); - local api_instance = setmetatable({ name = module_name, host = host, path = err, _log = _log, log = function (self, ...) return _log(...); end }, { __index = api }); + local api_instance = setmetatable({ name = module_name, host = host, path = err, + _log = _log, log = function (self, ...) return _log(...); end } + , { __index = api }); local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); api_instance.environment = pluginenv; @@ -125,11 +165,12 @@ function load(host, module_name, config) hosts[host].modules = modulemap[host]; modulemap[host][module_name] = pluginenv; - local success, err = pcall(mod); - if success then + local ok, err = pcall(mod); + if ok then + -- Call module's "load" if module_has_method(pluginenv, "load") then - success, err = call_module_method(pluginenv, "load"); - if not success then + ok, err = call_module_method(pluginenv, "load"); + if not ok then log("warn", "Error loading module '%s' on '%s': %s", module_name, host, err or "nil"); end end @@ -142,62 +183,12 @@ function load(host, module_name, config) end else log("error", "Error initializing module '%s' on '%s': %s", module_name, host, err or "nil"); + do_unload_module(api_instance.host, module_name); -- Ignore error, module may be partially-loaded end - if success then - (hosts[api_instance.host] or prosody).events.fire_event("module-loaded", { module = module_name, host = host }); - return true; - else -- load failed, unloading - unload(api_instance.host, module_name); - return nil, err; - end -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; + return ok and mod, err; end -function unload(host, name, ...) - local mod = get_module(host, name); - if not mod then return nil, "module-not-loaded"; end - - 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' on '%s': %s", name, host, err); - end - end - -- unhook event handlers hooked by module:hook - for event, handlers in pairs(hooks:get(host, name) or NULL) do - for handler in pairs(handlers or NULL) do - (hosts[host] or prosody).events.remove_handler(event, handler); - end - end - -- unhook event handlers hooked by module:hook_global - for event, handlers in pairs(hooks:get("*", name) or NULL) do - for handler in pairs(handlers or NULL) do - prosody.events.remove_handler(event, handler); - end - end - hooks:remove(host, name); - if mod.module.items then -- remove items - for key,t in pairs(mod.module.items) do - for i = #t,1,-1 do - local value = t[i]; - t[i] = nil; - hosts[host].events.fire_event("item-removed/"..key, {source = mod.module, item = value}); - end - end - end - modulemap[host][name] = nil; - (hosts[host] or prosody).events.fire_event("module-unloaded", { module = name, host = host }); - return true; -end - -function reload(host, name, ...) +local function do_reload_module(host, name) local mod = get_module(host, name); if not mod then return nil, "module-not-loaded"; end @@ -224,8 +215,8 @@ function reload(host, name, ...) end end - unload(host, name, ...); - local ok, err = load(host, name, ...); + do_unload_module(host, name); + local ok, err = do_load_module(host, name); if ok then mod = get_module(host, name); if module_has_method(mod, "restore") then @@ -234,11 +225,52 @@ function reload(host, name, ...) log("warn", "Error restoring module '%s' from '%s': %s", name, host, err); end end - return true; + end + return ok and mod, err; +end + +--- Public API --- + +-- Load a module and fire module-loaded event +function load(host, name) + local mod, err = do_load_module(host, name); + if mod then + (hosts[mod.host] or prosody).events.fire_event("module-loaded", { module = module_name, host = host }); + end + return mod, err; +end + +-- Unload a module and fire module-unloaded +function unload(host, name) + local ok, err = do_unload_module(host, name); + if ok then + (hosts[host] or prosody).events.fire_event("module-unloaded", { module = name, host = host }); + end + return ok, err; +end + +function reload(host, name) + local ok, err = do_reload_module(host, name); + if ok then + (hosts[host] or prosody).events.fire_event("module-reloaded", { module = name, host = host }); + elseif not is_loaded(host, name) then + (hosts[host] or prosody).events.fire_event("module-unloaded", { module = name, host = host }); end return ok, err; end +function get_module(host, name) + return modulemap[host] and modulemap[host][name]; +end + +function get_modules(host) + return modulemap[host]; +end + +function is_loaded(host, name) + return modulemap[host] and modulemap[host][name] and true; +end + function module_has_method(module, method) return type(module.module[method]) == "function"; end -- cgit v1.2.3 From 6924d7bfb5c9bcd125a5b872bd9fb7fc6d1b5322 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 18:47:33 +0000 Subject: modulemanager: Drop unnecessary prosody_events local --- core/modulemanager.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 1846e0f0..9f90e34e 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -15,7 +15,6 @@ local pluginloader = require "util.pluginloader"; local hosts = hosts; local prosody = prosody; -local prosody_events = prosody.events; local loadfile, pcall, xpcall = loadfile, pcall, xpcall; local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; @@ -87,8 +86,7 @@ function load_modules_for_host(host) load(host, module); end end -prosody_events.add_handler("host-activated", load_modules_for_host); --- +prosody.events.add_handler("host-activated", load_modules_for_host); --- Private helpers --- -- cgit v1.2.3 From 15a073672027cdf47822ad280e00185970ba0bdd Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 18:49:11 +0000 Subject: modulemanager, moduleapi: Replace hooks multitable with an event_handlers map stored in individual modules. Also adds module:hook_object_event() to hook events on any util.events compatible object. --- core/moduleapi.lua | 11 +++++++---- core/modulemanager.lua | 22 +++++----------------- 2 files changed, 12 insertions(+), 21 deletions(-) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index ee960709..3a28ec62 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -66,14 +66,17 @@ function api:fire_event(...) return (hosts[self.host] or prosody).events.fire_event(...); end +function api:hook_object_event(object, event, handler, priority) + self.event_handlers[handler] = { name = event, priority = priority, object = object }; + return object.add_handler(event, handler, priority); +end + function api:hook(event, handler, priority) - hooks:set(self.host, self.name, event, handler, true); - (hosts[self.host] or prosody).events.add_handler(event, handler, priority); + return self:hook_object_event((hosts[self.host] or prosody).events, event, handler, priority); end function api:hook_global(event, handler, priority) - hooks:set("*", self.name, event, handler, true); - prosody.events.add_handler(event, handler, priority); + return self:hook_object_event(prosody.events, event, handler, priority); end function api:hook_stanza(xmlns, name, handler, priority) diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 9f90e34e..f86298c9 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -48,10 +48,6 @@ local api = _G.require "core.moduleapi"; -- Module API container local modulemap = { ["*"] = {} }; -local modulehelpers = setmetatable({}, { __index = _G }); - -local hooks = multitable_new(); - local NULL = {}; -- Load modules when a host is activated @@ -100,19 +96,11 @@ local function do_unload_module(host, name) log("warn", "Non-fatal error unloading module '%s' on '%s': %s", name, host, err); end end - -- unhook event handlers hooked by module:hook - for event, handlers in pairs(hooks:get(host, name) or NULL) do - for handler in pairs(handlers or NULL) do - (hosts[host] or prosody).events.remove_handler(event, handler); - end - end - -- unhook event handlers hooked by module:hook_global - for event, handlers in pairs(hooks:get("*", name) or NULL) do - for handler in pairs(handlers or NULL) do - prosody.events.remove_handler(event, handler); - end + + for handler, event in pairs(mod.module.event_handlers) do + event.object.remove_handler(event.name, handler); end - hooks:remove(host, name); + if mod.module.items then -- remove items for key,t in pairs(mod.module.items) do for i = #t,1,-1 do @@ -153,7 +141,7 @@ local function do_load_module(host, module_name) local _log = logger.init(host..":"..module_name); local api_instance = setmetatable({ name = module_name, host = host, path = err, - _log = _log, log = function (self, ...) return _log(...); end } + _log = _log, log = function (self, ...) return _log(...); end, event_handlers = {} } , { __index = api }); local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); -- cgit v1.2.3 From c240995e515d44142f8c2808085198536bdcb15b Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 18:49:49 +0000 Subject: modulemanager: Cleanup some unused variables, imports, whitespace and add a comment. --- core/modulemanager.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index f86298c9..a6d1ad35 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -9,8 +9,6 @@ local logger = require "util.logger"; local log = logger.init("modulemanager"); local config = require "core.configmanager"; -local multitable_new = require "util.multitable".new; -local st = require "util.stanza"; local pluginloader = require "util.pluginloader"; local hosts = hosts; @@ -46,6 +44,7 @@ module "modulemanager" local api = _G.require "core.moduleapi"; -- Module API container +-- [host] = { [module] = module_env } local modulemap = { ["*"] = {} }; local NULL = {}; @@ -185,7 +184,6 @@ local function do_reload_module(host, name) end local saved; - if module_has_method(mod, "save") then local ok, ret, err = call_module_method(mod, "save"); if ok then -- cgit v1.2.3 From 11bf5edc1d5395822ab2dfe1edc84af85bc6dc57 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 19:27:06 +0000 Subject: modulemanager: load(): Return and use the correct module object --- core/modulemanager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index a6d1ad35..a192e637 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -170,7 +170,7 @@ local function do_load_module(host, module_name) log("error", "Error initializing module '%s' on '%s': %s", module_name, host, err or "nil"); do_unload_module(api_instance.host, module_name); -- Ignore error, module may be partially-loaded end - return ok and mod, err; + return ok and pluginenv, err; end local function do_reload_module(host, name) @@ -219,7 +219,7 @@ end function load(host, name) local mod, err = do_load_module(host, name); if mod then - (hosts[mod.host] or prosody).events.fire_event("module-loaded", { module = module_name, host = host }); + (hosts[mod.module.host] or prosody).events.fire_event("module-loaded", { module = name, host = host }); end return mod, err; end -- cgit v1.2.3 From 2f397255c26a57c36102ece3883c3765870c0bf9 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 19:35:50 +0000 Subject: moduleapi: Add module:depends(), a way to safely depend upon another module at runtime --- core/moduleapi.lua | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 3a28ec62..44ae9a07 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -100,6 +100,35 @@ function api:require(lib) return f(); end +function api:depends(name) + if not self.dependencies then + self.dependencies = {}; + self:hook("module-reloaded", function (event) + if self.dependencies[event.module] then + self:log("info", "Auto-reloading due to reload of %s:%s", event.host, event.module); + modulemanager.reload(self.host, self.name); + return; + end + end); + self:hook("module-unloaded", function (event) + if self.dependencies[event.module] then + self:log("info", "Auto-unloading due to unload of %s:%s", event.host, event.module); + modulemanager.unload(self.host, self.name); + end + end); + end + local mod = modulemanager.get_module(self.host, name) or modulemanager.get_module("*", name); + if not mod then + local err; + mod, err = modulemanager.load(self.host, name); + if not mod then + return error(("Unable to load required module, mod_%s: %s"):format(name, ((err or "unknown error"):gsub("%-", " ")) )); + end + end + self.dependencies[name] = true; + return mod; +end + function api:get_option(name, default_value) local value = config.get(self.host, self.name, name); if value == nil then -- cgit v1.2.3 From 7c5700ac5402bf47a6c55d55a7f1fa1a8b8cd0d0 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 19:48:53 +0000 Subject: moduleapi: Add module:shared(), a way to easily share data between multiple loaded modules --- core/moduleapi.lua | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 44ae9a07..7a4d1fa6 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -129,6 +129,29 @@ 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(...) + 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 = {}; + shared_data[path] = shared; + end + t_insert(data_array, shared); + end + return unpack(data_array); +end + function api:get_option(name, default_value) local value = config.get(self.host, self.name, name); if value == nil then -- cgit v1.2.3 From 29f37bbccc6d928adc4cf118aebf250974918eab Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 23:55:48 +0000 Subject: portmanager: One manager to, in the darkness, bind them --- core/portmanager.lua | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 core/portmanager.lua (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua new file mode 100644 index 00000000..a460cd6a --- /dev/null +++ b/core/portmanager.lua @@ -0,0 +1,132 @@ + +local multitable = require "util.multitable"; +local fire_event = prosody.events.fire_event; + +--- Config + +local default_interfaces = { "*" }; +local default_local_interfaces = { "127.0.0.1" }; +if config.get("*", "use_ipv6") then + table.insert(default_interfaces, "::"); + table.insert(default_local_interfaces, "::1"); +end + +--- Private state + +-- service_name -> service_info +local services = {}; + +-- service_name, interface (string), port (number) +local active_services = multitable.new(); + +--- Private helpers + +local function error_to_friendly_message(service_name, err) + local friendly_message = err; + if err:match(" in use") then + -- FIXME: Use service_name here + if port == 5222 or port == 5223 or port == 5269 then + friendly_message = "check that Prosody or another XMPP server is " + .."not already running and using this port"; + elseif port == 80 or port == 81 then + friendly_message = "check that a HTTP server is not already using " + .."this port"; + elseif port == 5280 then + friendly_message = "check that Prosody or a BOSH connection manager " + .."is not already running"; + else + friendly_message = "this port is in use by another application"; + end + elseif err:match("permission") then + friendly_message = "Prosody does not have sufficient privileges to use this port"; + elseif err == "no ssl context" then + if not config.get("*", "core", "ssl") then + friendly_message = "there is no 'ssl' config under Host \"*\" which is " + .."require for legacy SSL ports"; + else + friendly_message = "initializing SSL support failed, see previous log entries"; + end + end + return friendly_message; +end + +module("portmanager", package.seeall); + +--- Public API + +function activate_service(service_name) + local service_info = services[service_name]; + if not service_info then + return nil, "Unknown service: "..service_name; + end + + local bind_interfaces = set.new(config.get("*", service_name.."_interfaces") + or config.get("*", service_name.."_interface") -- COMPAT w/pre-0.9 + or config.get("*", "interfaces") + or config.get("*", "interface") -- COMPAT w/pre-0.9 + or (service_info.private and default_local_interfaces) + or service_info.default_interface -- COMPAT w/pre0.9 + or default_interfaces); + + local bind_ports = set.new(config.get("*", service_name.."_ports") + or (service_info.multiplex and config.get("*", "ports")) + or service_info.default_ports + or {service_info.default_port}); + + local listener = service_info.listener; + local mode = listener.default_mode or "*a"; + local ssl; + if service_info.encryption == "ssl" then + ssl = prosody.global_ssl_ctx; + if not ssl then + return nil, "global-ssl-context-required"; + end + end + + for interface in bind_interfaces do + for port in bind_ports do + if not service_info.multiplex and #active_services:search(nil, interface, port) > 0 then + log("error", "Multiple services configured to listen on the same port: %s, %s", table.concat(active_services:search(nil, interface, port), ", "), service_name); + else + local handler, err = server.addserver(interface, port, listener, mode, ssl); + if not handler then + log("error", "Failed to open server port %d on %s, %s", port, interface, error_to_friendly_message(service_name, err)); + else + log("debug", "Added listening service %s to [%s]:%d", service_name, interface, port); + active_services:add(service_name, interface, port, { + server = handler; + service = service_info; + }); + end + end + end + end + log("info", "Activated service '%s'", service_name); +end + +function deactivate(service_name) + local active = active_services:search(service_name)[1]; + if not active then return; end + for interface, ports in pairs(active) do + for port, active_service in pairs(ports) do + active_service:close(); + active_services:remove(service_name, interface, port, active_service); + log("debug", "Removed listening service %s from [%s]:%d", service_name, interface, port); + end + end + log("info", "Deactivated service '%s'", service_name); +end + +function register_service(service_name, service_info) + services[service_name] = service_info; + + if not active_services[service_name] then + activate_service(service_name); + end + + fire_event("service-added", { name = service_name, service = service_info }); + return true; +end + + +return _M; -- cgit v1.2.3 From 13b36f8ded00794f3142887c41ac8b31efb01e4b Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 22 Jan 2012 23:57:13 +0000 Subject: mod_c2s, sessionmanager, xmppclient_listener: Move all c2s network and stream logic into a new module, mod_c2s --- core/sessionmanager.lua | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) (limited to 'core') diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index b1ec819f..17c718dc 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -6,11 +6,8 @@ -- COPYING file in the source package for more information. -- - - local tonumber, tostring, setmetatable = tonumber, tostring, setmetatable; local ipairs, pairs, print, next= ipairs, pairs, print, next; -local format = string.format; local hosts = hosts; local full_sessions = full_sessions; @@ -19,10 +16,8 @@ local bare_sessions = bare_sessions; local logger = require "util.logger"; local log = logger.init("sessionmanager"); local error = error; -local uuid_generate = require "util.uuid".generate; local rm_load_roster = require "core.rostermanager".load_roster; local config_get = require "core.configmanager".get; -local nameprep = require "util.encodings".stringprep.nameprep; local resourceprep = require "util.encodings".stringprep.resourceprep; local nodeprep = require "util.encodings".stringprep.nodeprep; @@ -216,50 +211,6 @@ function bind_resource(session, resource) return true; end -function streamopened(session, attr) - local send = session.send; - session.host = attr.to; - if not session.host then - session:close{ condition = "improper-addressing", - text = "A 'to' attribute is required on stream headers" }; - return; - end - session.host = nameprep(session.host); - session.version = tonumber(attr.version) or 0; - session.streamid = uuid_generate(); - (session.log or session)("debug", "Client sent opening to %s", session.host); - - if not hosts[session.host] then - -- We don't serve this host... - session:close{ condition = "host-unknown", text = "This server does not serve "..tostring(session.host)}; - return; - end - - send(""); - send(format("", session.streamid, session.host)); - - (session.log or log)("debug", "Sent reply to client"); - session.notopen = nil; - - -- If session.secure is *false* (not nil) then it means we /were/ encrypting - -- since we now have a new stream header, session is secured - if session.secure == false then - session.secure = true; - end - - local features = st.stanza("stream:features"); - hosts[session.host].events.fire_event("stream-features", { origin = session, features = features }); - fire_event("stream-features", session, features); - - send(features); - -end - -function streamclosed(session) - session.log("debug", "Received "); - session:close(); -end - function send_to_available_resources(user, host, stanza) local jid = user.."@"..host; local count = 0; -- cgit v1.2.3 From 1374dd01213e64739c9f555ba3d46bb875015fb3 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Jan 2012 00:07:15 +0000 Subject: portmanager: Pass port to friendly_error_message() --- core/portmanager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index a460cd6a..353c4a89 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -21,7 +21,7 @@ local active_services = multitable.new(); --- Private helpers -local function error_to_friendly_message(service_name, err) +local function error_to_friendly_message(service_name, port, err) local friendly_message = err; if err:match(" in use") then -- FIXME: Use service_name here @@ -90,7 +90,7 @@ function activate_service(service_name) else local handler, err = server.addserver(interface, port, listener, mode, ssl); if not handler then - log("error", "Failed to open server port %d on %s, %s", port, interface, error_to_friendly_message(service_name, err)); + log("error", "Failed to open server port %d on %s, %s", port, interface, error_to_friendly_message(service_name, port, err)); else log("debug", "Added listening service %s to [%s]:%d", service_name, interface, port); active_services:add(service_name, interface, port, { -- cgit v1.2.3 From b14f0af41d94b5ee137d48e269ad29b45ee765d9 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Jan 2012 00:56:57 +0000 Subject: sessionmanager, mod_c2s: Move timeout logic to mod_c2s --- core/sessionmanager.lua | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'core') diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 17c718dc..276cd8f5 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -28,8 +28,6 @@ local gettime = require "socket".gettime; local st = require "util.stanza"; -local c2s_timeout = config_get("*", "core", "c2s_timeout"); - local newproxy = newproxy; local getmetatable = getmetatable; @@ -62,14 +60,6 @@ function new_session(conn) session.ip = conn:ip(); local conn_name = "c2s"..tostring(conn):match("[a-f0-9]+$"); session.log = logger.init(conn_name); - - if c2s_timeout then - add_task(c2s_timeout, function () - if session.type == "c2s_unauthed" then - session:close("connection-timeout"); - end - end); - end return session; end -- cgit v1.2.3 From b1b28066ba73cf808af9f2b895ece7428c61a4b5 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Jan 2012 02:23:23 +0000 Subject: sessionmanager: Require uuid_generate() --- core/sessionmanager.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 276cd8f5..c101bf4e 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -20,6 +20,7 @@ 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 initialize_filters = require "util.filters".initialize; local fire_event = prosody.events.fire_event; -- cgit v1.2.3 From 3e2d3f18754e6b367ff69b46f138af9770c92b62 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Jan 2012 16:24:06 +0000 Subject: stanza_router: Remove obsolete commented code --- core/stanza_router.lua | 5 ----- 1 file changed, 5 deletions(-) (limited to 'core') diff --git a/core/stanza_router.lua b/core/stanza_router.lua index 406ad2f0..4a30279d 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -105,11 +105,6 @@ function core_process_stanza(origin, stanza) stanza.attr.from = from; end - --[[if to and not(hosts[to]) and not(hosts[to_bare]) and (hosts[host] and hosts[host].type ~= "local") then -- not for us? - log("warn", "stanza recieved for a non-local server"); - return; -- FIXME what should we do here? - end]] -- FIXME - if (origin.type == "s2sin" or origin.type == "c2s" or origin.type == "component") and xmlns == nil then if origin.type == "s2sin" and not origin.dummy then local host_status = origin.hosts[from_host]; -- cgit v1.2.3 From 3c5d5f95aded549e619dca86b7ff5689413646f9 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Jan 2012 16:25:21 +0000 Subject: stanza_router: Replace s2s send logic with firing of a 'route/remote' event --- core/stanza_router.lua | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) (limited to 'core') diff --git a/core/stanza_router.lua b/core/stanza_router.lua index 4a30279d..54c5a1a6 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -11,7 +11,6 @@ local log = require "util.logger".init("stanzarouter") local hosts = _G.prosody.hosts; local tostring = tostring; local st = require "util.stanza"; -local send_s2s = require "core.s2smanager".send_to_host; local jid_split = require "util.jid".split; local jid_prepped_split = require "util.jid".prepped_split; @@ -184,26 +183,18 @@ function core_route_stanza(origin, stanza) if hosts[host] then -- old stanza routing code removed core_post_stanza(origin, stanza); - elseif origin.type == "c2s" then - -- Remote host + else + log("debug", "Routing to remote..."); if not hosts[from_host] then log("error", "No hosts[from_host] (please report): %s", tostring(stanza)); - end - if (not hosts[from_host]) or (not hosts[from_host].disallow_s2s) then + else local xmlns = stanza.attr.xmlns; - --stanza.attr.xmlns = "jabber:server"; stanza.attr.xmlns = nil; - log("debug", "sending s2s stanza: %s", tostring(stanza.top_tag and stanza:top_tag()) or stanza); - send_s2s(origin.host, host, stanza); -- TODO handle remote routing errors + local routed = prosody.events.fire_event("route/remote", { origin = origin, stanza = stanza, from_host = from_host, to_host = host }); --FIXME: Should be per-host (shared modules!) stanza.attr.xmlns = xmlns; -- reset - else - core_route_stanza(hosts[from_host], st.error_reply(stanza, "cancel", "not-allowed", "Communication with remote servers is not allowed")); + if routed == nil then + core_route_stanza(hosts[from_host], st.error_reply(stanza, "cancel", "not-allowed", "Communication with remote domains is not enabled")); + end end - elseif origin.type == "component" or origin.type == "local" then - -- Route via s2s for components and modules - log("debug", "Routing outgoing stanza for %s to %s", from_host, host); - send_s2s(from_host, host, stanza); - else - log("warn", "received %s stanza from unhandled connection type: %s", tostring(stanza.name), tostring(origin.type)); end end -- cgit v1.2.3 From f851289311ce15196d3dc7ae0d912b17586901b9 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Jan 2012 16:28:20 +0000 Subject: s2smanager, mod_s2s, mod_s2s/s2sout: Split connection handling out of s2smanager into mod_s2s, and further split connection logic for s2sout to a module lib, s2sout.lib.lua --- core/s2smanager.lua | 581 +--------------------------------------------------- 1 file changed, 11 insertions(+), 570 deletions(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index f44921c3..e61aaccb 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -9,18 +9,13 @@ local hosts = hosts; -local sessions = sessions; local core_process_stanza = function(a, b) core_process_stanza(a, b); end -local add_task = require "util.timer".add_task; -local socket = require "socket"; local format = string.format; local t_insert, t_sort = table.insert, table.sort; local get_traceback = debug.traceback; local tostring, pairs, ipairs, getmetatable, newproxy, type, error, tonumber, setmetatable = tostring, pairs, ipairs, getmetatable, newproxy, type, error, tonumber, setmetatable; -local idna_to_ascii = require "util.encodings".idna.to_ascii; -local connlisteners_get = require "net.connlisteners".get; local initialize_filters = require "util.filters".initialize; local wrapclient = require "net.server".wrapclient; local st = require "stanza"; @@ -41,11 +36,13 @@ local sha256_hash = require "util.hashes".sha256; local adns, dns = require "net.adns", require "net.dns"; local config = require "core.configmanager"; -local connect_timeout = config.get("*", "core", "s2s_timeout") or 60; local dns_timeout = config.get("*", "core", "dns_timeout") or 15; local max_dns_depth = config.get("*", "core", "dns_max_depth") or 3; +local cfg_sources = config.get("*", "core", "s2s_interface") + or config.get("*", "core", "interface"); local sources; +--FIXME: s2sout should create its own resolver w/ timeout dns.settimeout(dns_timeout); local prosody = _G.prosody; @@ -55,89 +52,6 @@ local incoming_s2s = incoming_s2s; module "s2smanager" -function compare_srv_priorities(a,b) - return a.priority < b.priority or (a.priority == b.priority and a.weight > b.weight); -end - -local bouncy_stanzas = { message = true, presence = true, iq = true }; -local function bounce_sendq(session, reason) - local sendq = session.sendq; - if sendq then - session.log("info", "sending error replies for "..#sendq.." queued stanzas because of failed outgoing connection to "..tostring(session.to_host)); - local dummy = { - type = "s2sin"; - send = function(s) - (session.log or log)("error", "Replying to to an s2s error reply, please report this! Traceback: %s", get_traceback()); - end; - dummy = true; - }; - for i, data in ipairs(sendq) do - local reply = data[2]; - if reply and not(reply.attr.xmlns) and bouncy_stanzas[reply.name] then - reply.attr.type = "error"; - reply:tag("error", {type = "cancel"}) - :tag("remote-server-not-found", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}):up(); - if reason then - reply:tag("text", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}) - :text("Server-to-server connection failed: "..reason):up(); - end - core_process_stanza(dummy, reply); - end - sendq[i] = nil; - end - session.sendq = nil; - end -end - -function send_to_host(from_host, to_host, data) - if not hosts[from_host] then - log("warn", "Attempt to send stanza from %s - a host we don't serve", from_host); - return false; - end - local host = hosts[from_host].s2sout[to_host]; - if host then - -- We have a connection to this host already - if host.type == "s2sout_unauthed" and (data.name ~= "db:verify" or not host.dialback_key) then - (host.log or log)("debug", "trying to send over unauthed s2sout to "..to_host); - - -- Queue stanza until we are able to send it - if host.sendq then t_insert(host.sendq, {tostring(data), data.attr.type ~= "error" and data.attr.type ~= "result" and st.reply(data)}); - else host.sendq = { {tostring(data), data.attr.type ~= "error" and data.attr.type ~= "result" and st.reply(data)} }; end - host.log("debug", "stanza [%s] queued ", data.name); - elseif host.type == "local" or host.type == "component" then - log("error", "Trying to send a stanza to ourselves??") - log("error", "Traceback: %s", get_traceback()); - log("error", "Stanza: %s", tostring(data)); - return false; - else - (host.log or log)("debug", "going to send stanza to "..to_host.." from "..from_host); - -- FIXME - if host.from_host ~= from_host then - log("error", "WARNING! This might, possibly, be a bug, but it might not..."); - log("error", "We are going to send from %s instead of %s", tostring(host.from_host), tostring(from_host)); - end - host.sends2s(data); - host.log("debug", "stanza sent over "..host.type); - end - else - log("debug", "opening a new outgoing connection for this stanza"); - local host_session = new_outgoing(from_host, to_host); - - -- Store in buffer - host_session.sendq = { {tostring(data), data.attr.type ~= "error" and data.attr.type ~= "result" and st.reply(data)} }; - log("debug", "stanza [%s] queued until connection complete", tostring(data.name)); - if (not host_session.connecting) and (not host_session.conn) then - log("warn", "Connection to %s failed already, destroying session...", to_host); - if not destroy_session(host_session, "Connection failed") then - -- Already destroyed, we need to bounce our stanza - bounce_sendq(host_session, host_session.destruction_reason); - end - return false; - end - end - return true; -end - local open_sessions = 0; function new_incoming(conn) @@ -147,491 +61,18 @@ function new_incoming(conn) getmetatable(session.trace).__gc = function () open_sessions = open_sessions - 1; end; end open_sessions = open_sessions + 1; - local w, log = conn.write, logger_init("s2sin"..tostring(conn):match("[a-f0-9]+$")); - session.log = log; - local filter = initialize_filters(session); - session.sends2s = function (t) - log("debug", "sending: %s", t.top_tag and t:top_tag() or t:match("^([^>]*>?)")); - if t.name then - t = filter("stanzas/out", t); - end - if t then - t = filter("bytes/out", tostring(t)); - if t then - return w(conn, t); - end - end - end + session.log = logger_init("s2sin"..tostring(conn):match("[a-f0-9]+$")); incoming_s2s[session] = true; - add_task(connect_timeout, function () - if session.conn ~= conn or - session.type == "s2sin" then - return; -- Ok, we're connect[ed|ing] - end - -- Not connected, need to close session and clean up - (session.log or log)("debug", "Destroying incomplete session %s->%s due to inactivity", - session.from_host or "(unknown)", session.to_host or "(unknown)"); - session:close("connection-timeout"); - end); return session; end function new_outgoing(from_host, to_host, connect) - local host_session = { to_host = to_host, from_host = from_host, host = from_host, - notopen = true, type = "s2sout_unauthed", direction = "outgoing", - open_stream = session_open_stream }; - - hosts[from_host].s2sout[to_host] = host_session; - - host_session.close = destroy_session; -- This gets replaced by xmppserver_listener later - - local log; - do - local conn_name = "s2sout"..tostring(host_session):match("[a-f0-9]*$"); - log = logger_init(conn_name); - host_session.log = log; - end - - initialize_filters(host_session); - - if connect ~= false then - -- Kick the connection attempting machine into life - if not attempt_connection(host_session) then - -- Intentionally not returning here, the - -- session is needed, connected or not - destroy_session(host_session); - end - end - - if not host_session.sends2s then - -- A sends2s which buffers data (until the stream is opened) - -- note that data in this buffer will be sent before the stream is authed - -- and will not be ack'd in any way, successful or otherwise - local buffer; - function host_session.sends2s(data) - if not buffer then - buffer = {}; - host_session.send_buffer = buffer; - end - log("debug", "Buffering data on unconnected s2sout to %s", to_host); - buffer[#buffer+1] = data; - log("debug", "Buffered item %d: %s", #buffer, tostring(data)); - end - end - - return host_session; -end - - -function attempt_connection(host_session, err) - local from_host, to_host = host_session.from_host, host_session.to_host; - local connect_host, connect_port = to_host and idna_to_ascii(to_host), 5269; - - if not connect_host then - return false; - end - - if not err then -- This is our first attempt - log("debug", "First attempt to connect to %s, starting with SRV lookup...", to_host); - host_session.connecting = true; - local handle; - handle = adns.lookup(function (answer) - handle = nil; - host_session.connecting = nil; - if answer then - log("debug", to_host.." has SRV records, handling..."); - local srv_hosts = {}; - host_session.srv_hosts = srv_hosts; - for _, record in ipairs(answer) do - t_insert(srv_hosts, record.srv); - end - if #srv_hosts == 1 and srv_hosts[1].target == "." then - log("debug", to_host.." does not provide a XMPP service"); - destroy_session(host_session, err); -- Nothing to see here - return; - end - t_sort(srv_hosts, compare_srv_priorities); - - local srv_choice = srv_hosts[1]; - host_session.srv_choice = 1; - if srv_choice then - connect_host, connect_port = srv_choice.target or to_host, srv_choice.port or connect_port; - log("debug", "Best record found, will connect to %s:%d", connect_host, connect_port); - end - else - log("debug", to_host.." has no SRV records, falling back to A"); - end - -- Try with SRV, or just the plain hostname if no SRV - local ok, err = try_connect(host_session, connect_host, connect_port); - if not ok then - if not attempt_connection(host_session, err) then - -- No more attempts will be made - destroy_session(host_session, err); - end - end - end, "_xmpp-server._tcp."..connect_host..".", "SRV"); - - return true; -- Attempt in progress - elseif host_session.ip_hosts then - return try_connect(host_session, connect_host, connect_port, err); - elseif host_session.srv_hosts and #host_session.srv_hosts > host_session.srv_choice then -- Not our first attempt, and we also have SRV - host_session.srv_choice = host_session.srv_choice + 1; - local srv_choice = host_session.srv_hosts[host_session.srv_choice]; - connect_host, connect_port = srv_choice.target or to_host, srv_choice.port or connect_port; - host_session.log("info", "Connection failed (%s). Attempt #%d: This time to %s:%d", tostring(err), host_session.srv_choice, connect_host, connect_port); - else - host_session.log("info", "Out of connection options, can't connect to %s", tostring(host_session.to_host)); - -- We're out of options - return false; - end - - if not (connect_host and connect_port) then - -- Likely we couldn't resolve DNS - log("warn", "Hmm, we're without a host (%s) and port (%s) to connect to for %s, giving up :(", tostring(connect_host), tostring(connect_port), tostring(to_host)); - return false; - end - - return try_connect(host_session, connect_host, connect_port); -end - -function try_next_ip(host_session) - host_session.connecting = nil; - host_session.ip_choice = host_session.ip_choice + 1; - local ip = host_session.ip_hosts[host_session.ip_choice]; - local ok, err= make_connect(host_session, ip.ip, ip.port); - if not ok then - if not attempt_connection(host_session, err or "closed") then - err = err and (": "..err) or ""; - destroy_session(host_session, "Connection failed"..err); - end - end -end - -function try_connect(host_session, connect_host, connect_port, err) - host_session.connecting = true; - - if not err then - local IPs = {}; - host_session.ip_hosts = IPs; - local handle4, handle6; - local has_other = false; - - if not sources then - sources = {}; - local cfg_sources = config.get("*", "core", "interface") or connlisteners_get("xmppserver").default_interface; - if type(cfg_sources) == "string" then - cfg_sources = { cfg_sources }; - end - for i, source in ipairs(cfg_sources) do - if source == "*" then - sources[i] = new_ip("0.0.0.0", "IPv4"); - else - sources[i] = new_ip(source, (source:find(":") and "IPv6") or "IPv4"); - end - end - end - - handle4 = adns.lookup(function (reply, err) - handle4 = nil; - - -- COMPAT: This is a compromise for all you CNAME-(ab)users :) - if not (reply and reply[#reply] and reply[#reply].a) then - local count = max_dns_depth; - reply = dns.peek(connect_host, "CNAME", "IN"); - while count > 0 and reply and reply[#reply] and not reply[#reply].a and reply[#reply].cname do - log("debug", "Looking up %s (DNS depth is %d)", tostring(reply[#reply].cname), count); - reply = dns.peek(reply[#reply].cname, "A", "IN") or dns.peek(reply[#reply].cname, "CNAME", "IN"); - count = count - 1; - end - end - -- end of CNAME resolving - - if reply and reply[#reply] and reply[#reply].a then - for _, ip in ipairs(reply) do - log("debug", "DNS reply for %s gives us %s", connect_host, ip.a); - IPs[#IPs+1] = new_ip(ip.a, "IPv4"); - end - end - - if has_other then - if #IPs > 0 then - rfc3484_dest(host_session.ip_hosts, sources); - for i = 1, #IPs do - IPs[i] = {ip = IPs[i], port = connect_port}; - end - host_session.ip_choice = 0; - try_next_ip(host_session); - else - log("debug", "DNS lookup failed to get a response for %s", connect_host); - host_session.ip_hosts = nil; - if not attempt_connection(host_session, "name resolution failed") then -- Retry if we can - log("debug", "No other records to try for %s - destroying", host_session.to_host); - err = err and (": "..err) or ""; - destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't - end - end - else - has_other = true; - end - end, connect_host, "A", "IN"); - - handle6 = adns.lookup(function (reply, err) - handle6 = nil; - - if reply and reply[#reply] and reply[#reply].aaaa then - for _, ip in ipairs(reply) do - log("debug", "DNS reply for %s gives us %s", connect_host, ip.aaaa); - IPs[#IPs+1] = new_ip(ip.aaaa, "IPv6"); - end - end - - if has_other then - if #IPs > 0 then - rfc3484_dest(host_session.ip_hosts, sources); - for i = 1, #IPs do - IPs[i] = {ip = IPs[i], port = connect_port}; - end - host_session.ip_choice = 0; - try_next_ip(host_session); - else - log("debug", "DNS lookup failed to get a response for %s", connect_host); - host_session.ip_hosts = nil; - if not attempt_connection(host_session, "name resolution failed") then -- Retry if we can - log("debug", "No other records to try for %s - destroying", host_session.to_host); - err = err and (": "..err) or ""; - destroy_session(host_session, "DNS resolution failed"..err); -- End of the line, we can't - end - end - else - has_other = true; - end - end, connect_host, "AAAA", "IN"); - - return true; - elseif host_session.ip_hosts and #host_session.ip_hosts > host_session.ip_choice then -- Not our first attempt, and we also have IPs left to try - try_next_ip(host_session); - else - host_session.ip_hosts = nil; - if not attempt_connection(host_session, "out of IP addresses") then -- Retry if we can - log("debug", "No other records to try for %s - destroying", host_session.to_host); - err = err and (": "..err) or ""; - destroy_session(host_session, "Connecting failed"..err); -- End of the line, we can't - return false; - end - end - - return true; -end - -function make_connect(host_session, connect_host, connect_port) - (host_session.log or log)("info", "Beginning new connection attempt to %s ([%s]:%d)", host_session.to_host, connect_host.addr, connect_port); - -- Ok, we're going to try to connect - - local from_host, to_host = host_session.from_host, host_session.to_host; - - local conn, handler; - if connect_host.proto == "IPv4" then - conn, handler = socket.tcp(); - else - conn, handler = socket.tcp6(); - end - - if not conn then - log("warn", "Failed to create outgoing connection, system error: %s", handler); - return false, handler; - end - - conn:settimeout(0); - local success, err = conn:connect(connect_host.addr, connect_port); - if not success and err ~= "timeout" then - log("warn", "s2s connect() to %s (%s:%d) failed: %s", host_session.to_host, connect_host.addr, connect_port, err); - return false, err; - end - - local cl = connlisteners_get("xmppserver"); - conn = wrapclient(conn, connect_host.addr, connect_port, cl, cl.default_mode or 1 ); - host_session.conn = conn; - - local filter = initialize_filters(host_session); - local w, log = conn.write, host_session.log; - host_session.sends2s = function (t) - log("debug", "sending: %s", (t.top_tag and t:top_tag()) or t:match("^[^>]*>?")); - if t.name then - t = filter("stanzas/out", t); - end - if t then - t = filter("bytes/out", tostring(t)); - if t then - return w(conn, tostring(t)); - end - end - end - - -- Register this outgoing connection so that xmppserver_listener knows about it - -- otherwise it will assume it is a new incoming connection - cl.register_outgoing(conn, host_session); - - host_session:open_stream(from_host, to_host); - - log("debug", "Connection attempt in progress..."); - add_task(connect_timeout, function () - if host_session.conn ~= conn or - host_session.type == "s2sout" or - host_session.connecting then - return; -- Ok, we're connect[ed|ing] - end - -- Not connected, need to close session and clean up - (host_session.log or log)("warn", "Destroying incomplete session %s->%s due to inactivity", - host_session.from_host or "(unknown)", host_session.to_host or "(unknown)"); - host_session:close("connection-timeout"); - end); - return true; -end - -function session_open_stream(session, from, to) - session.sends2s(st.stanza("stream:stream", { - xmlns='jabber:server', ["xmlns:db"]='jabber:server:dialback', - ["xmlns:stream"]='http://etherx.jabber.org/streams', - from=from, to=to, version='1.0', ["xml:lang"]='en'}):top_tag()); -end - -local function check_cert_status(session) - local conn = session.conn:socket() - local cert - if conn.getpeercertificate then - cert = conn:getpeercertificate() - end - - if cert then - local chain_valid, errors = conn:getpeerverification() - -- Is there any interest in printing out all/the number of errors here? - if not chain_valid then - (session.log or log)("debug", "certificate chain validation result: invalid"); - session.cert_chain_status = "invalid"; - else - (session.log or log)("debug", "certificate chain validation result: valid"); - session.cert_chain_status = "valid"; - - local host = session.direction == "incoming" and session.from_host or session.to_host - - -- We'll go ahead and verify the asserted identity if the - -- connecting server specified one. - if host then - if cert_verify_identity(host, "xmpp-server", cert) then - session.cert_identity_status = "valid" - else - session.cert_identity_status = "invalid" - end - end - end - end -end - -function streamopened(session, attr) - local send = session.sends2s; - - -- TODO: #29: SASL/TLS on s2s streams - session.version = tonumber(attr.version) or 0; - - -- TODO: Rename session.secure to session.encrypted - if session.secure == false then - session.secure = true; - end - - if session.direction == "incoming" then - -- Send a reply stream header - session.to_host = attr.to and nameprep(attr.to); - session.from_host = attr.from and nameprep(attr.from); - - session.streamid = uuid_gen(); - (session.log or log)("debug", "Incoming s2s received "); - if session.to_host then - if not hosts[session.to_host] then - -- Attempting to connect to a host we don't serve - session:close({ - condition = "host-unknown"; - text = "This host does not serve "..session.to_host - }); - return; - elseif hosts[session.to_host].disallow_s2s then - -- Attempting to connect to a host that disallows s2s - session:close({ - condition = "policy-violation"; - text = "Server-to-server communication is not allowed to this host"; - }); - return; - end - end - - if session.secure and not session.cert_chain_status then check_cert_status(session); end - - send(""); - send(stanza("stream:stream", { xmlns='jabber:server', ["xmlns:db"]='jabber:server:dialback', - ["xmlns:stream"]='http://etherx.jabber.org/streams', id=session.streamid, from=session.to_host, to=session.from_host, version=(session.version > 0 and "1.0" or nil) }):top_tag()); - if session.version >= 1.0 then - local features = st.stanza("stream:features"); - - if session.to_host then - hosts[session.to_host].events.fire_event("s2s-stream-features", { origin = session, features = features }); - else - (session.log or log)("warn", "No 'to' on stream header from %s means we can't offer any features", session.from_host or "unknown host"); - end - - log("debug", "Sending stream features: %s", tostring(features)); - send(features); - end - elseif session.direction == "outgoing" then - -- If we are just using the connection for verifying dialback keys, we won't try and auth it - if not attr.id then error("stream response did not give us a streamid!!!"); end - session.streamid = attr.id; - - if session.secure and not session.cert_chain_status then check_cert_status(session); end - - -- Send unauthed buffer - -- (stanzas which are fine to send before dialback) - -- Note that this is *not* the stanza queue (which - -- we can only send if auth succeeds) :) - local send_buffer = session.send_buffer; - if send_buffer and #send_buffer > 0 then - log("debug", "Sending s2s send_buffer now..."); - for i, data in ipairs(send_buffer) do - session.sends2s(tostring(data)); - send_buffer[i] = nil; - end - end - session.send_buffer = nil; - - -- If server is pre-1.0, don't wait for features, just do dialback - if session.version < 1.0 then - if not session.dialback_verifying then - log("debug", "Initiating dialback..."); - initiate_dialback(session); - else - mark_connected(session); - end - end - end - session.notopen = nil; -end - -function streamclosed(session) - (session.log or log)("debug", "Received "); - session:close(); -end - -function initiate_dialback(session) - -- generate dialback key - session.dialback_key = generate_dialback(session.streamid, session.to_host, session.from_host); - session.sends2s(format("%s", session.from_host, session.to_host, session.dialback_key)); - session.log("info", "sent dialback key on outgoing s2s stream"); -end - -function generate_dialback(id, to, from) - return sha256_hash(id..to..from..hosts[from].dialback_secret, true); -end - -function verify_dialback(id, to, from, key) - return key == generate_dialback(id, to, from); + local host_session = { to_host = to_host, from_host = from_host, host = from_host, + notopen = true, type = "s2sout_unauthed", direction = "outgoing" }; + hosts[from_host].s2sout[to_host] = host_session; + local conn_name = "s2sout"..tostring(host_session):match("[a-f0-9]*$"); + host_session.log = logger_init(conn_name); + return host_session; end function make_authenticated(session, host) @@ -733,7 +174,7 @@ function destroy_session(session, reason) if session.direction == "outgoing" then hosts[session.from_host].s2sout[session.to_host] = nil; - bounce_sendq(session, reason); + session:bounce_sendq(reason); elseif session.direction == "incoming" then incoming_s2s[session] = nil; end -- cgit v1.2.3 From 4c9c8363bca9bbe87c34f102567cff7a9e539107 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Fri, 24 Feb 2012 15:14:07 +0000 Subject: modulemanager: include mod_c2s and mod_s2s into autoloaded modules. --- core/modulemanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index a192e637..0ca37105 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -34,7 +34,7 @@ end local array, set = require "util.array", require "util.set"; -local autoload_modules = {"presence", "message", "iq", "offline"}; +local autoload_modules = {"presence", "message", "iq", "offline", "c2s", "s2s"}; local component_inheritable_modules = {"tls", "dialback", "iq"}; -- We need this to let modules access the real global namespace -- cgit v1.2.3 From 8f06587c5070d361bb41d39c4c92a57b49c4dfea Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Fri, 24 Feb 2012 15:15:43 +0000 Subject: s2smanager: remove send_to_host. --- core/s2smanager.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index e61aaccb..6877ee18 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -114,10 +114,7 @@ function mark_connected(session) local from, to = session.from_host, session.to_host; session.log("info", session.direction.." s2s connection "..from.."->"..to.." complete"); - - local send_to_host = send_to_host; - function session.send(data) return send_to_host(to, from, data); end - + local event_data = { session = session }; if session.type == "s2sout" then prosody.events.fire_event("s2sout-established", event_data); -- cgit v1.2.3 From 74bff42057bbe1dbf278959cff1ae8cab077ac19 Mon Sep 17 00:00:00 2001 From: Marco Cirillo Date: Fri, 24 Feb 2012 18:03:27 +0000 Subject: s2smanager, mod_s2s: clear up ip_hosts after s2s is marked as established, remove useless space from mod_s2s code --- core/s2smanager.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 6877ee18..c05f7229 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -134,6 +134,7 @@ function mark_connected(session) session.sendq = nil; end + session.ip_hosts = nil; session.srv_hosts = nil; end end -- cgit v1.2.3 From ba9e28535b28d3a9a2e8eca7b8a740a8ffad49c1 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 25 Feb 2012 02:03:26 +0000 Subject: s2smanager: Fix traceback when socket.tcp6 isn't available --- core/s2smanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 822713fe..6c880a02 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -432,7 +432,7 @@ function make_connect(host_session, connect_host, connect_port) local conn, handler; if connect_host.proto == "IPv4" then conn, handler = socket.tcp(); - else + elseif socket.tcp6 then conn, handler = socket.tcp6(); end -- cgit v1.2.3 From 25b408fcaf0f3b11fe550d68681d13b64cc2a222 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 3 Mar 2012 00:54:19 +0100 Subject: core.portmanager: Make sure the private flag takes precedence over global interfaces --- core/portmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 353c4a89..3d6dada4 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -62,9 +62,9 @@ function activate_service(service_name) local bind_interfaces = set.new(config.get("*", service_name.."_interfaces") or config.get("*", service_name.."_interface") -- COMPAT w/pre-0.9 + or (service_info.private and default_local_interfaces) or config.get("*", "interfaces") or config.get("*", "interface") -- COMPAT w/pre-0.9 - or (service_info.private and default_local_interfaces) or service_info.default_interface -- COMPAT w/pre0.9 or default_interfaces); -- cgit v1.2.3 From 4c152e2f3beafe251107fd66d0476d66e3fcc65c Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 11 Mar 2012 12:40:32 +0000 Subject: portmanager: Add get_service() --- core/portmanager.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 3d6dada4..f655659d 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -128,5 +128,8 @@ function register_service(service_name, service_info) return true; end +function get_service(service_name) + return services[service_name]; +end return _M; -- cgit v1.2.3 From 26768f3e54805074211fc0846221acce5765f570 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 11 Mar 2012 19:14:28 +0100 Subject: s2smanager, mod_s2s: Move import of dns_max_depth to mod_s2s --- core/s2smanager.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'core') diff --git a/core/s2smanager.lua b/core/s2smanager.lua index c05f7229..158b5461 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -37,7 +37,6 @@ local sha256_hash = require "util.hashes".sha256; local adns, dns = require "net.adns", require "net.dns"; local config = require "core.configmanager"; local dns_timeout = config.get("*", "core", "dns_timeout") or 15; -local max_dns_depth = config.get("*", "core", "dns_max_depth") or 3; local cfg_sources = config.get("*", "core", "s2s_interface") or config.get("*", "core", "interface"); local sources; -- cgit v1.2.3 From 30314b5891a1eb96c6b5fc7d9235695c3077e54e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 11 Mar 2012 18:35:27 +0000 Subject: portmanager: Add get_active_services() --- core/portmanager.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index f655659d..103c5d44 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -132,4 +132,8 @@ function get_service(service_name) return services[service_name]; end +function get_active_services(...) + return active_services; +end + return _M; -- cgit v1.2.3 From 121a7f3acddc52eb911688b5f23d3efee9178ea5 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 14 Mar 2012 17:03:48 +0000 Subject: modulemanager: Use appropriate events object for global modules when firing item-removed on unload --- core/modulemanager.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 0ca37105..328224ae 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -101,11 +101,12 @@ local function do_unload_module(host, name) end if mod.module.items then -- remove items + local events = (host == "*" and prosody.events) or hosts[host].events; for key,t in pairs(mod.module.items) do for i = #t,1,-1 do local value = t[i]; t[i] = nil; - hosts[host].events.fire_event("item-removed/"..key, {source = mod.module, item = value}); + events.fire_event("item-removed/"..key, {source = mod.module, item = value}); end end end -- cgit v1.2.3 From 2c3103e84ae364bc20782575a8113c9b96c1cbd7 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 14 Mar 2012 21:33:15 +0000 Subject: moduleapi: Set module.global = true when module:set_global() is called --- core/moduleapi.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 7a4d1fa6..b11fd7b3 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -50,6 +50,7 @@ function api:set_global() local _log = logger.init("mod_"..self.name); self.log = function (self, ...) return _log(...); end; self._log = _log; + self.global = true; end function api:add_feature(xmlns) -- cgit v1.2.3 From ce27bd5fe59bc640673abb52daa43110cfcd5c55 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 14 Mar 2012 21:37:00 +0000 Subject: modulemanager: Some refactoring. Deprecate module.host = "*", modules should call module:set_global() (which has been around since forever) --- core/modulemanager.lua | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 328224ae..f9f3a8b8 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -123,6 +123,7 @@ local function do_load_module(host, module_name) if not modulemap[host] then modulemap[host] = {}; + hosts[host].modules = modulemap[host]; end if modulemap[host][module_name] then @@ -148,8 +149,6 @@ local function do_load_module(host, module_name) api_instance.environment = pluginenv; setfenv(mod, pluginenv); - hosts[host].modules = modulemap[host]; - modulemap[host][module_name] = pluginenv; local ok, err = pcall(mod); if ok then @@ -161,15 +160,18 @@ local function do_load_module(host, module_name) end end - -- Use modified host, if the module set one - if api_instance.host == "*" and host ~= "*" then - modulemap[host][module_name] = nil; - modulemap["*"][module_name] = pluginenv; - api_instance:set_global(); + modulemap[pluginenv.module.host][module_name] = pluginenv; + if pluginenv.module.host == "*" then + if not pluginenv.module.global then -- COMPAT w/pre-0.9 + log("warn", "mod_%s: Setting module.host = '*' deprecated, call module:set_global() instead", module_name); + api_instance:set_global(); + end + else + hosts[host].modules[module_name] = pluginenv; end - else + end + if not ok then log("error", "Error initializing module '%s' on '%s': %s", module_name, host, err or "nil"); - do_unload_module(api_instance.host, module_name); -- Ignore error, module may be partially-loaded end return ok and pluginenv, err; end -- cgit v1.2.3 From 0270a3a90107621947d18bead0b5ed66054317ca Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 14 Mar 2012 21:39:02 +0000 Subject: portmanager: Add unregister_service(), and allow multiple services with the same name (they get queued) --- core/portmanager.lua | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 103c5d44..30597628 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -13,8 +13,8 @@ end --- Private state --- service_name -> service_info -local services = {}; +-- service_name -> { service_info, ... } +local services = setmetatable({}, { __index = function (t, k) rawset(t, k, {}); return rawget(t, k); end }); -- service_name, interface (string), port (number) local active_services = multitable.new(); @@ -55,7 +55,7 @@ module("portmanager", package.seeall); --- Public API function activate_service(service_name) - local service_info = services[service_name]; + local service_info = services[service_name][1]; if not service_info then return nil, "Unknown service: "..service_name; end @@ -102,6 +102,7 @@ function activate_service(service_name) end end log("info", "Activated service '%s'", service_name); + return true; end function deactivate(service_name) @@ -118,16 +119,35 @@ function deactivate(service_name) end function register_service(service_name, service_info) - services[service_name] = service_info; + table.insert(services[service_name], service_info); - if not active_services[service_name] then - activate_service(service_name); + if not active_services:get(service_name) then + log("debug", "No active service for %s, activating...", service_name); + local ok, err = activate_service(service_name); + if not ok then + log("error", "Failed to activate service '%s': %s", service_name, err or "unknown error"); + end end fire_event("service-added", { name = service_name, service = service_info }); return true; end +function unregister_service(service_name, service_info) + local service_info_list = services[service_name]; + for i, service in ipairs(service_info_list) do + if service == service_info then + table.remove(service_info_list, i); + end + end + if active_services[service_name] == service_info then + deactivate(service_name); + if #service_info_list > 0 then -- Other services registered with this name + activate(service_name); -- Re-activate with the next available one + end + end +end + function get_service(service_name) return services[service_name]; end -- cgit v1.2.3 From f70f82d6a711b3eb94e800baed00bb87c09eaecd Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 14 Mar 2012 21:39:45 +0000 Subject: portmanager: Support item-added/net-provider (global and shared modules only!) --- core/portmanager.lua | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 30597628..2870815c 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -52,6 +52,15 @@ end module("portmanager", package.seeall); +prosody.events.add_handler("item-added/net-provider", function (event) + local item = event.item; + register_service(item.name, item); +end); +prosody.events.add_handler("item-removed/net-provider", function (event) + local item = event.item; + unregister_service(item.name, item); +end); + --- Public API function activate_service(service_name) -- cgit v1.2.3 From dd638dc7173768121e53034170b4bf85943018c7 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 14 Mar 2012 21:40:14 +0000 Subject: portmanager: Fix log message when multiple services are configured to use the same port --- core/portmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 2870815c..a7ba8a49 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -95,7 +95,7 @@ function activate_service(service_name) for interface in bind_interfaces do for port in bind_ports do if not service_info.multiplex and #active_services:search(nil, interface, port) > 0 then - log("error", "Multiple services configured to listen on the same port: %s, %s", table.concat(active_services:search(nil, interface, port), ", "), service_name); + log("error", "Multiple services configured to listen on the same port ([%s]:%d): %s, %s", interface, port, active_services:search(nil, interface, port)[1][1].service.name or "", service_name or ""); else local handler, err = server.addserver(interface, port, listener, mode, ssl); if not handler then -- cgit v1.2.3 From 7366c85253a3e1dddb35f8eea2c2fd45996c7f1b Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 14 Mar 2012 23:44:24 +0000 Subject: portmanager: Fire service-removed on unregister --- core/portmanager.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index a7ba8a49..605e1e30 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -155,6 +155,7 @@ function unregister_service(service_name, service_info) activate(service_name); -- Re-activate with the next available one end end + fire_event("service-removed", { name = service_name, service = service_info }); end function get_service(service_name) -- cgit v1.2.3 From 775261ef27a572da6e1c1ccacf79f59f6ead58ef Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 15 Mar 2012 02:52:31 +0000 Subject: moduleapi: Add module:provides(), a shortcut to add an item with the current module's name --- core/moduleapi.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index b11fd7b3..2177378f 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -292,4 +292,18 @@ function api:handle_items(type, added_cb, removed_cb, existing) end end +function api:provides(name, item) + if not item then item = self.environment; end + if not item.name then + local item_name = module.name; + -- Strip a provider prefix to find the item name + -- (e.g. "auth_foo" -> "foo" for an auth provider) + if item_name:find(name.."_", 1, true) == 1 then + item_name = item_name:sub(#name+2); + end + item.name = item_name; + end + self:add_item(name, item); +end + return api; -- cgit v1.2.3 From 78cd9a0ddcb2e3af03173eeceec270ef804603ec Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 15 Mar 2012 02:53:05 +0000 Subject: moduleapi: Add module:send() as an alias for core_post_stanza() from the current host's origin --- core/moduleapi.lua | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 2177378f..a577c07a 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -22,6 +22,7 @@ local tonumber, tostring = tonumber, tostring; local prosody = prosody; local hosts = prosody.hosts; +local core_post_stanza = prosody.core_post_stanza; -- Registry of shared module data local shared_data = setmetatable({}, { __mode = "v" }); @@ -306,4 +307,8 @@ function api:provides(name, item) self:add_item(name, item); end +function api:send(stanza) + return core_post_stanza(hosts[self.host], stanza); +end + return api; -- cgit v1.2.3 From eafbf7d47eb4e65a8efb9b9daea112b470d3f4c8 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 15 Mar 2012 02:56:44 +0000 Subject: portmanager: Allow services to specify their config option prefix --- core/portmanager.lua | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 605e1e30..a87e14eb 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -68,19 +68,23 @@ function activate_service(service_name) if not service_info then return nil, "Unknown service: "..service_name; end + + local config_prefix = (service_info.config_prefix or service_name).."_"; + if config_prefix == "_" then + config_prefix = ""; + end - local bind_interfaces = set.new(config.get("*", service_name.."_interfaces") - or config.get("*", service_name.."_interface") -- COMPAT w/pre-0.9 + local bind_interfaces = set.new(config.get("*", config_prefix.."interfaces") + or config.get("*", config_prefix.."interface") -- COMPAT w/pre-0.9 or (service_info.private and default_local_interfaces) or config.get("*", "interfaces") or config.get("*", "interface") -- COMPAT w/pre-0.9 or service_info.default_interface -- COMPAT w/pre0.9 or default_interfaces); - local bind_ports = set.new(config.get("*", service_name.."_ports") - or (service_info.multiplex and config.get("*", "ports")) or service_info.default_ports or {service_info.default_port}); + local bind_ports = set.new(config.get("*", config_prefix.."ports") local listener = service_info.listener; local mode = listener.default_mode or "*a"; -- cgit v1.2.3 From 373fb34e948918f0a74732337e6357a92a59e669 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 15 Mar 2012 03:02:09 +0000 Subject: portmanager: Fix pre-0.9 compatibility by taking default_interface and default_port from the listener instead of service table --- core/portmanager.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index a87e14eb..a7c3c44e 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -69,6 +69,8 @@ function activate_service(service_name) return nil, "Unknown service: "..service_name; end + local listener = service_info.listener; + local config_prefix = (service_info.config_prefix or service_name).."_"; if config_prefix == "_" then config_prefix = ""; @@ -79,14 +81,13 @@ function activate_service(service_name) or (service_info.private and default_local_interfaces) or config.get("*", "interfaces") or config.get("*", "interface") -- COMPAT w/pre-0.9 - or service_info.default_interface -- COMPAT w/pre0.9 + or listener.default_interface -- COMPAT w/pre0.9 or default_interfaces); - or service_info.default_ports - or {service_info.default_port}); local bind_ports = set.new(config.get("*", config_prefix.."ports") + or service_info.default_ports + or {listener.default_port}); -- COMPAT w/pre-0.9 - local listener = service_info.listener; local mode = listener.default_mode or "*a"; local ssl; if service_info.encryption == "ssl" then -- cgit v1.2.3 From f0b8af1484581188305a3d0abac0f8b6c15bfb53 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 15 Mar 2012 03:02:36 +0000 Subject: portmanager: Remove check for service_info.multiplex (now implemented in mod_net_multiplex) --- core/portmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index a7c3c44e..b4ceaef9 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -99,7 +99,7 @@ function activate_service(service_name) for interface in bind_interfaces do for port in bind_ports do - if not service_info.multiplex and #active_services:search(nil, interface, port) > 0 then + if #active_services:search(nil, interface, port) > 0 then log("error", "Multiple services configured to listen on the same port ([%s]:%d): %s, %s", interface, port, active_services:search(nil, interface, port)[1][1].service.name or "", service_name or ""); else local handler, err = server.addserver(interface, port, listener, mode, ssl); -- cgit v1.2.3 From 0d6cb88a1eb002675334b16b5a3c627282cb2c61 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 15 Mar 2012 03:02:51 +0000 Subject: portmanager: Add get_registered_services() to the public API --- core/portmanager.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index b4ceaef9..914a8e2f 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -171,4 +171,8 @@ function get_active_services(...) return active_services; end +function get_registered_services() + return services; +end + return _M; -- cgit v1.2.3 From 60b203533dbbb0404d9641e6455aaf6dad916dcb Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 15 Mar 2012 16:29:30 +0000 Subject: portmanager: Support 'default_port' in service options --- core/portmanager.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 914a8e2f..c5bb936a 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -86,7 +86,9 @@ function activate_service(service_name) local bind_ports = set.new(config.get("*", config_prefix.."ports") or service_info.default_ports - or {listener.default_port}); -- COMPAT w/pre-0.9 + or {service_info.default_port + or listener.default_port -- COMPAT w/pre-0.9 + }); local mode = listener.default_mode or "*a"; local ssl; -- cgit v1.2.3 From fe16dde20be2082bb44788113d416ecb35955ad1 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 15 Mar 2012 19:09:24 +0000 Subject: loggingmanager, util.logger: Remove name sinks and the ability to filter logs by source name (lots of code, hardly used if at all, and possibly broken) --- core/loggingmanager.lua | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) (limited to 'core') diff --git a/core/loggingmanager.lua b/core/loggingmanager.lua index 426425c1..56a3ee2c 100644 --- a/core/loggingmanager.lua +++ b/core/loggingmanager.lua @@ -48,34 +48,12 @@ local logging_levels = { "debug", "info", "warn", "error" } local function add_rule(sink_config) local sink_maker = log_sink_types[sink_config.to]; if sink_maker then - if sink_config.levels and not sink_config.source then - -- Create sink - local sink = sink_maker(sink_config); - - -- Set sink for all chosen levels - for level in pairs(get_levels(sink_config.levels)) do - logger.add_level_sink(level, sink); - end - elseif sink_config.source and not sink_config.levels then - logger.add_name_sink(sink_config.source, sink_maker(sink_config)); - elseif sink_config.source and sink_config.levels then - local levels = get_levels(sink_config.levels); - local sink = sink_maker(sink_config); - logger.add_name_sink(sink_config.source, - function (name, level, ...) - if levels[level] then - return sink(name, level, ...); - end - end); - else - -- All sources - -- Create sink - local sink = sink_maker(sink_config); - - -- Set sink for all levels - for _, level in pairs(logging_levels) do - logger.add_level_sink(level, sink); - end + -- Create sink + local sink = sink_maker(sink_config); + + -- Set sink for all chosen levels + for level in pairs(get_levels(sink_config.levels or logging_levels)) do + logger.add_level_sink(level, sink); end else -- No such sink type -- cgit v1.2.3 From 9792c6566b3416e7aef11bd3628f15ca00418132 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 21 Apr 2012 20:00:30 +0100 Subject: modulemanager: Allow loading a module onto "*" (part-fixes #228) --- core/modulemanager.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index f9f3a8b8..f00532a0 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -117,13 +117,15 @@ end local function do_load_module(host, module_name) if not (host and module_name) then return nil, "insufficient-parameters"; - elseif not hosts[host] then + elseif not hosts[host] and host ~= "*"then return nil, "unknown-host"; end if not modulemap[host] then modulemap[host] = {}; - hosts[host].modules = modulemap[host]; + if host ~= "*" then + hosts[host].modules = modulemap[host]; + end end if modulemap[host][module_name] then -- cgit v1.2.3 From e0805574e18fddde821ba9ec6ade8f234f368f1b Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 21 Apr 2012 20:01:40 +0100 Subject: modulemanager: Use api_instance rather than pluginenv.module (same thing) --- core/modulemanager.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index f00532a0..f5173f00 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -162,9 +162,9 @@ local function do_load_module(host, module_name) end end - modulemap[pluginenv.module.host][module_name] = pluginenv; - if pluginenv.module.host == "*" then - if not pluginenv.module.global then -- COMPAT w/pre-0.9 + modulemap[api_instance.host][module_name] = pluginenv; + if api_instance.host == "*" then + if not api_instance.global then -- COMPAT w/pre-0.9 log("warn", "mod_%s: Setting module.host = '*' deprecated, call module:set_global() instead", module_name); api_instance:set_global(); end -- cgit v1.2.3 From bf4925029fade8287314c858029413aacc5a9a48 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 21 Apr 2012 20:02:45 +0100 Subject: modulemanager: Use modulemap rather than hosts[host] (fix for when host == "*") --- core/modulemanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index f5173f00..f7594cd9 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -169,7 +169,7 @@ local function do_load_module(host, module_name) api_instance:set_global(); end else - hosts[host].modules[module_name] = pluginenv; + modulemap[host][module_name] = pluginenv; end end if not ok then -- cgit v1.2.3 From 3f130834834b04f47b0c00bb5504e67e0744fa16 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 21 Apr 2012 20:04:07 +0100 Subject: modulemanager: Make module_has_method and module_call_method use rawget() --- core/modulemanager.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index f7594cd9..769041f9 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -261,12 +261,12 @@ function is_loaded(host, name) end function module_has_method(module, method) - return type(module.module[method]) == "function"; + return type(rawget(module.module, method)) == "function"; end function call_module_method(module, method, ...) - if module_has_method(module, method) then - local f = module.module[method]; + local f = rawget(module.module, method); + if type(f) == "function" then return pcall(f, ...); else return false, "no-such-method"; -- cgit v1.2.3 From f51d5c0bd00c83ed10eae136e95dc49a0d61b684 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 21 Apr 2012 20:09:03 +0100 Subject: modulemanager: Support for shared modules - function module.add_host(host_module) in a global module --- core/modulemanager.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 769041f9..e76f2624 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -132,6 +132,21 @@ local function do_load_module(host, module_name) log("warn", "%s is already loaded for %s, so not loading again", module_name, host); return nil, "module-already-loaded"; elseif modulemap["*"][module_name] then + local mod = modulemap["*"][module_name]; + if module_has_method(mod, "add_host") then + local _log = logger.init(host..":"..module_name); + local host_module_api = setmetatable({ + host = host, event_handlers = {}, items = {}; + _log = _log, log = function (self, ...) return _log(...); end; + },{ + __index = modulemap["*"][module_name].module; + }); + local ok, result, module_err = call_module_method(mod, "add_host", host_module_api); + if not ok or result == false then return nil, ok and module_err or result; end + local host_module = setmetatable({ module = host_module_api }, { __index = mod }); + modulemap[host][module_name] = host_module; + return host_module; + end return nil, "global-module-already-loaded"; end -- cgit v1.2.3 From 1894252bd4d000923088e4db37de91c0270b323a Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 21 Apr 2012 20:37:06 +0100 Subject: modulemanager: When a shared module becomes global, ensure it still gets loaded onto the original target host --- core/modulemanager.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index e76f2624..f263816b 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -183,8 +183,10 @@ local function do_load_module(host, module_name) log("warn", "mod_%s: Setting module.host = '*' deprecated, call module:set_global() instead", module_name); api_instance:set_global(); end - else - modulemap[host][module_name] = pluginenv; + if host ~= api_instance.host and module_has_method(pluginenv, "add_host") then + -- Now load the module again onto the host it was originally being loaded on + do_load_module(host, module_name); + end end end if not ok then -- cgit v1.2.3 From e0762790fdb004d359450908dc8b94b3725daf74 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 21 Apr 2012 23:11:59 +0200 Subject: core.certmanager: Log a message when a password is required but not supplied. fixes #214 --- core/certmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/certmanager.lua b/core/certmanager.lua index 8b82ac47..cccf3098 100644 --- a/core/certmanager.lua +++ b/core/certmanager.lua @@ -35,7 +35,7 @@ function create_context(host, mode, user_ssl_config) mode = mode; protocol = user_ssl_config.protocol or "sslv23"; key = resolve_path(config_path, user_ssl_config.key); - password = user_ssl_config.password; + password = user_ssl_config.password or function() log("error", "Encrypted certificate for %s requires 'ssl' 'password' to be set in config", host); end; certificate = resolve_path(config_path, user_ssl_config.certificate); capath = resolve_path(config_path, user_ssl_config.capath or default_capath); cafile = resolve_path(config_path, user_ssl_config.cafile); -- cgit v1.2.3 From 2d053569057683dbba3f960522d760cee3a1aae3 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 21 Apr 2012 22:52:15 +0100 Subject: moduleapi: Have modules internally store a reference to shared tables they use, to ensure they don't get collected while any module that had access to that table is still loaded (thanks Zash) --- core/moduleapi.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index a577c07a..7a3bd1c8 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -135,6 +135,7 @@ end -- 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 }; @@ -150,6 +151,7 @@ function api:shared(...) shared_data[path] = shared; end t_insert(data_array, shared); + self.shared_data[path] = shared; end return unpack(data_array); end -- cgit v1.2.3 From 6202ef36ecb18cfcf2aee207ccbccec24899513e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 21 Apr 2012 22:53:22 +0100 Subject: modulemanager: For children of shared modules, set module.environment to the empty environment for that module (useful to expose data or APIs at host.modules[module]) --- core/modulemanager.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index f263816b..aca314c0 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -144,6 +144,7 @@ local function do_load_module(host, module_name) local ok, result, module_err = call_module_method(mod, "add_host", host_module_api); if not ok or result == false then return nil, ok and module_err or result; end local host_module = setmetatable({ module = host_module_api }, { __index = mod }); + host_module.module.environment = host_module; modulemap[host][module_name] = host_module; return host_module; end -- cgit v1.2.3 From 5b5c8c83b395e259924d28f14b65133bb9a5791c Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Apr 2012 14:09:35 +0100 Subject: moduleapi: module:provides(): Fix usage of wrong table --- core/moduleapi.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 7a3bd1c8..61926017 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -298,7 +298,7 @@ end function api:provides(name, item) if not item then item = self.environment; end if not item.name then - local item_name = module.name; + local item_name = self.name; -- Strip a provider prefix to find the item name -- (e.g. "auth_foo" -> "foo" for an auth provider) if item_name:find(name.."_", 1, true) == 1 then -- cgit v1.2.3 From de1168f2885e614882839f754e039da55fdbe42f Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Apr 2012 14:10:04 +0100 Subject: moduleapi: module:provides(): Add "-provider" onto the key name --- core/moduleapi.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 61926017..2223f4d0 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -306,7 +306,7 @@ function api:provides(name, item) end item.name = item_name; end - self:add_item(name, item); + self:add_item(name.."-provider", item); end function api:send(stanza) -- cgit v1.2.3 From c40ee817429487a325e871da5ddc3e43eab19bb5 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Apr 2012 14:11:10 +0100 Subject: modulemanager: Report errors that happen when loading a shared module onto its original host --- core/modulemanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index aca314c0..f0648667 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -186,7 +186,7 @@ local function do_load_module(host, module_name) end if host ~= api_instance.host and module_has_method(pluginenv, "add_host") then -- Now load the module again onto the host it was originally being loaded on - do_load_module(host, module_name); + ok, err = do_load_module(host, module_name); end end end -- cgit v1.2.3 From 33ffda321d20938d4a28b15716d4f85871b4e6a7 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Apr 2012 14:15:07 +0100 Subject: moduleapi: module:depends(): Load shared modules onto the current host even if they are loaded globally already --- core/moduleapi.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 2223f4d0..e680f615 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -120,6 +120,9 @@ function api:depends(name) end); end local mod = modulemanager.get_module(self.host, name) or modulemanager.get_module("*", name); + if mod and mod.module.host == "*" and modulemanager.module_has_method(mod, "add_host") then + mod = nil; -- This is a shared module, so we still want to load it on our host + end if not mod then local err; mod, err = modulemanager.load(self.host, name); -- cgit v1.2.3 From 91d1035d7d501855d595d80aa985adfac6addfda Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Apr 2012 15:38:36 +0100 Subject: modulemanager: Set module.loaded = false on unload --- core/modulemanager.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index f0648667..bf1e1924 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -110,6 +110,7 @@ local function do_unload_module(host, name) end end end + mod.module.loaded = false; modulemap[host][name] = nil; return true; end -- cgit v1.2.3 From b6a2692f3f90ed40f7e9a5103b1bb141646a7259 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 23 Apr 2012 15:38:40 +0100 Subject: moduleapi: Add module:add_timer(delay, callback) - automatically halts the timer on module unload --- core/moduleapi.lua | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index e680f615..d16ee410 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -316,4 +316,11 @@ function api:send(stanza) return core_post_stanza(hosts[self.host], stanza); 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); +end + return api; -- cgit v1.2.3 From 64d127307adc8aa401d7ae4a964298cae4d08016 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Tue, 24 Apr 2012 16:00:20 +0100 Subject: portmanager: Add get_service_at(interface, port) and close(interface, port) --- core/portmanager.lua | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index c5bb936a..da238dba 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -126,9 +126,7 @@ function deactivate(service_name) if not active then return; end for interface, ports in pairs(active) do for port, active_service in pairs(ports) do - active_service:close(); - active_services:remove(service_name, interface, port, active_service); - log("debug", "Removed listening service %s from [%s]:%d", service_name, interface, port); + close(interface, port); end end log("info", "Deactivated service '%s'", service_name); @@ -165,6 +163,22 @@ function unregister_service(service_name, service_info) fire_event("service-removed", { name = service_name, service = service_info }); end +function close(interface, port) + local service, server = get_service_at(interface, port); + if not service then + return false, "port-not-open"; + end + server:close(); + active_services:remove(service.name, interface, port); + log("debug", "Removed listening service %s from [%s]:%d", service.name, interface, port); + return true; +end + +function get_service_at(interface, port) + local data = active_services:search(nil, interface, port)[1][1]; + return data.service, data.server; +end + function get_service(service_name) return services[service_name]; end -- cgit v1.2.3 From 44f95451b29fe017b5ba071c0544a4af57446b7c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Wed, 25 Apr 2012 14:53:54 +0200 Subject: portmanager: Fix selecting bind_interfaces from pre-0.9 config options. --- core/portmanager.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index da238dba..e2994308 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -76,13 +76,14 @@ function activate_service(service_name) config_prefix = ""; end - local bind_interfaces = set.new(config.get("*", config_prefix.."interfaces") + local bind_interfaces = config.get("*", config_prefix.."interfaces") or config.get("*", config_prefix.."interface") -- COMPAT w/pre-0.9 or (service_info.private and default_local_interfaces) or config.get("*", "interfaces") or config.get("*", "interface") -- COMPAT w/pre-0.9 or listener.default_interface -- COMPAT w/pre0.9 - or default_interfaces); + or default_interfaces + bind_interfaces = set.new(type(bind_interfaces)~="table" and {bind_interfaces} or bind_interfaces); local bind_ports = set.new(config.get("*", config_prefix.."ports") or service_info.default_ports -- cgit v1.2.3 From a7a312881838cbf9ed374907de2231636df37629 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Apr 2012 05:39:27 +0100 Subject: moduleapi: Add module:unhook_object_event() --- core/moduleapi.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index d16ee410..1f8c492d 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -73,6 +73,10 @@ function api:hook_object_event(object, event, handler, priority) return object.add_handler(event, handler, priority); end +function api:unhook_object_event(event, handler) + return object.remove_handler(event, handler); +end + function api:hook(event, handler, priority) return self:hook_object_event((hosts[self.host] or prosody).events, event, handler, priority); end -- cgit v1.2.3 From 45aab93d285912787385d4ee089624d5de71d431 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Apr 2012 07:04:59 +0100 Subject: moduleapi: module:depends(): Don't load shared modules onto the current host if the current host is '*'... --- core/moduleapi.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 1f8c492d..1c676bc3 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -124,7 +124,8 @@ function api:depends(name) end); end local mod = modulemanager.get_module(self.host, name) or modulemanager.get_module("*", name); - if mod and mod.module.host == "*" and modulemanager.module_has_method(mod, "add_host") then + if mod and mod.module.host == "*" and self.host ~= "*" + and modulemanager.module_has_method(mod, "add_host") then mod = nil; -- This is a shared module, so we still want to load it on our host end if not mod then -- cgit v1.2.3 From 898ec7a5cfb4dd5a0a589725e627966a8410e2ce Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Apr 2012 14:51:55 +0100 Subject: moduleapi: Fix parameters to unhook_object_event() --- core/moduleapi.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 1c676bc3..8e76a247 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -73,7 +73,7 @@ function api:hook_object_event(object, event, handler, priority) return object.add_handler(event, handler, priority); end -function api:unhook_object_event(event, handler) +function api:unhook_object_event(object, event, handler) return object.remove_handler(event, handler); end -- cgit v1.2.3 From ba7525b97ad5d49f0f3c0d6ee8777e00774e7e62 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Apr 2012 18:34:40 +0100 Subject: moduleapi: get_host_type(): Return nil for global modules (no host) --- core/moduleapi.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 8e76a247..8c57e301 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -42,7 +42,7 @@ function api:get_host() end function api:get_host_type() - return hosts[self.host].type; + return self.host ~= "*" and hosts[self.host].type or nil; end function api:set_global() -- cgit v1.2.3 From 1565fe93a2b0650262b7b6b92e0c40f66a866e96 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Apr 2012 18:35:33 +0100 Subject: moduleapi: Rename module:hook_stanza() -> module:hook_tag() (hook_stanza works for compat) --- core/moduleapi.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 8c57e301..9e8489c2 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -85,7 +85,7 @@ function api:hook_global(event, handler, priority) return self:hook_object_event(prosody.events, event, handler, priority); end -function api:hook_stanza(xmlns, name, handler, priority) +function api:hook_tag(xmlns, name, handler, priority) if not handler and type(name) == "function" then -- If only 2 options then they specified no xmlns xmlns, name, handler, priority = nil, xmlns, name, handler; @@ -95,6 +95,7 @@ function api:hook_stanza(xmlns, name, handler, priority) end return self:hook("stanza/"..(xmlns and (xmlns..":") or "")..name, function (data) return handler(data.origin, data.stanza, data); end, priority); end +api.hook_stanza = api.hook_tag; -- COMPAT w/pre-0.9 function api:require(lib) local f, n = pluginloader.load_code(self.name, lib..".lib.lua"); -- cgit v1.2.3 From 0181e189a3dad8882b80d277476d781912807228 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Apr 2012 21:37:45 +0100 Subject: modulemanager: Set module.environment before calling add_host, otherwise the module will get the parent's environment (thanks xnyhps and Maranda) --- core/modulemanager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index bf1e1924..5a97e5bf 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -142,10 +142,10 @@ local function do_load_module(host, module_name) },{ __index = modulemap["*"][module_name].module; }); + local host_module = setmetatable({ module = host_module_api }, { __index = mod }); + host_module_api.environment = host_module; local ok, result, module_err = call_module_method(mod, "add_host", host_module_api); if not ok or result == false then return nil, ok and module_err or result; end - local host_module = setmetatable({ module = host_module_api }, { __index = mod }); - host_module.module.environment = host_module; modulemap[host][module_name] = host_module; return host_module; end -- cgit v1.2.3 From 88637ab348548a4893b1bea2bb813c13d7c26f19 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Apr 2012 22:31:53 +0100 Subject: hostmanager: Convert host-deactivating event parameters to a table --- core/hostmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/hostmanager.lua b/core/hostmanager.lua index 330a0d03..91c6d4e1 100644 --- a/core/hostmanager.lua +++ b/core/hostmanager.lua @@ -102,7 +102,7 @@ function deactivate(host, reason) local host_session = hosts[host]; if not host_session then return nil, "The host "..tostring(host).." is not activated"; end log("info", "Deactivating host: %s", host); - prosody_events.fire_event("host-deactivating", host, host_session); + prosody_events.fire_event("host-deactivating", { host = host, host_session = host_session, reason = reason }); if type(reason) ~= "table" then reason = { condition = "host-gone", text = tostring(reason or "This server has stopped serving "..host) }; -- cgit v1.2.3 From 3547b00138ab3a8721b4872023f9f42944298815 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Apr 2012 22:32:04 +0100 Subject: hostmanager: Add some TODO comments --- core/hostmanager.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core') diff --git a/core/hostmanager.lua b/core/hostmanager.lua index 91c6d4e1..39af5732 100644 --- a/core/hostmanager.lua +++ b/core/hostmanager.lua @@ -109,6 +109,7 @@ function deactivate(host, reason) end -- Disconnect local users, s2s connections + -- TODO: These should move to mod_c2s and mod_s2s (how do they know they're being unloaded and not reloaded?) if host_session.sessions then for username, user in pairs(host_session.sessions) do for resource, session in pairs(user.sessions) do @@ -133,6 +134,7 @@ function deactivate(host, reason) end end + -- TODO: This should be done in modulemanager if host_session.modules then for module in pairs(host_session.modules) do modulemanager.unload(host, module); -- cgit v1.2.3 From f427f1c7d5f397979d4fedf49e1ccec67efd8ff6 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Apr 2012 22:33:38 +0100 Subject: hostmanager: Remove unused host_config parameter from host-activated event --- core/hostmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/hostmanager.lua b/core/hostmanager.lua index 39af5732..4b9fa240 100644 --- a/core/hostmanager.lua +++ b/core/hostmanager.lua @@ -94,7 +94,7 @@ function activate(host, host_config) end log((hosts_loaded_once and "info") or "debug", "Activated host: %s", host); - prosody_events.fire_event("host-activated", host, host_config); + prosody_events.fire_event("host-activated", host); return true; end -- cgit v1.2.3 From 05af8c8bfabc44445cc3ee7020cc1b6ca4fc58ed Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Apr 2012 22:36:35 +0100 Subject: modulemanager: Clear modulemap when a host is deactivated (thanks xnyhps) --- core/modulemanager.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 5a97e5bf..3829da57 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -82,6 +82,9 @@ function load_modules_for_host(host) end end prosody.events.add_handler("host-activated", load_modules_for_host); +prosody.events.add_handler("host-deactivated", function (host) + modulemap[host] = nil; +end); --- Private helpers --- -- cgit v1.2.3 From 958ffcf343279caf2f36469b3cdbba6b1e282f12 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 01:27:02 +0100 Subject: portmanager: Explicitly import some libraries --- core/portmanager.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index e2994308..afcfb797 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -1,5 +1,11 @@ +local config = require "core.configmanager"; +local server = require "net.server"; +local log = require "util.logger".init("portmanager"); local multitable = require "util.multitable"; +local set = require "util.set"; + +local prosody = prosody; local fire_event = prosody.events.fire_event; --- Config -- cgit v1.2.3 From d468617f5d11c8cc13ef82c5cff6d2e53e2f4019 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 01:27:15 +0100 Subject: portmanager: Add module() definition --- core/portmanager.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index afcfb797..8f26c57e 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -8,6 +8,8 @@ local set = require "util.set"; local prosody = prosody; local fire_event = prosody.events.fire_event; +module "portmanager"; + --- Config local default_interfaces = { "*" }; -- cgit v1.2.3 From 0ed5d7e68ca75f8c034f26f81c99a164290df21f Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 01:27:46 +0100 Subject: portmanager: Rename activate_service() to activate() (to match deactivate()) --- core/portmanager.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 8f26c57e..337b8f4b 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -71,7 +71,7 @@ end); --- Public API -function activate_service(service_name) +function activate(service_name) local service_info = services[service_name][1]; if not service_info then return nil, "Unknown service: "..service_name; @@ -146,7 +146,7 @@ function register_service(service_name, service_info) if not active_services:get(service_name) then log("debug", "No active service for %s, activating...", service_name); - local ok, err = activate_service(service_name); + local ok, err = activate(service_name); if not ok then log("error", "Failed to activate service '%s': %s", service_name, err or "unknown error"); end -- cgit v1.2.3 From 6bdcff0371cc2b12e2d318c46adc4685603496d2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 01:44:08 +0100 Subject: portmanager: Fix breakage (import ALL the functions) --- core/portmanager.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 337b8f4b..3bd143ef 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -5,6 +5,10 @@ local log = require "util.logger".init("portmanager"); local multitable = require "util.multitable"; local set = require "util.set"; +local table, package = table, package; +local setmetatable, rawset, rawget = setmetatable, rawset, rawget; +local type = type; + local prosody = prosody; local fire_event = prosody.events.fire_event; @@ -58,8 +62,6 @@ local function error_to_friendly_message(service_name, port, err) return friendly_message; end -module("portmanager", package.seeall); - prosody.events.add_handler("item-added/net-provider", function (event) local item = event.item; register_service(item.name, item); -- cgit v1.2.3 From 0ecb3e3e04d11b115666af849340fdd8de352bd7 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 02:18:17 +0100 Subject: modulemanager: Remove unused NULL declaration --- core/modulemanager.lua | 2 -- 1 file changed, 2 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 3829da57..40aa4ba2 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -47,8 +47,6 @@ local api = _G.require "core.moduleapi"; -- Module API container -- [host] = { [module] = module_env } local modulemap = { ["*"] = {} }; -local NULL = {}; - -- Load modules when a host is activated function load_modules_for_host(host) local component = config.get(host, "core", "component_module"); -- cgit v1.2.3 From 45fb895f1992c1cd602e93654b8c99ed25e51912 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 02:22:42 +0100 Subject: modulemanager: Remove unused function imports --- core/modulemanager.lua | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 40aa4ba2..8fdd5c1d 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -14,15 +14,9 @@ local pluginloader = require "util.pluginloader"; local hosts = hosts; local prosody = prosody; -local loadfile, pcall, xpcall = loadfile, pcall, xpcall; -local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; -local pairs, ipairs = pairs, ipairs; -local t_insert, t_concat = table.insert, table.concat; -local type = type; -local next = next; -local rawget = rawget; -local error = error; -local tostring, tonumber = tostring, tonumber; +local pcall, xpcall = pcall, xpcall; +local setmetatable, rawget, setfenv = setmetatable, rawget, setfenv; +local pairs, type, tostring = pairs, type, tostring; local debug_traceback = debug.traceback; local unpack, select = unpack, select; @@ -32,7 +26,7 @@ pcall = function(f, ...) return xpcall(function() return f(unpack(params, 1, n)) end, function(e) return tostring(e).."\n"..debug_traceback(); end); end -local array, set = require "util.array", require "util.set"; +local set = require "util.set"; local autoload_modules = {"presence", "message", "iq", "offline", "c2s", "s2s"}; local component_inheritable_modules = {"tls", "dialback", "iq"}; -- cgit v1.2.3 From e47a14da07a05d80473407b1a0521e54ba76e18b Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 02:24:41 +0100 Subject: moduleapi: Remove unused variable 'module_items' --- core/moduleapi.lua | 1 - 1 file changed, 1 deletion(-) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 9e8489c2..f23dc118 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -255,7 +255,6 @@ function api:get_option_set(name, ...) return set.new(value); end -local module_items = multitable_new(); function api:add_item(key, value) self.items = self.items or {}; self.items[key] = self.items[key] or {}; -- cgit v1.2.3 From 3ba967c53a6cd3570047c6e9416be1935eeb174a Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 02:25:54 +0100 Subject: hostmanager: Remove import of unused setmetatable --- core/hostmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/hostmanager.lua b/core/hostmanager.lua index 4b9fa240..a9db1a92 100644 --- a/core/hostmanager.lua +++ b/core/hostmanager.lua @@ -24,7 +24,7 @@ if not _G.prosody.incoming_s2s then end local incoming_s2s = _G.prosody.incoming_s2s; -local pairs, setmetatable, select = pairs, setmetatable, select; +local pairs, select = pairs, select; local tostring, type = tostring, type; module "hostmanager" -- cgit v1.2.3 From e25c402ab08bb19cf7e36ee12a139736583a91c5 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 02:40:36 +0100 Subject: moduleapi: Import util.timer --- core/moduleapi.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index f23dc118..703eb268 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -12,6 +12,7 @@ local array = require "util.array"; local set = require "util.set"; local logger = require "util.logger"; local pluginloader = require "util.pluginloader"; +local timer = require "util.timer"; local multitable_new = require "util.multitable".new; -- cgit v1.2.3 From 158675928e0fe7e40f18cfc27535cded124ec6be Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 03:25:40 +0100 Subject: storagemanager: Fix incorrect variable name --- core/storagemanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/storagemanager.lua b/core/storagemanager.lua index c96ef3ec..71e79271 100644 --- a/core/storagemanager.lua +++ b/core/storagemanager.lua @@ -47,7 +47,7 @@ prosody.events.add_handler("host-activated", initialize_host, 101); function load_driver(host, driver_name) if driver_name == "null" then - return null_storage_provider; + return null_storage_driver; end local driver = stores_available:get(host, driver_name); if driver then return driver; end -- cgit v1.2.3 From 37365a3a78089a8978414ce1eb6d8f5d7eb53e1f Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 14:35:52 +0100 Subject: usermanager: Add log error for use of COMPAT config option 'anonymous_login'. To be removed in next version. --- core/usermanager.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/usermanager.lua b/core/usermanager.lua index 9e5a016c..50aee701 100644 --- a/core/usermanager.lua +++ b/core/usermanager.lua @@ -41,7 +41,10 @@ function initialize_host(host) host_session.events.add_handler("item-added/auth-provider", function (event) local provider = event.item; local auth_provider = config.get(host, "core", "authentication") or default_provider; - if config.get(host, "core", "anonymous_login") then auth_provider = "anonymous"; end -- COMPAT 0.7 + if config.get(host, "core", "anonymous_login") then + log("error", "Deprecated config option 'anonymous_login'. Use authentication = 'anonymous' instead."); + auth_provider = "anonymous"; + end -- COMPAT 0.7 if provider.name == auth_provider then host_session.users = setmetatable(provider, provider_mt); end -- cgit v1.2.3 From e8d147c96a9cf84cae6a957adc16cb0a9cd11360 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 15:47:43 +0100 Subject: modulemanager: Fixes to handle circular dependencies in module:depends() --- core/modulemanager.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'core') diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 8fdd5c1d..90116166 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -139,9 +139,12 @@ local function do_load_module(host, module_name) }); local host_module = setmetatable({ module = host_module_api }, { __index = mod }); host_module_api.environment = host_module; - local ok, result, module_err = call_module_method(mod, "add_host", host_module_api); - if not ok or result == false then return nil, ok and module_err or result; end modulemap[host][module_name] = host_module; + local ok, result, module_err = call_module_method(mod, "add_host", host_module_api); + if not ok or result == false then + modulemap[host][module_name] = nil; + return nil, ok and module_err or result; + end return host_module; end return nil, "global-module-already-loaded"; @@ -164,6 +167,7 @@ local function do_load_module(host, module_name) setfenv(mod, pluginenv); + modulemap[host][module_name] = pluginenv; local ok, err = pcall(mod); if ok then -- Call module's "load" @@ -174,12 +178,13 @@ local function do_load_module(host, module_name) end end - modulemap[api_instance.host][module_name] = pluginenv; if api_instance.host == "*" then if not api_instance.global then -- COMPAT w/pre-0.9 log("warn", "mod_%s: Setting module.host = '*' deprecated, call module:set_global() instead", module_name); api_instance:set_global(); end + modulemap[host][module_name] = nil; + modulemap[api_instance.host][module_name] = pluginenv; if host ~= api_instance.host and module_has_method(pluginenv, "add_host") then -- Now load the module again onto the host it was originally being loaded on ok, err = do_load_module(host, module_name); @@ -187,6 +192,7 @@ local function do_load_module(host, module_name) end end if not ok then + modulemap[api_instance.host][module_name] = nil; log("error", "Error initializing module '%s' on '%s': %s", module_name, host, err or "nil"); end return ok and pluginenv, err; -- cgit v1.2.3 From 99d16ae1392d520312dd3fecf642cb60abe81b0e Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 18:45:04 +0100 Subject: portmanager: Ensure port is always a number (thanks Zash) --- core/portmanager.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 3bd143ef..5f53b61c 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -112,6 +112,7 @@ function activate(service_name) for interface in bind_interfaces do for port in bind_ports do + port = tonumber(port); if #active_services:search(nil, interface, port) > 0 then log("error", "Multiple services configured to listen on the same port ([%s]:%d): %s, %s", interface, port, active_services:search(nil, interface, port)[1][1].service.name or "", service_name or ""); else -- cgit v1.2.3 From 5455ac95160af590c203abf162411c76762117f1 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 19:38:51 +0100 Subject: portmanager: Import tonumber (thanks Zash) --- core/portmanager.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/portmanager.lua b/core/portmanager.lua index 5f53b61c..fed35987 100644 --- a/core/portmanager.lua +++ b/core/portmanager.lua @@ -7,7 +7,7 @@ local set = require "util.set"; local table, package = table, package; local setmetatable, rawset, rawget = setmetatable, rawset, rawget; -local type = type; +local type, tonumber = type, tonumber; local prosody = prosody; local fire_event = prosody.events.fire_event; -- cgit v1.2.3 From 570492f6278129b438e8f783563ad0473c1ef9bc Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Apr 2012 19:41:04 +0100 Subject: moduleapi: Add module:get_directory() to get module file's directory, and module:load_resource() to load a file relative to that directory --- core/moduleapi.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'core') diff --git a/core/moduleapi.lua b/core/moduleapi.lua index 703eb268..57367255 100644 --- a/core/moduleapi.lua +++ b/core/moduleapi.lua @@ -329,4 +329,14 @@ function api:add_timer(delay, callback) end); end +local path_sep = package.config:sub(1,1); +function api:get_directory() + return self.path and (self.path:gsub("%"..path_sep.."[^"..path_sep.."]*$", "")) or nil; +end + +function api:load_resource(path, mode) + path = config.resolve_relative_path(self:get_directory(), path); + return io.open(path, mode); +end + return api; -- cgit v1.2.3