aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/componentmanager.lua12
-rw-r--r--core/modulemanager.lua1
-rw-r--r--core/presencemanager.lua2
-rw-r--r--core/stanza_router.lua67
-rw-r--r--plugins/mod_muc.lua30
5 files changed, 71 insertions, 41 deletions
diff --git a/core/componentmanager.lua b/core/componentmanager.lua
index 0d61bbb1..04909a07 100644
--- a/core/componentmanager.lua
+++ b/core/componentmanager.lua
@@ -27,21 +27,13 @@ function load_enabled_components(config)
for host, host_config in pairs(defined_hosts) do
if host ~= "*" and ((host_config.core.enabled == nil or host_config.core.enabled) and type(host_config.core.component_module) == "string") then
- hosts[host] = { type = "component", host = host, connected = true, s2sout = {} };
- modulemanager.load(host, "dialback");
+ hosts[host] = { type = "component", host = host, connected = false, s2sout = {} };
local ok, err = modulemanager.load(host, host_config.core.component_module);
if not ok then
log("error", "Error loading %s component %s: %s", tostring(host_config.core.component_module), tostring(host), tostring(err));
else
log("info", "Activated %s component: %s", host_config.core.component_module, host);
end
-
- local ok, component_handler = modulemanager.call_module_method(modulemanager.get_module(host, host_config.core.component_module), "load_component");
- if not ok then
- log("error", "Error loading %s component %s: %s", tostring(host_config.core.component_module), tostring(host), tostring(component_handler));
- else
- components[host] = component_handler;
- end
end
end
end
@@ -63,7 +55,7 @@ function handle_stanza(origin, stanza)
end
function register_component(host, component)
- if not hosts[host] then
+ if not hosts[host] or (hosts[host].type == 'component' and not hosts[host].connected) then
-- TODO check for host well-formedness
components[host] = component;
hosts[host] = { type = "component", host = host, connected = true, s2sout = {} };
diff --git a/core/modulemanager.lua b/core/modulemanager.lua
index 12cf9ce8..5afe3144 100644
--- a/core/modulemanager.lua
+++ b/core/modulemanager.lua
@@ -112,6 +112,7 @@ function load(host, module_name, config)
local pluginenv = setmetatable({ module = api_instance }, { __index = _G });
setfenv(mod, pluginenv);
+ if not hosts[host] then hosts[host] = { type = "component", host = host, connected = false, s2sout = {} }; end
local success, ret = pcall(mod);
if not success then
diff --git a/core/presencemanager.lua b/core/presencemanager.lua
index 3a216d7c..8fdf3612 100644
--- a/core/presencemanager.lua
+++ b/core/presencemanager.lua
@@ -97,7 +97,7 @@ function handle_normal_presence(origin, stanza, core_route_stanza)
if stanza.attr.type == "unavailable" then
origin.presence = nil;
if origin.directed then
- for _, jid in ipairs(origin.directed) do
+ for jid in pairs(origin.directed) do
stanza.attr.to = jid;
core_route_stanza(origin, stanza);
end
diff --git a/core/stanza_router.lua b/core/stanza_router.lua
index 89e6a77f..a8de6b4a 100644
--- a/core/stanza_router.lua
+++ b/core/stanza_router.lua
@@ -34,6 +34,8 @@ local t_concat = table.concat;
local t_insert = table.insert;
local tonumber = tonumber;
local s_find = string.find;
+local pairs = pairs;
+local ipairs = ipairs;
local jid_split = require "util.jid".split;
local jid_prepped_split = require "util.jid".prepped_split;
@@ -105,6 +107,11 @@ function core_process_stanza(origin, stanza)
return; -- FIXME what should we do here? does this work with subdomains?
end
end
+ if origin.type == "c2s" and stanza.name == "presence" and to ~= nil and not(origin.roster[to_bare] and (origin.roster[to_bare].subscription == "both" or origin.roster[to_bare].subscription == "from")) then -- directed presence
+ origin.directed = origin.directed or {};
+ origin.directed[to] = true;
+ --t_insert(origin.directed, to); -- FIXME does it make more sense to add to_bare rather than to?
+ end
if not to then
core_handle_stanza(origin, stanza);
elseif hosts[to] and hosts[to].type == "local" then -- directed at a local server
@@ -122,10 +129,6 @@ function core_process_stanza(origin, stanza)
elseif origin.type ~= "c2s" and stanza.name == "iq" and not resource then -- directed at bare JID
core_handle_stanza(origin, stanza);
else
- if origin.type == "c2s" and stanza.name == "presence" and to ~= nil and not(origin.roster[to_bare] and (origin.roster[to_bare].subscription == "both" or origin.roster[to_bare].subscription == "from")) then
- origin.directed = origin.directed or {};
- t_insert(origin.directed, to); -- FIXME does it make more sense to add to_bare rather than to?
- end
core_route_stanza(origin, stanza);
end
else
@@ -177,6 +180,14 @@ function core_route_stanza(origin, stanza)
origin = origin or hosts[from_host];
if not origin then return false; end
+ if hosts[to] and hosts[to].type == "component" then -- hack to allow components to handle node@server/resource and server/resource
+ return component_handle_stanza(origin, stanza);
+ elseif hosts[to_bare] and hosts[to_bare].type == "component" then -- hack to allow components to handle node@server
+ return component_handle_stanza(origin, stanza);
+ elseif hosts[host] and hosts[host].type == "component" then -- directed at a component
+ return component_handle_stanza(origin, stanza);
+ end
+
if stanza.name == "presence" and (stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable") then resource = nil; end
local host_session = hosts[host]
@@ -199,25 +210,36 @@ function core_route_stanza(origin, stanza)
end
end
elseif stanza.name == "message" then -- select a resource to recieve message
- local priority = 0;
- local recipients = {};
- for _, session in pairs(user.sessions) do -- find resource with greatest priority
- local p = session.priority or -1;
- if p > priority then
- priority = p;
- recipients = {session};
- elseif p == priority then
- t_insert(recipients, session);
+ stanza.attr.to = to_bare;
+ if stanza.attr.type == 'headline' then
+ for _, session in pairs(user.sessions) do -- find resource with greatest priority
+ if session.presence and session.priority >= 0 then
+ session.send(stanza);
+ end
+ end
+ else
+ local priority = 0;
+ local recipients = {};
+ for _, session in pairs(user.sessions) do -- find resource with greatest priority
+ if session.presence then
+ local p = session.priority;
+ if p > priority then
+ priority = p;
+ recipients = {session};
+ elseif p == priority then
+ t_insert(recipients, session);
+ end
+ end
+ end
+ local count = 0;
+ for _, session in ipairs(recipients) do
+ session.send(stanza);
+ count = count + 1;
+ end
+ if count == 0 and (stanza.attr.type == "chat" or stanza.attr.type == "normal" or not stanza.attr.type) then
+ offlinemanager.store(node, host, stanza);
+ -- TODO deal with storage errors
end
- end
- local count = 0;
- for _, session in pairs(recipients) do
- session.send(stanza);
- count = count + 1;
- end
- if count == 0 then
- offlinemanager.store(node, host, stanza);
- -- TODO deal with storage errors
end
else
-- TODO send IQ error
@@ -237,6 +259,7 @@ function core_route_stanza(origin, stanza)
-- TODO send unavailable presence or unsubscribed
end
elseif stanza.name == "message" then -- FIXME if full jid, then send out to resources with highest priority
+ stanza.attr.to = to_bare; -- TODO not in RFC, but seems obvious. Should discuss on the mailing list.
if stanza.attr.type == "chat" or stanza.attr.type == "normal" or not stanza.attr.type then
offlinemanager.store(node, host, stanza);
-- FIXME don't store messages with only chat state notifications
diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua
index 602fb5bc..bd36bd8f 100644
--- a/plugins/mod_muc.lua
+++ b/plugins/mod_muc.lua
@@ -7,14 +7,15 @@ local jid_bare = require "util.jid".bare;
local st = require "util.stanza";
local log = require "util.logger".init("mod_muc");
local multitable_new = require "util.multitable".new;
+local t_insert, t_remove = table.insert, table.remove;
if module:get_host_type() ~= "component" then
error("MUC should be loaded as a component, please see http://prosody.im/doc/components", 0);
end
local muc_domain = module:get_host();
-
local muc_name = "MUCMUCMUC!!!";
+local history_length = 20;
-- room_name -> room
-- occupant_room_nick -> data
@@ -30,6 +31,7 @@ local jid_nick = multitable_new(); -- real jid -> room's jid -> room nick
-- subject - the room's subject
-- non-anonymous = true|nil
-- persistent = true|nil
+ -- history = {preserialized stanzas}
local rooms_info = multitable_new();
local persist_list = datamanager.load(nil, muc_domain, 'room_list') or {};
@@ -131,6 +133,15 @@ function broadcast_message(from, room, subject, body)
stanza.attr.to = o_data.jid;
core_route_stanza(component, stanza);
end
+ if not subject and body then -- add to history
+ local history = rooms_info:get(room, 'history');
+ if not history then history = {}; rooms_info:set(room, 'history', history); end
+ -- stanza = st.deserialize(st.preserialize(stanza));
+ stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = muc_domain, stamp = datetime.datetime()}):up(); -- XEP-0203
+ stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated)
+ t_insert(history, st.preserialize(stanza));
+ while #history > history_length do t_remove(history, 1) end
+ end
end
end
@@ -200,7 +211,14 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc
end
end
broadcast_presence(nil, to, room);
- -- TODO send discussion history
+ local history = rooms_info:get(room, 'history'); -- send discussion history
+ if history then
+ for _, msg in ipairs(history) do
+ msg = st.deserialize(msg);
+ msg.attr.to=from;
+ core_route_stanza(component, msg);
+ end
+ end
if rooms_info:get(room, 'subject') then
core_route_stanza(component, st.message({type='groupchat', from=room, to=from}):tag("subject"):text(rooms_info:get(room, 'subject')));
end
@@ -266,7 +284,7 @@ function handle_to_domain(origin, stanza)
end
end
-function handle_stanza(origin, stanza)
+register_component(muc_domain, function(origin, stanza)
local to_node, to_host, to_resource = jid_split(stanza.attr.to);
if stanza.name == "presence" and stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" then
if type == "error" or type == "result" then return; end
@@ -282,11 +300,7 @@ function handle_stanza(origin, stanza)
if type == "error" or type == "result" then return; end
handle_to_domain(origin, stanza);
end
-end
-
-module.load_component = function()
- return handle_stanza; -- Return the function that we want to handle incoming stanzas
-end
+end);
module.unload = function()
deregister_component(muc_domain);