core/hostmanager.lua

1
-- Prosody IM
2
-- Copyright (C) 2008-2010 Matthew Wild
3
-- Copyright (C) 2008-2010 Waqas Hussain
4
-- 
5
-- This project is MIT/X11 licensed. Please see the
6
-- COPYING file in the source package for more information.
7
--
8
 
9
local configmanager = require "core.configmanager";
10
local modulemanager = require "core.modulemanager";
11
local events_new = require "util.events".new;
12
local disco_items = require "util.multitable".new();
13
local NULL = {};
14
 
15
local uuid_gen = require "util.uuid".generate;
16
 
17
local log = require "util.logger".init("hostmanager");
18
 
19
local hosts = hosts;
20
local prosody_events = prosody.events;
21
if not _G.prosody.incoming_s2s then
22
	require "core.s2smanager";
23
end
24
local incoming_s2s = _G.prosody.incoming_s2s;
25
 
26
local pairs, setmetatable = pairs, setmetatable;
27
local tostring, type = tostring, type;
28
 
29
module "hostmanager"
30
 
31
local hosts_loaded_once;
32
 
33
local function load_enabled_hosts(config)
34
	local defined_hosts = config or configmanager.getconfig();
35
	local activated_any_host;
36
	
37
	for host, host_config in pairs(defined_hosts) do
38
		if host ~= "*" and host_config.core.enabled ~= false then
39
			if not host_config.core.component_module then
40
				activated_any_host = true;
41
			end
42
			activate(host, host_config);
43
		end
44
	end
45
	
46
	if not activated_any_host then
47
		log("error", "No active VirtualHost entries in the config file. This may cause unexpected behaviour as no modules will be loaded.");
48
	end
49
	
50
	prosody_events.fire_event("hosts-activated", defined_hosts);
51
	hosts_loaded_once = true;
52
end
53
 
54
prosody_events.add_handler("server-starting", load_enabled_hosts);
55
 
56
function activate(host, host_config)
57
	if hosts[host] then return nil, "The host "..host.." is already activated"; end
58
	host_config = host_config or configmanager.getconfig()[host];
59
	if not host_config then return nil, "Couldn't find the host "..tostring(host).." defined in the current config"; end
60
	local host_session = {
61
		host = host;
62
		s2sout = {};
63
		events = events_new();
64
		dialback_secret = configmanager.get(host, "core", "dialback_secret") or uuid_gen();
65
		disallow_s2s = configmanager.get(host, "core", "disallow_s2s");
66
	};
67
	if not host_config.core.component_module then -- host
68
		host_session.type = "local";
69
		host_session.sessions = {};
70
	else -- component
71
		host_session.type = "component";
72
	end
73
	hosts[host] = host_session;
74
	if not host:match("[@/]") then
75
		disco_items:set(host:match("%.(.*)") or "*", host, true);
76
	end
77
	for option_name in pairs(host_config.core) do
78
		if option_name:match("_ports$") or option_name:match("_interface$") then
79
			log("warn", "%s: Option '%s' has no effect for virtual hosts - put it in the server-wide section instead", host, option_name);
80
		end
81
	end
82
	
83
	log((hosts_loaded_once and "info") or "debug", "Activated host: %s", host);
84
	prosody_events.fire_event("host-activated", host, host_config);
85
	return true;
86
end
87
 
88
function deactivate(host, reason)
89
	local host_session = hosts[host];
90
	if not host_session then return nil, "The host "..tostring(host).." is not activated"; end
91
	log("info", "Deactivating host: %s", host);
92
	prosody_events.fire_event("host-deactivating", host, host_session);
93
	
94
	if type(reason) ~= "table" then
95
		reason = { condition = "host-gone", text = tostring(reason or "This server has stopped serving "..host) };
96
	end
97
	
98
	-- Disconnect local users, s2s connections
99
	if host_session.sessions then
100
		for username, user in pairs(host_session.sessions) do
101
			for resource, session in pairs(user.sessions) do
102
				log("debug", "Closing connection for %s@%s/%s", username, host, resource);
103
				session:close(reason);
104
			end
105
		end
106
	end
107
	if host_session.s2sout then
108
		for remotehost, session in pairs(host_session.s2sout) do
109
			if session.close then
110
				log("debug", "Closing outgoing connection to %s", remotehost);
111
				if session.srv_hosts then session.srv_hosts = nil; end
112
				session:close(reason);
113
			end
114
		end
115
	end
116
	for remote_session in pairs(incoming_s2s) do
117
		if remote_session.to_host == host then
118
			log("debug", "Closing incoming connection from %s", remote_session.from_host or "<unknown>");
119
			remote_session:close(reason);
120
		end
121
	end
122
 
123
	if host_session.modules then
124
		for module in pairs(host_session.modules) do
125
			modulemanager.unload(host, module);
126
		end
127
	end
128
 
129
	hosts[host] = nil;
130
	if not host:match("[@/]") then
131
		disco_items:remove(host:match("%.(.*)") or "*", host);
132
	end
133
	prosody_events.fire_event("host-deactivated", host);
134
	log("info", "Deactivated host: %s", host);
135
	return true;
136
end
137
 
138
function get_children(host)
139
	return disco_items:get(host) or NULL;
140
end
141
 
142
return _M;