Add hostmanager, and eventmanager
authorMatthew Wild <mwild1@gmail.com>
Sat, 6 Dec 2008 03:41:49 +0000 (03:41 +0000)
committerMatthew Wild <mwild1@gmail.com>
Sat, 6 Dec 2008 03:41:49 +0000 (03:41 +0000)
core/eventmanager.lua [new file with mode: 0644]
core/hostmanager.lua [new file with mode: 0644]
core/modulemanager.lua
core/sessionmanager.lua
prosody
tests/test.lua

diff --git a/core/eventmanager.lua b/core/eventmanager.lua
new file mode 100644 (file)
index 0000000..169be8e
--- /dev/null
@@ -0,0 +1,25 @@
+\r
+local t_insert = table.insert;\r
+local ipairs = ipairs;\r
+\r
+module "eventmanager"\r
+\r
+local event_handlers = {};\r
+\r
+function add_event_hook(name, handler)\r
+       if not event_handlers[name] then\r
+               event_handlers[name] = {};\r
+       end\r
+       t_insert(event_handlers[name] , handler);\r
+end\r
+\r
+function fire_event(name, ...)\r
+       local event_handlers = event_handlers[name];\r
+       if event_handlers then\r
+               for name, handler in ipairs(event_handlers) do\r
+                       handler(...);\r
+               end\r
+       end\r
+end\r
+\r
+return _M;
\ No newline at end of file
diff --git a/core/hostmanager.lua b/core/hostmanager.lua
new file mode 100644 (file)
index 0000000..a46da05
--- /dev/null
@@ -0,0 +1,49 @@
+
+hosts = {};
+
+local hosts = hosts;
+local configmanager = require "core.configmanager";
+local eventmanager = require "core.eventmanager";
+
+local pairs = pairs;
+
+module "hostmanager"
+
+local function load_enabled_hosts(config)
+       local defined_hosts = config or configmanager.getconfig();
+       
+       for host, host_config in pairs(defined_hosts) do
+               if host ~= "*" and (host_config.core.enabled == nil or host_config.core.enabled) then
+                       activate(host, host_config);
+               end
+       end
+end
+
+eventmanager.add_event_hook("server-starting", load_enabled_hosts);
+
+function activate(host, host_config)
+       hosts[host] = {type = "local", connected = true, sessions = {}, host = host, s2sout = {} };
+       
+       eventmanager.fire_event("host-activated", host, host_config);
+end
+
+function deactivate(host)
+       local host_session = hosts[host];
+       
+       eventmanager.fire_event("host-deactivating", host, host_session);
+       
+       -- Disconnect local users, s2s connections
+       for user, session_list in pairs(host_session.sessions) do
+               for resource, session in pairs(session_list) do
+                       session:close("host-gone");
+               end
+       end
+       -- Components?
+       
+       hosts[host] = nil;
+       eventmanager.fire_event("host-deactivated", host);
+end
+
+function getconfig(name)
+end
+
index 532a0f862512699eed79e53e029328bd51b19fa9..aa59b9da2062f97ef5676207b5343efae2c0826e 100644 (file)
@@ -24,6 +24,8 @@ local plugin_dir = CFG_PLUGINDIR or "./plugins/";
 local logger = require "util.logger";
 local log = logger.init("modulemanager");
 local addDiscoInfoHandler = require "core.discomanager".addDiscoInfoHandler;
+local eventmanager = require "core.eventmanager";
+
 
 local loadfile, pcall = loadfile, pcall;
 local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv;
@@ -182,28 +184,7 @@ function api:add_feature(xmlns)
        end);
 end
 
-
-do
-       local event_handlers = {};
-       
-       function api:add_event_hook(name, handler)
-               if not event_handlers[name] then
-                       event_handlers[name] = {};
-               end
-               t_insert(event_handlers[name] , handler);
-               self:log("debug", "Subscribed to %s", name);
-       end
-       
-       function fire_event(name, ...)
-               local event_handlers = event_handlers[name];
-               if event_handlers then
-                       for name, handler in ipairs(event_handlers) do
-                               handler(...);
-                       end
-               end
-       end
-end
-
+api.add_event_hook = eventmanager.add_event_hook;
 
 local function _add_handler(module, origin_type, tag, xmlns, handler)
        local handlers = stanza_handlers[module.host];
index 36111633418b9362e8d7db603afb43a1a763ea35..74a17fe5a5b174361feed539f087f5f464ac5cde 100644 (file)
@@ -35,6 +35,10 @@ local uuid_generate = require "util.uuid".generate;
 local rm_load_roster = require "core.rostermanager".load_roster;
 local config_get = require "core.configmanager".get;
 
+local fire_event = require "core.eventmanager".fire_event;
+
+local gettime = require "socket".gettime;
+
 local st = require "util.stanza";
 
 local newproxy = newproxy;
@@ -45,7 +49,7 @@ module "sessionmanager"
 local open_sessions = 0;
 
 function new_session(conn)
-       local session = { conn = conn,  priority = 0, type = "c2s_unauthed" };
+       local session = { conn = conn,  priority = 0, type = "c2s_unauthed", conntime = gettime() };
        if true then
                session.trace = newproxy(true);
                getmetatable(session.trace).__gc = function () open_sessions = open_sessions - 1; print("Session got collected, now "..open_sessions.." sessions are allocated") end;
@@ -109,6 +113,8 @@ function bind_resource(session, resource)
        if session.resource then return nil, "cancel", "already-bound", "Cannot bind multiple resources on a single connection"; end
        -- We don't support binding multiple resources
 
+       session.conntimetotal = gettime()-session.conntime;
+       
        resource = resource or uuid_generate();
        --FIXME: Randomly-generated resources must be unique per-user, and never conflict with existing
        
@@ -175,7 +181,7 @@ function streamopened(session, attr)
                                                
                                                
                                                local features = st.stanza("stream:features");
-                                               modulemanager.fire_event("stream-features", session, features);
+                                               fire_event("stream-features", session, features);
                                                
                                                send(features);
                                                
diff --git a/prosody b/prosody
index 08b0d93693b02293fad0b535074a70afd364825d..9fd5e4ff6c00c31409d8e909f6bf050a5e55d1a2 100755 (executable)
--- a/prosody
+++ b/prosody
@@ -68,29 +68,6 @@ do
        end
 end
 
-local data_path = config.get("*", "core", "data_path") or CFG_DATADIR or "data";
-local path_separator = "/"; if os.getenv("WINDIR") then path_separator = "\\" end
-local _mkdir = {}
-function mkdir(path)
-       path = path:gsub("/", path_separator);
-       --print("mkdir",path);
-       local x = io.popen("mkdir \""..path.."\" 2>&1"):read("*a");
-end
-function encode(s) return s and (s:gsub("%W", function (c) return string.format("%%%x", c:byte()); end)); end
-function mkdirs(host)
-       if not _mkdir[host] then
-               local host_dir = string.format("%s/%s", data_path, encode(host));
-               mkdir(host_dir);
-               mkdir(host_dir.."/accounts");
-               mkdir(host_dir.."/vcard");
-               mkdir(host_dir.."/roster");
-               mkdir(host_dir.."/private");
-               mkdir(host_dir.."/offline");
-               _mkdir[host] = true;
-       end
-end
-mkdir(data_path);
-
 require "util.datamanager".set_data_path(data_path);
 
 local server = require "net.server"
@@ -101,14 +78,6 @@ require "util.dependencies"
 sessions = {};
 hosts = {};
 
-local defined_hosts = config.getconfig();
-
-for host, host_config in pairs(defined_hosts) do
-       if host ~= "*" and (host_config.core.enabled == nil or host_config.core.enabled) then
-               hosts[host] = {type = "local", connected = true, sessions = {}, host = host, s2sout = {} };
-               mkdirs(host);
-       end
-end
 
 -- Load and initialise core modules --
 
@@ -116,6 +85,8 @@ require "util.import"
 require "core.xmlhandlers"
 require "core.rostermanager"
 require "core.offlinemessage"
+require "core.eventmanager"
+require "core.hostmanager"
 require "core.modulemanager"
 require "core.usermanager"
 require "core.sessionmanager"
@@ -126,12 +97,44 @@ pcall(require, "remdebug.engine");
 if remdebug then remdebug.engine.start() end
 ]]
 
-local start = require "net.connlisteners".start;
+local cl = require "net.connlisteners";
+
 require "util.stanza"
 require "util.jid"
 
 ------------------------------------------------------------------------
 
+------------- Begin code without a home ---------------------
+
+local data_path = config.get("*", "core", "data_path") or CFG_DATADIR or "data";
+local path_separator = "/"; if os.getenv("WINDIR") then path_separator = "\\" end
+local _mkdir = {}
+function mkdir(path)
+       path = path:gsub("/", path_separator);
+       --print("mkdir",path);
+       local x = io.popen("mkdir \""..path.."\" 2>&1"):read("*a");
+end
+function encode(s) return s and (s:gsub("%W", function (c) return string.format("%%%x", c:byte()); end)); end
+function mkdirs(host)
+       if not _mkdir[host] then
+               local host_dir = string.format("%s/%s", data_path, encode(host));
+               mkdir(host_dir);
+               mkdir(host_dir.."/accounts");
+               mkdir(host_dir.."/vcard");
+               mkdir(host_dir.."/roster");
+               mkdir(host_dir.."/private");
+               mkdir(host_dir.."/offline");
+               _mkdir[host] = true;
+       end
+end
+mkdir(data_path);
+
+eventmanager.add_event_hook("host-activated", mkdirs);
+
+----------- End of out-of-place code --------------
+
+eventmanager.fire_event("server-starting");
+
 -- Initialise modules
 
 for host in pairs(hosts) do
@@ -159,13 +162,17 @@ if global_ssl_ctx then
 end
 
 -- start listening on sockets
-start("xmppclient", { ssl = global_ssl_ctx })
-start("xmppserver", { ssl = global_ssl_ctx })
+cl.start("xmppclient", { ssl = global_ssl_ctx })
+cl.start("xmppserver", { ssl = global_ssl_ctx })
 
 if config.get("*", "core", "console_enabled") then
-       start("console")
+       if cl.get("console") then
+               cl.start("console")
+       else
+               log("error", "Console is enabled, but the console module appears not to be loaded");
+       end
 end
 
-modulemanager.fire_event("server-started");
+eventmanager.fire_event("server-started");
 
 server.loop();
index 0d69d08bcc9a25f640736c08a9ccf8d72d98dd8f..503ac4a19a5dac380431c31992c75018c14a9aec 100644 (file)
@@ -21,6 +21,7 @@
 
 function run_all_tests()
        dotest "util.jid"
+       dotest "util.multitable"
        dotest "core.stanza_router"
        dotest "core.s2smanager"
        dotest "core.configmanager"
@@ -40,14 +41,34 @@ function testlib_new_env(t)
        return setmetatable(t or {}, env_mt);
 end
 
-function assert_equal(a, b, message)
+function assert_equal(a, b, message, level)
        if not (a == b) then
-               error("\n   assert_equal failed: "..tostring(a).." ~= "..tostring(b)..(message and ("\n   Message: "..message) or ""), 2);
+               error("\n   assert_equal failed: "..tostring(a).." ~= "..tostring(b)..(message and ("\n   Message: "..message) or ""), (level or 1) + 1);
        elseif verbosity >= 4 then
                print("assert_equal succeeded: "..tostring(a).." == "..tostring(b));
        end
 end
 
+function assert_table(a, message, level)
+       assert_equal(type(a), "table", message, (level or 1) + 1);
+end
+function assert_function(a, message, level)
+       assert_equal(type(a), "function", message, (level or 1) + 1);
+end
+function assert_string(a, message, level)
+       assert_equal(type(a), "string", message, (level or 1) + 1);
+end
+function assert_boolean(a, message)
+       assert_equal(type(a), "boolean", message);
+end
+function assert_is(a, message)
+       assert_equal(not not a, true, message);
+end
+function assert_is_not(a, message)
+       assert_equal(not not a, false, message);
+end
+
+
 function dosingletest(testname, fname)
        local tests = setmetatable({}, { __index = _G });
        tests.__unit = testname;