Annotate

mod_presence_cache/mod_presence_cache.lua @ 2712:d89ab70808f6

mod_cloud_notify: fix bug when multiple resources are used This bug was triggered under the rare circumstances that a message arrived and one resource was smacks hibernated while the other one(s) were offline. Then only the hibernated resource but not the offline one(s) (or the other way round) got notified.
author tmolitor <thilo@eightysoft.de>
date Mon, 08 May 2017 18:24:29 +0200
parent 2292:54f44365a378
child 3183:b718092e442f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2176
b76b062e77db mod_presence_cache: Add copyright header
Kim Alvefur <zash@zash.se>
parents: 2175
diff changeset
1 -- XEP-0280: Message Carbons implementation for Prosody
b76b062e77db mod_presence_cache: Add copyright header
Kim Alvefur <zash@zash.se>
parents: 2175
diff changeset
2 -- Copyright (C) 2015-2016 Kim Alvefur
b76b062e77db mod_presence_cache: Add copyright header
Kim Alvefur <zash@zash.se>
parents: 2175
diff changeset
3 --
b76b062e77db mod_presence_cache: Add copyright header
Kim Alvefur <zash@zash.se>
parents: 2175
diff changeset
4 -- This file is MIT/X11 licensed.
b76b062e77db mod_presence_cache: Add copyright header
Kim Alvefur <zash@zash.se>
parents: 2175
diff changeset
5
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
6 local is_contact_subscribed = require"core.rostermanager".is_contact_subscribed;
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
7 local jid_split = require"util.jid".split;
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
8 local jid_bare = require"util.jid".bare;
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
9 local st = require"util.stanza";
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
10 local datetime = require"util.datetime";
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
11 local cache = require "util.cache";
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
12
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
13 local cache_size = module:get_option_number("presence_cache_size", 100);
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
14
2175
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
15 local bare_cache = {}; -- [username NUL bare_jid] = { [full_jid] = { timestamp, ... } }
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
16
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
17 local function on_evict(cache_key)
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
18 local bare_cache_key = cache_key:match("^%Z+%z[^/]+");
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
19 local full_jid = cache_key:match("%z(.*)$");
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
20 local jids = bare_cache[bare_cache_key];
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
21
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
22 if jids then
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
23 jids[full_jid] = nil;
2153
aa24d49c47ef mod_presence_cache: Only check set set is empty if it exists
Kim Alvefur <zash@zash.se>
parents: 2152
diff changeset
24 if next(jids) == nil then
aa24d49c47ef mod_presence_cache: Only check set set is empty if it exists
Kim Alvefur <zash@zash.se>
parents: 2152
diff changeset
25 bare_cache[bare_cache_key] = nil;
aa24d49c47ef mod_presence_cache: Only check set set is empty if it exists
Kim Alvefur <zash@zash.se>
parents: 2152
diff changeset
26 end
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
27 end
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
28 end
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
29
2152
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
30 -- used indirectly for the on_evict callback
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
31 local presence_cache = cache.new(cache_size, on_evict);
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
32
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
33 local function cache_hook(event)
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
34 local origin, stanza = event.origin, event.stanza;
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
35 local typ = stanza.attr.type;
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
36 module:log("debug", "Cache hook, got %s from a %s", stanza:top_tag(), origin.type);
2145
f965f86a5cad mod_presence_cache: Check stanzas only from s2sin (not needed, even with mod_bidi)
Kim Alvefur <zash@zash.se>
parents: 2123
diff changeset
37 if origin.type == "s2sin" and ( typ == nil or typ == "unavailable" ) then
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
38
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
39 local contact_full = stanza.attr.from;
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
40 local contact_bare = jid_bare(contact_full);
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
41 local username, host = jid_split(stanza.attr.to);
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
42
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
43 if not is_contact_subscribed(username, host, contact_bare) then
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
44 module:log("debug", "Presence from jid not in roster");
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
45 return;
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
46 end
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
47
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
48 local cache_key = username .. "\0" .. contact_full;
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
49 local bare_cache_key = username .. "\0" .. contact_bare;
2152
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
50
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
51 local jids = bare_cache[bare_cache_key];
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
52
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
53 if typ == "unavailable" then -- remove from cache
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
54 presence_cache:set(cache_key, nil);
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
55 on_evict(cache_key);
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
56 return;
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
57 end
bb4a2e4b7ba7 mod_presence_cache: Forget about cached presence when receiving unavailable
Kim Alvefur <zash@zash.se>
parents: 2147
diff changeset
58
2175
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
59 local presence_bits = {
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
60 stamp = datetime.datetime();
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
61 show = stanza:get_child_text("show");
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
62 };
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
63 if jids then
2175
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
64 jids[contact_full] = presence_bits;
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
65 else
2175
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
66 jids = { [contact_full] = presence_bits };
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
67 bare_cache[bare_cache_key] = jids;
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
68 end
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
69 presence_cache:set(cache_key, true);
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
70 end
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
71 end
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
72
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
73 module:hook("presence/bare", cache_hook, 10);
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
74 -- module:hook("presence/full", cache_hook, 10);
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
75
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
76 local function answer_probe_from_cache(event)
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
77 local origin, stanza = event.origin, event.stanza;
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
78 if stanza.attr.type ~= "probe" then return; end
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
79
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
80 local username = origin.username;
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
81 local contact_bare = stanza.attr.to;
2292
54f44365a378 mod_presence_cache: Ignore stanzas to self (fixes traceback on probe to self)
Kim Alvefur <zash@zash.se>
parents: 2176
diff changeset
82 if not contact_bare then return; end -- probe to self
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
83
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
84 local bare_cache_key = username .. "\0" .. contact_bare;
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
85
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
86 local cached = bare_cache[bare_cache_key];
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
87 if not cached then return end
2175
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
88 for jid, presence_bits in pairs(cached) do
2147
ed2bb50d4f91 mod_presence_cache: Switch to using util.cache for limiting size of cache
Kim Alvefur <zash@zash.se>
parents: 2146
diff changeset
89 local presence = st.presence({ to = origin.full_jid, from = jid })
2175
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
90 if presence_bits.show then
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
91 presence:tag("show"):text(presence_bits.show):up();
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
92 end
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
93 if presence_bits.stamp then
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
94 presence:tag("delay", { xmlns = "urn:xmpp:delay", from = module.host, stamp = presence_bits.stamp }):up();
cc0cf6748885 mod_presence_cache: Also cache the 'show' value
Kim Alvefur <zash@zash.se>
parents: 2153
diff changeset
95 end
1952
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
96 origin.send(presence);
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
97 end
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
98 end
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
99
9d0c33ebbcc5 mod_presence_cache: Cache incoming presence broadcasts in order to get clients up to speed with who is online faster
Kim Alvefur <zash@zash.se>
parents:
diff changeset
100 module:hook("pre-presence/bare", answer_probe_from_cache, 10);