Comparison

plugins/mod_disco.lua @ 3347:99f56bed5228

mod_disco: Cache disco#info reply and caps hash for host, return correct caps hash, and respond to disco#info to the caps hash node.
author Waqas Hussain <waqas20@gmail.com>
date Sun, 11 Jul 2010 21:21:38 +0500
parent 3343:c70c6d5bf270
child 3348:3b84a84f472a
comparison
equal deleted inserted replaced
3346:c9294e190bb6 3347:99f56bed5228
34 34
35 module:add_identity("server", "im", "Prosody"); -- FIXME should be in the non-existing mod_router 35 module:add_identity("server", "im", "Prosody"); -- FIXME should be in the non-existing mod_router
36 module:add_feature("http://jabber.org/protocol/disco#info"); 36 module:add_feature("http://jabber.org/protocol/disco#info");
37 module:add_feature("http://jabber.org/protocol/disco#items"); 37 module:add_feature("http://jabber.org/protocol/disco#items");
38 38
39 -- Handle disco requests to the server 39 -- Generate and cache disco result and caps hash
40 40 local _cached_server_disco_info, _cached_server_caps_feature, _cached_server_caps_hash;
41 local function build_server_disco_info(stanza) 41 local function build_server_disco_info()
42 local query = st.stanza("query", { xmlns = "http://jabber.org/protocol/disco#info" });
42 local done = {}; 43 local done = {};
43 for _,identity in ipairs(module:get_host_items("identity")) do 44 for _,identity in ipairs(module:get_host_items("identity")) do
44 local identity_s = identity.category.."\0"..identity.type; 45 local identity_s = identity.category.."\0"..identity.type;
45 if not done[identity_s] then 46 if not done[identity_s] then
46 stanza:tag("identity", identity):up(); 47 query:tag("identity", identity):up();
47 done[identity_s] = true; 48 done[identity_s] = true;
48 end 49 end
49 end 50 end
50 for _,feature in ipairs(module:get_host_items("feature")) do 51 for _,feature in ipairs(module:get_host_items("feature")) do
51 if not done[feature] then 52 if not done[feature] then
52 stanza:tag("feature", {var=feature}):up(); 53 query:tag("feature", {var=feature}):up();
53 done[feature] = true; 54 done[feature] = true;
54 end 55 end
55 end 56 end
57 _cached_server_disco_info = query;
58 _cached_server_caps_hash = calculate_hash(query);
59 _cached_server_caps_feature = st.stanza("c", {
60 xmlns = "http://jabber.org/protocol/caps";
61 hash = "sha-1";
62 node = "http://prosody.im";
63 ver = _cached_server_caps_hash;
64 });
56 end 65 end
66 local function clear_disco_cache()
67 _cached_server_disco_info, _cached_server_caps_feature, _cached_server_caps_hash = nil, nil, nil;
68 end
69 local function get_server_disco_info()
70 if not _cached_server_disco_info then build_server_disco_info(); end
71 return _cached_server_disco_info;
72 end
73 local function get_server_caps_feature()
74 if not _cached_server_caps_feature then build_server_disco_info(); end
75 return _cached_server_caps_feature;
76 end
77 local function get_server_caps_hash()
78 if not _cached_server_caps_hash then build_server_disco_info(); end
79 return _cached_server_caps_hash;
80 end
81
82 module:hook("item-added/identity", clear_disco_cache);
83 module:hook("item-added/feature", clear_disco_cache);
84
85 -- Handle disco requests to the server
57 module:hook("iq/host/http://jabber.org/protocol/disco#info:query", function(event) 86 module:hook("iq/host/http://jabber.org/protocol/disco#info:query", function(event)
58 local origin, stanza = event.origin, event.stanza; 87 local origin, stanza = event.origin, event.stanza;
59 if stanza.attr.type ~= "get" then return; end 88 if stanza.attr.type ~= "get" then return; end
60 local node = stanza.tags[1].attr.node; 89 local node = stanza.tags[1].attr.node;
61 if node and node ~= "" then return; end -- TODO fire event? 90 if node and node ~= "" and node ~= get_server_caps_hash() then return; end -- TODO fire event?
62 local reply = st.reply(stanza):query("http://jabber.org/protocol/disco#info"); 91 local reply = st.reply(stanza):add_child(get_server_disco_info());
63 build_server_disco_info(reply);
64 origin.send(reply); 92 origin.send(reply);
65 return true; 93 return true;
66 end); 94 end);
67 module:hook("iq/host/http://jabber.org/protocol/disco#items:query", function(event) 95 module:hook("iq/host/http://jabber.org/protocol/disco#items:query", function(event)
68 local origin, stanza = event.origin, event.stanza; 96 local origin, stanza = event.origin, event.stanza;
79 end 107 end
80 origin.send(reply); 108 origin.send(reply);
81 return true; 109 return true;
82 end); 110 end);
83 111
84 -- Server caps hash calculation 112 -- Handle caps stream feature
85 local caps_hash_feature;
86
87 local function recalculate_server_caps()
88 local caps_hash = calculate_hash(st.stanza());
89 caps_hash_feature = st.stanza("c", {
90 xmlns = "http://jabber.org/protocol/caps";
91 hash = "sha-1";
92 node = "http://prosody.im";
93 ver = caps_hash;
94 });
95 end
96 recalculate_server_caps();
97
98 module:hook("item-added/identity", recalculate_server_caps);
99 module:hook("item-added/feature", recalculate_server_caps);
100
101 module:hook("stream-features", function (event) 113 module:hook("stream-features", function (event)
102 if caps_hash_feature then 114 event.features:add_child(get_server_caps_feature());
103 event.features:add_child(caps_hash_feature);
104 end
105 end); 115 end);
106 116
107 -- Handle disco requests to user accounts 117 -- Handle disco requests to user accounts
108 module:hook("iq/bare/http://jabber.org/protocol/disco#info:query", function(event) 118 module:hook("iq/bare/http://jabber.org/protocol/disco#info:query", function(event)
109 local origin, stanza = event.origin, event.stanza; 119 local origin, stanza = event.origin, event.stanza;