diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/loggingmanager.lua | 6 | ||||
-rw-r--r-- | core/modulemanager.lua | 83 | ||||
-rw-r--r-- | core/objectmanager.lua | 120 | ||||
-rw-r--r-- | core/s2smanager.lua | 23 | ||||
-rw-r--r-- | core/sessionmanager.lua | 39 | ||||
-rw-r--r-- | core/stanza_router.lua | 2 |
6 files changed, 187 insertions, 86 deletions
diff --git a/core/loggingmanager.lua b/core/loggingmanager.lua index c26fdc71..4154e1a7 100644 --- a/core/loggingmanager.lua +++ b/core/loggingmanager.lua @@ -17,6 +17,12 @@ local math_max, rep = math.max, string.rep; local os_date, os_getenv = os.date, os.getenv; local getstyle, getstring = require "util.termcolours".getstyle, require "util.termcolours".getstring; +if os.getenv("__FLUSH_LOG") then + local io_flush = io.flush; + local _io_write = io_write; + io_write = function(...) _io_write(...); io_flush(); end +end + local config = require "core.configmanager"; local eventmanager = require "core.eventmanager"; local logger = require "util.logger"; diff --git a/core/modulemanager.lua b/core/modulemanager.lua index 9cd56187..d1f7d413 100644 --- a/core/modulemanager.lua +++ b/core/modulemanager.lua @@ -28,7 +28,9 @@ local type = type; local next = next; local rawget = rawget; local error = error; -local tostring = tostring; +local tostring, tonumber = tostring, tonumber; + +local array, set = require "util.array", require "util.set"; local autoload_modules = {"presence", "message", "iq"}; @@ -400,6 +402,85 @@ function api:get_option(name, default_value) return value; end +function api:get_option_string(...) + local value = self:get_option(...); + 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) diff --git a/core/objectmanager.lua b/core/objectmanager.lua index e96cbd90..293622c9 100644 --- a/core/objectmanager.lua +++ b/core/objectmanager.lua @@ -6,63 +6,63 @@ -- COPYING file in the source package for more information. -- -
-local new_multitable = require "util.multitable".new;
-local t_insert = table.insert;
-local t_concat = table.concat;
-local tostring = tostring;
-local unpack = unpack;
-local pairs = pairs;
-local error = error;
-local type = type;
-local _G = _G;
-
-local data = new_multitable();
-
-module "objectmanager"
-
-function set(...)
- return data:set(...);
-end
-function remove(...)
- return data:remove(...);
-end
-function get(...)
- return data:get(...);
-end
-
-local function get_path(path)
- if type(path) == "table" then return path; end
- local s = {};
- for part in tostring(path):gmatch("[%w_]+") do
- t_insert(s, part);
- end
- return s;
-end
-
-function get_object(path)
- path = get_path(path)
- return data:get(unpack(path)), path;
-end
-function set_object(path, object)
- path = get_path(path);
- data:set(unpack(path), object);
-end
-
-data:set("ls", function(_dir)
- local obj, dir = get_object(_dir);
- if not obj then error("object not found: " .. t_concat(dir, '/')); end
- local r = {};
- if type(obj) == "table" then
- for key, val in pairs(obj) do
- r[key] = type(val);
- end
- end
- return r;
-end);
-data:set("get", get_object);
-data:set("set", set_object);
-data:set("echo", function(...) return {...}; end);
-data:set("_G", _G);
-
-return _M;
+ +local new_multitable = require "util.multitable".new; +local t_insert = table.insert; +local t_concat = table.concat; +local tostring = tostring; +local unpack = unpack; +local pairs = pairs; +local error = error; +local type = type; +local _G = _G; + +local data = new_multitable(); + +module "objectmanager" + +function set(...) + return data:set(...); +end +function remove(...) + return data:remove(...); +end +function get(...) + return data:get(...); +end + +local function get_path(path) + if type(path) == "table" then return path; end + local s = {}; + for part in tostring(path):gmatch("[%w_]+") do + t_insert(s, part); + end + return s; +end + +function get_object(path) + path = get_path(path) + return data:get(unpack(path)), path; +end +function set_object(path, object) + path = get_path(path); + data:set(unpack(path), object); +end + +data:set("ls", function(_dir) + local obj, dir = get_object(_dir); + if not obj then error("object not found: " .. t_concat(dir, '/')); end + local r = {}; + if type(obj) == "table" then + for key, val in pairs(obj) do + r[key] = type(val); + end + end + return r; +end); +data:set("get", get_object); +data:set("set", set_object); +data:set("echo", function(...) return {...}; end); +data:set("_G", _G); + +return _M; diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 3613707c..666022d1 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -79,15 +79,15 @@ local function bounce_sendq(session) 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" and ((not data.xmlns) or data.xmlns == "jabber:client" or data.xmlns == "jabber:server") then + if host.type == "s2sout_unauthed" and (data.name ~= "db:verify" or not host.dialback_key) and ((not data.xmlns) or data.xmlns == "jabber:client" or data.xmlns == "jabber:server") then (host.log or log)("debug", "trying to send over unauthed s2sout to "..to_host); - if not host.notopen and not host.dialback_key and host.sends2s then - host.log("debug", "dialback had not been initiated"); - initiate_dialback(host); - end -- Queue stanza until we are able to send it if host.sendq then t_insert(host.sendq, {tostring(data), st.reply(data)}); @@ -110,6 +110,7 @@ function send_to_host(from_host, to_host, data) 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), st.reply(data)} }; log("debug", "stanza [%s] queued until connection complete", tostring(data.name)); @@ -131,7 +132,7 @@ function new_incoming(conn) open_sessions = open_sessions + 1; local w, log = conn.write, logger_init("s2sin"..tostring(conn):match("[a-f0-9]+$")); session.log = log; - session.sends2s = function (t) log("debug", "sending: %s", tostring(t)); w(tostring(t)); end + session.sends2s = function (t) log("debug", "sending: %s", t.top_tag and t:top_tag() or t:match("^([^>]*>?)")); w(conn, tostring(t)); end incoming_s2s[session] = true; add_task(connect_timeout, function () if session.conn ~= conn or @@ -159,7 +160,7 @@ function new_outgoing(from_host, to_host) host_session.log = log; end - -- This is the first call, can't fail (the first step is DNS lookup) + -- Kick the connection attempting machine attempt_connection(host_session); if not host_session.sends2s then @@ -187,6 +188,10 @@ function attempt_connection(host_session, err) local from_host, to_host = host_session.from_host, host_session.to_host; local connect_host, connect_port = 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; @@ -316,9 +321,9 @@ function make_connect(host_session, connect_host, connect_port) cl.register_outgoing(conn, host_session); local w, log = conn.write, host_session.log; - host_session.sends2s = function (t) log("debug", "sending: %s", tostring(t)); w(tostring(t)); end + host_session.sends2s = function (t) log("debug", "sending: %s", (t.top_tag and t:top_tag()) or t:match("^[^>]*>?")); w(conn, tostring(t)); end - conn.write(format([[<stream:stream xmlns='jabber:server' xmlns:db='jabber:server:dialback' xmlns:stream='http://etherx.jabber.org/streams' from='%s' to='%s' version='1.0' xml:lang='en'>]], from_host, to_host)); + conn:write(format([[<stream:stream xmlns='jabber:server' xmlns:db='jabber:server:dialback' xmlns:stream='http://etherx.jabber.org/streams' from='%s' to='%s' version='1.0' xml:lang='en'>]], from_host, to_host)); log("debug", "Connection attempt in progress..."); add_task(connect_timeout, function () if host_session.conn ~= conn or diff --git a/core/sessionmanager.lua b/core/sessionmanager.lua index 08e70d44..69160af7 100644 --- a/core/sessionmanager.lua +++ b/core/sessionmanager.lua @@ -10,7 +10,6 @@ local tonumber, tostring = tonumber, tostring; local ipairs, pairs, print, next= ipairs, pairs, print, next; -local collectgarbage = collectgarbage; local format = import("string", "format"); local hosts = hosts; @@ -50,8 +49,8 @@ function new_session(conn) open_sessions = open_sessions + 1; log("debug", "open sessions now: ".. open_sessions); local w = conn.write; - session.send = function (t) w(tostring(t)); end - session.ip = conn.ip(); + session.send = function (t) w(conn, tostring(t)); end + session.ip = conn:ip(); local conn_name = "c2s"..tostring(conn):match("[a-f0-9]+$"); session.log = logger.init(conn_name); @@ -201,22 +200,32 @@ function streamclosed(session) end function send_to_available_resources(user, host, stanza) + local jid = user.."@"..host; local count = 0; - local to = stanza.attr.to; - stanza.attr.to = nil; - local h = hosts[host]; - if h and h.type == "local" then - local u = h.sessions[user]; - if u then - for k, session in pairs(u.sessions) do - if session.presence then - session.send(stanza); - count = count + 1; - end + local user = bare_sessions[jid]; + if user then + for k, session in pairs(user.sessions) do + if session.presence then + session.send(stanza); + count = count + 1; + end + end + end + return count; +end + +function send_to_interested_resources(user, host, stanza) + local jid = user.."@"..host; + local count = 0; + local user = bare_sessions[jid]; + if user then + for k, session in pairs(user.sessions) do + if session.interested then + session.send(stanza); + count = count + 1; end end end - stanza.attr.to = to; return count; end diff --git a/core/stanza_router.lua b/core/stanza_router.lua index 00c37ed7..ad312b85 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -180,7 +180,7 @@ function core_route_stanza(origin, stanza) local xmlns = stanza.attr.xmlns; --stanza.attr.xmlns = "jabber:server"; stanza.attr.xmlns = nil; - log("debug", "sending s2s stanza: %s", tostring(stanza)); + 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 stanza.attr.xmlns = xmlns; -- reset else |