Comparison

plugins/mod_presence.lua @ 3198:5a4e766a3577

mod_presence: Enable firing of pre-events for all outbound stanzas, and switching completely to core_post_stanza.
author Waqas Hussain <waqas20@gmail.com>
date Tue, 08 Jun 2010 16:21:14 +0500
parent 3196:d35b181a895a
child 3215:e55782f20679
comparison
equal deleted inserted replaced
3197:f1db45e89317 3198:5a4e766a3577
21 local NULL = {}; 21 local NULL = {};
22 22
23 local rostermanager = require "core.rostermanager"; 23 local rostermanager = require "core.rostermanager";
24 local sessionmanager = require "core.sessionmanager"; 24 local sessionmanager = require "core.sessionmanager";
25 local offlinemanager = require "core.offlinemanager"; 25 local offlinemanager = require "core.offlinemanager";
26
27 local _core_route_stanza = core_route_stanza;
28 local core_route_stanza;
29 function core_route_stanza(origin, stanza)
30 if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then
31 local node, host = jid_split(stanza.attr.to);
32 host = hosts[host];
33 if node and host and host.type == "local" then
34 handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to));
35 return;
36 end
37 end
38 _core_route_stanza(origin, stanza);
39 end
40 26
41 local function select_top_resources(user) 27 local function select_top_resources(user)
42 local priority = 0; 28 local priority = 0;
43 local recipients = {}; 29 local recipients = {};
44 for _, session in pairs(user.sessions) do -- find resource with greatest priority 30 for _, session in pairs(user.sessions) do -- find resource with greatest priority
80 local node, host = origin.username, origin.host; 66 local node, host = origin.username, origin.host;
81 local user = bare_sessions[node.."@"..host]; 67 local user = bare_sessions[node.."@"..host];
82 for _, res in pairs(user and user.sessions or NULL) do -- broadcast to all resources 68 for _, res in pairs(user and user.sessions or NULL) do -- broadcast to all resources
83 if res ~= origin and res.presence then -- to resource 69 if res ~= origin and res.presence then -- to resource
84 stanza.attr.to = res.full_jid; 70 stanza.attr.to = res.full_jid;
85 core_route_stanza(origin, stanza); 71 core_post_stanza(origin, stanza, true);
86 end 72 end
87 end 73 end
88 for jid, item in pairs(roster) do -- broadcast to all interested contacts 74 for jid, item in pairs(roster) do -- broadcast to all interested contacts
89 if item.subscription == "both" or item.subscription == "from" then 75 if item.subscription == "both" or item.subscription == "from" then
90 stanza.attr.to = jid; 76 stanza.attr.to = jid;
91 core_route_stanza(origin, stanza); 77 core_post_stanza(origin, stanza, true);
92 end 78 end
93 end 79 end
94 if stanza.attr.type == nil and not origin.presence then -- initial presence 80 if stanza.attr.type == nil and not origin.presence then -- initial presence
95 origin.presence = stanza; -- FIXME repeated later 81 origin.presence = stanza; -- FIXME repeated later
96 local probe = st.presence({from = origin.full_jid, type = "probe"}); 82 local probe = st.presence({from = origin.full_jid, type = "probe"});
101 end 87 end
102 end 88 end
103 for _, res in pairs(user and user.sessions or NULL) do -- broadcast from all available resources 89 for _, res in pairs(user and user.sessions or NULL) do -- broadcast from all available resources
104 if res ~= origin and res.presence then 90 if res ~= origin and res.presence then
105 res.presence.attr.to = origin.full_jid; 91 res.presence.attr.to = origin.full_jid;
106 core_route_stanza(res, res.presence); 92 core_post_stanza(res, res.presence, true);
107 res.presence.attr.to = nil; 93 res.presence.attr.to = nil;
108 end 94 end
109 end 95 end
110 if roster.pending then -- resend incoming subscription requests 96 if roster.pending then -- resend incoming subscription requests
111 for jid in pairs(roster.pending) do 97 for jid in pairs(roster.pending) do
114 end 100 end
115 local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host}); 101 local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host});
116 for jid, item in pairs(roster) do -- resend outgoing subscription requests 102 for jid, item in pairs(roster) do -- resend outgoing subscription requests
117 if item.ask then 103 if item.ask then
118 request.attr.to = jid; 104 request.attr.to = jid;
119 core_route_stanza(origin, request); 105 core_post_stanza(origin, request, true);
120 end 106 end
121 end 107 end
122 local offline = offlinemanager.load(node, host); 108 local offline = offlinemanager.load(node, host);
123 if offline then 109 if offline then
124 for _, msg in ipairs(offline) do 110 for _, msg in ipairs(offline) do
134 recalc_resource_map(user); 120 recalc_resource_map(user);
135 end 121 end
136 if origin.directed then 122 if origin.directed then
137 for jid in pairs(origin.directed) do 123 for jid in pairs(origin.directed) do
138 stanza.attr.to = jid; 124 stanza.attr.to = jid;
139 core_route_stanza(origin, stanza); 125 core_post_stanza(origin, stanza, true);
140 end 126 end
141 origin.directed = nil; 127 origin.directed = nil;
142 end 128 end
143 else 129 else
144 origin.presence = stanza; 130 origin.presence = stanza;
168 for k, session in pairs(u.sessions) do 154 for k, session in pairs(u.sessions) do
169 local pres = session.presence; 155 local pres = session.presence;
170 if pres then 156 if pres then
171 if stanza then pres = stanza; pres.attr.from = session.full_jid; end 157 if stanza then pres = stanza; pres.attr.from = session.full_jid; end
172 pres.attr.to = jid; 158 pres.attr.to = jid;
173 core_route_stanza(session, pres); 159 core_post_stanza(session, pres, true);
174 pres.attr.to = nil; 160 pres.attr.to = nil;
175 count = count + 1; 161 count = count + 1;
176 end 162 end
177 end 163 end
178 end 164 end
194 -- 1. route stanza 180 -- 1. route stanza
195 -- 2. roster push (subscription = none, ask = subscribe) 181 -- 2. roster push (subscription = none, ask = subscribe)
196 if rostermanager.set_contact_pending_out(node, host, to_bare) then 182 if rostermanager.set_contact_pending_out(node, host, to_bare) then
197 rostermanager.roster_push(node, host, to_bare); 183 rostermanager.roster_push(node, host, to_bare);
198 end -- else file error 184 end -- else file error
199 core_route_stanza(origin, stanza); 185 core_post_stanza(origin, stanza);
200 elseif stanza.attr.type == "unsubscribe" then 186 elseif stanza.attr.type == "unsubscribe" then
201 -- 1. route stanza 187 -- 1. route stanza
202 -- 2. roster push (subscription = none or from) 188 -- 2. roster push (subscription = none or from)
203 if rostermanager.unsubscribe(node, host, to_bare) then 189 if rostermanager.unsubscribe(node, host, to_bare) then
204 rostermanager.roster_push(node, host, to_bare); -- FIXME do roster push when roster has in fact not changed? 190 rostermanager.roster_push(node, host, to_bare); -- FIXME do roster push when roster has in fact not changed?
205 end -- else file error 191 end -- else file error
206 core_route_stanza(origin, stanza); 192 core_post_stanza(origin, stanza);
207 elseif stanza.attr.type == "subscribed" then 193 elseif stanza.attr.type == "subscribed" then
208 -- 1. route stanza 194 -- 1. route stanza
209 -- 2. roster_push () 195 -- 2. roster_push ()
210 -- 3. send_presence_of_available_resources 196 -- 3. send_presence_of_available_resources
211 if rostermanager.subscribed(node, host, to_bare) then 197 if rostermanager.subscribed(node, host, to_bare) then
212 rostermanager.roster_push(node, host, to_bare); 198 rostermanager.roster_push(node, host, to_bare);
213 end 199 end
214 core_route_stanza(origin, stanza); 200 core_post_stanza(origin, stanza);
215 send_presence_of_available_resources(node, host, to_bare, origin); 201 send_presence_of_available_resources(node, host, to_bare, origin);
216 elseif stanza.attr.type == "unsubscribed" then 202 elseif stanza.attr.type == "unsubscribed" then
217 -- 1. route stanza 203 -- 1. route stanza
218 -- 2. roster push (subscription = none or to) 204 -- 2. roster push (subscription = none or to)
219 if rostermanager.unsubscribed(node, host, to_bare) then 205 if rostermanager.unsubscribed(node, host, to_bare) then
220 rostermanager.roster_push(node, host, to_bare); 206 rostermanager.roster_push(node, host, to_bare);
221 end 207 end
222 core_route_stanza(origin, stanza); 208 core_post_stanza(origin, stanza);
223 end 209 end
224 stanza.attr.from, stanza.attr.to = st_from, st_to; 210 stanza.attr.from, stanza.attr.to = st_from, st_to;
225 return true; 211 return true;
226 end 212 end
227 213
233 219
234 if stanza.attr.type == "probe" then 220 if stanza.attr.type == "probe" then
235 local result, err = rostermanager.is_contact_subscribed(node, host, from_bare); 221 local result, err = rostermanager.is_contact_subscribed(node, host, from_bare);
236 if result then 222 if result then
237 if 0 == send_presence_of_available_resources(node, host, st_from, origin) then 223 if 0 == send_presence_of_available_resources(node, host, st_from, origin) then
238 core_route_stanza(hosts[host], st.presence({from=to_bare, to=st_from, type="unavailable"})); -- TODO send last activity 224 core_post_stanza(hosts[host], st.presence({from=to_bare, to=st_from, type="unavailable"}), true); -- TODO send last activity
239 end 225 end
240 elseif not err then 226 elseif not err then
241 core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unsubscribed"})); 227 core_post_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unsubscribed"}), true);
242 end 228 end
243 elseif stanza.attr.type == "subscribe" then 229 elseif stanza.attr.type == "subscribe" then
244 if rostermanager.is_contact_subscribed(node, host, from_bare) then 230 if rostermanager.is_contact_subscribed(node, host, from_bare) then
245 core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="subscribed"})); -- already subscribed 231 core_post_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="subscribed"}), true); -- already subscribed
246 -- Sending presence is not clearly stated in the RFC, but it seems appropriate 232 -- Sending presence is not clearly stated in the RFC, but it seems appropriate
247 if 0 == send_presence_of_available_resources(node, host, from_bare, origin) then 233 if 0 == send_presence_of_available_resources(node, host, from_bare, origin) then
248 core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- TODO send last activity 234 core_post_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"}), true); -- TODO send last activity
249 end 235 end
250 else 236 else
251 core_route_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"})); -- acknowledging receipt 237 core_post_stanza(hosts[host], st.presence({from=to_bare, to=from_bare, type="unavailable"}), true); -- acknowledging receipt
252 if not rostermanager.is_contact_pending_in(node, host, from_bare) then 238 if not rostermanager.is_contact_pending_in(node, host, from_bare) then
253 if rostermanager.set_contact_pending_in(node, host, from_bare) then 239 if rostermanager.set_contact_pending_in(node, host, from_bare) then
254 sessionmanager.send_to_available_resources(node, host, stanza); 240 sessionmanager.send_to_available_resources(node, host, stanza);
255 end -- TODO else return error, unable to save 241 end -- TODO else return error, unable to save
256 end 242 end
347 local origin, stanza = data.origin, data.stanza; 333 local origin, stanza = data.origin, data.stanza;
348 334
349 local from_bare = jid_bare(stanza.attr.from); 335 local from_bare = jid_bare(stanza.attr.from);
350 local t = stanza.attr.type; 336 local t = stanza.attr.type;
351 if t == "probe" then 337 if t == "probe" then
352 core_route_stanza(hosts[module.host], st.presence({ from = module.host, to = from_bare, id = stanza.attr.id })); 338 core_post_stanza(hosts[module.host], st.presence({ from = module.host, to = from_bare, id = stanza.attr.id }));
353 elseif t == "subscribe" then 339 elseif t == "subscribe" then
354 core_route_stanza(hosts[module.host], st.presence({ from = module.host, to = from_bare, id = stanza.attr.id, type = "subscribed" })); 340 core_post_stanza(hosts[module.host], st.presence({ from = module.host, to = from_bare, id = stanza.attr.id, type = "subscribed" }));
355 core_route_stanza(hosts[module.host], st.presence({ from = module.host, to = from_bare, id = stanza.attr.id })); 341 core_post_stanza(hosts[module.host], st.presence({ from = module.host, to = from_bare, id = stanza.attr.id }));
356 end 342 end
357 return true; 343 return true;
358 end); 344 end);
359 345
360 module:hook("resource-unbind", function(event) 346 module:hook("resource-unbind", function(event)
369 local pres = st.presence{ type = "unavailable", from = session.full_jid }; 355 local pres = st.presence{ type = "unavailable", from = session.full_jid };
370 if not(err) or err == "closed" then err = "connection closed"; end 356 if not(err) or err == "closed" then err = "connection closed"; end
371 pres:tag("status"):text("Disconnected: "..err):up(); 357 pres:tag("status"):text("Disconnected: "..err):up();
372 for jid in pairs(session.directed) do 358 for jid in pairs(session.directed) do
373 pres.attr.to = jid; 359 pres.attr.to = jid;
374 core_route_stanza(session, pres); 360 core_post_stanza(session, pres, true);
375 end 361 end
376 session.directed = nil; 362 session.directed = nil;
377 end 363 end
378 end); 364 end);