aboutsummaryrefslogtreecommitdiffstats
path: root/core/rostermanager.lua
diff options
context:
space:
mode:
Diffstat (limited to 'core/rostermanager.lua')
-rw-r--r--core/rostermanager.lua51
1 files changed, 45 insertions, 6 deletions
diff --git a/core/rostermanager.lua b/core/rostermanager.lua
index 61b08002..7b104339 100644
--- a/core/rostermanager.lua
+++ b/core/rostermanager.lua
@@ -12,6 +12,7 @@
local log = require "util.logger".init("rostermanager");
local new_id = require "util.id".short;
+local new_cache = require "util.cache".new;
local pairs = pairs;
local tostring = tostring;
@@ -111,6 +112,23 @@ local function load_roster(username, host)
else -- Attempt to load roster for non-loaded user
log("debug", "load_roster: loading for offline user: %s", jid);
end
+ local roster_cache = hosts[host] and hosts[host].roster_cache;
+ if not roster_cache then
+ if hosts[host] then
+ roster_cache = new_cache(1024);
+ hosts[host].roster_cache = roster_cache;
+ end
+ else
+ roster = roster_cache:get(jid);
+ if roster then
+ log("debug", "load_roster: cache hit");
+ roster_cache:set(jid, roster);
+ if user then user.roster = roster; end
+ return roster;
+ else
+ log("debug", "load_roster: cache miss, loading from storage");
+ end
+ end
local roster_store = storagemanager.open(host, "roster", "keyval");
local data, err = roster_store:get(username);
roster = data or {};
@@ -134,6 +152,10 @@ local function load_roster(username, host)
if not err then
hosts[host].events.fire_event("roster-load", { username = username, host = host, roster = roster });
end
+ if roster_cache and not user then
+ log("debug", "load_roster: caching loaded roster");
+ roster_cache:set(jid, roster);
+ end
return roster, err;
end
@@ -263,15 +285,15 @@ end
function is_contact_pending_in(username, host, jid)
local roster = load_roster(username, host);
- return roster[false].pending[jid];
+ return roster[false].pending[jid] ~= nil;
end
-local function set_contact_pending_in(username, host, jid)
+local function set_contact_pending_in(username, host, jid, stanza)
local roster = load_roster(username, host);
local item = roster[jid];
if item and (item.subscription == "from" or item.subscription == "both") then
return; -- false
end
- roster[false].pending[jid] = true;
+ roster[false].pending[jid] = st.is_stanza(stanza) and st.preserialize(stanza) or true;
return save_roster(username, host, roster, jid);
end
function is_contact_pending_out(username, host, jid)
@@ -279,6 +301,11 @@ function is_contact_pending_out(username, host, jid)
local item = roster[jid];
return item and item.ask;
end
+local function is_contact_preapproved(username, host, jid)
+ local roster = load_roster(username, host);
+ local item = roster[jid];
+ return item and (item.approved == "true");
+end
local function set_contact_pending_out(username, host, jid) -- subscribe
local roster = load_roster(username, host);
local item = roster[jid];
@@ -309,9 +336,10 @@ local function unsubscribe(username, host, jid)
return save_roster(username, host, roster, jid);
end
local function subscribed(username, host, jid)
+ local roster = load_roster(username, host);
+ local item = roster[jid];
+
if is_contact_pending_in(username, host, jid) then
- local roster = load_roster(username, host);
- local item = roster[jid];
if not item then -- FIXME should roster item be auto-created?
item = {subscription = "none", groups = {}};
roster[jid] = item;
@@ -323,7 +351,17 @@ local function subscribed(username, host, jid)
end
roster[false].pending[jid] = nil;
return save_roster(username, host, roster, jid);
- end -- TODO else implement optional feature pre-approval (ask = subscribed)
+ elseif not item or item.subscription == "none" or item.subscription == "to" then
+ -- Contact is not subscribed and has not sent a subscription request.
+ -- We store a pre-approval as per RFC6121 3.4
+ if not item then
+ item = {subscription = "none", groups = {}};
+ roster[jid] = item;
+ end
+ item.approved = "true";
+ log("debug", "Storing preapproval for %s", jid);
+ return save_roster(username, host, roster, jid);
+ end
end
local function unsubscribed(username, host, jid)
local roster = load_roster(username, host);
@@ -381,6 +419,7 @@ return {
set_contact_pending_in = set_contact_pending_in;
is_contact_pending_out = is_contact_pending_out;
set_contact_pending_out = set_contact_pending_out;
+ is_contact_preapproved = is_contact_preapproved;
unsubscribe = unsubscribe;
subscribed = subscribed;
unsubscribed = unsubscribed;