comparison mod_cloud_notify/mod_cloud_notify.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
parents 6e01878103c0
children 75b137cf869a
comparison
equal deleted inserted replaced
2711:ff1f7e61517f 2712:d89ab70808f6
205 { name = "last-message-body"; type = "text-single"; }; 205 { name = "last-message-body"; type = "text-single"; };
206 }; 206 };
207 207
208 -- http://xmpp.org/extensions/xep-0357.html#publishing 208 -- http://xmpp.org/extensions/xep-0357.html#publishing
209 local function handle_notify_request(stanza, node, user_push_services) 209 local function handle_notify_request(stanza, node, user_push_services)
210 if not user_push_services or not #user_push_services then return end 210 local pushes = 0;
211 if not user_push_services or not #user_push_services then return pushes end
211 212
212 for push_identifier, push_info in pairs(user_push_services) do 213 for push_identifier, push_info in pairs(user_push_services) do
214 local send_push = true; -- only send push to this node when not already done for this stanza or if no stanza is given at all
213 if stanza then 215 if stanza then
214 if not stanza._push_notify then stanza._push_notify = {}; end 216 if not stanza._push_notify then stanza._push_notify = {}; end
215 if stanza._push_notify[push_identifier] then 217 if stanza._push_notify[push_identifier] then
216 module:log("debug", "Already sent push notification for %s@%s to %s (%s)", node, module.host, push_info.jid, tostring(push_info.node)); 218 module:log("debug", "Already sent push notification for %s@%s to %s (%s)", node, module.host, push_info.jid, tostring(push_info.node));
217 return; 219 send_push = false;
218 end 220 end
219 stanza._push_notify[push_identifier] = true; 221 stanza._push_notify[push_identifier] = true;
220 end 222 end
221 223
222 -- increment count and save it 224 if send_push then
223 push_info.count = push_info.count + 1; 225 -- increment count and save it
224 push_store:set_identifier(node, push_identifier, push_info); 226 push_info.count = push_info.count + 1;
225 -- construct push stanza 227 push_store:set_identifier(node, push_identifier, push_info);
226 local stanza_id = hashes.sha256(push_identifier, true); 228 -- construct push stanza
227 local push_publish = st.iq({ to = push_info.jid, from = node .. "@" .. module.host, type = "set", id = stanza_id }) 229 local stanza_id = hashes.sha256(push_identifier, true);
228 :tag("pubsub", { xmlns = "http://jabber.org/protocol/pubsub" }) 230 local push_publish = st.iq({ to = push_info.jid, from = node .. "@" .. module.host, type = "set", id = stanza_id })
229 :tag("publish", { node = push_info.node }) 231 :tag("pubsub", { xmlns = "http://jabber.org/protocol/pubsub" })
230 :tag("item") 232 :tag("publish", { node = push_info.node })
231 :tag("notification", { xmlns = xmlns_push }); 233 :tag("item")
232 local form_data = { 234 :tag("notification", { xmlns = xmlns_push });
233 ["message-count"] = tostring(push_info.count); 235 local form_data = {
234 }; 236 ["message-count"] = tostring(push_info.count);
235 if stanza and include_sender then 237 };
236 form_data["last-message-sender"] = stanza.attr.from; 238 if stanza and include_sender then
237 end 239 form_data["last-message-sender"] = stanza.attr.from;
238 if stanza and include_body then 240 end
239 form_data["last-message-body"] = stanza:get_child_text("body"); 241 if stanza and include_body then
240 end 242 form_data["last-message-body"] = stanza:get_child_text("body");
241 push_publish:add_child(push_form:form(form_data)); 243 end
242 push_publish:up(); -- / notification 244 push_publish:add_child(push_form:form(form_data));
243 push_publish:up(); -- / publish 245 push_publish:up(); -- / notification
244 push_publish:up(); -- / pubsub 246 push_publish:up(); -- / publish
245 if push_info.options then 247 push_publish:up(); -- / pubsub
246 push_publish:tag("publish-options"):add_child(st.deserialize(push_info.options)); 248 if push_info.options then
247 end 249 push_publish:tag("publish-options"):add_child(st.deserialize(push_info.options));
248 -- send out push 250 end
249 module:log("debug", "Sending push notification for %s@%s to %s (%s)", node, module.host, push_info.jid, tostring(push_info.node)); 251 -- send out push
250 -- handle push errors for this node 252 module:log("debug", "Sending push notification for %s@%s to %s (%s)", node, module.host, push_info.jid, tostring(push_info.node));
251 if push_errors[push_identifier] == nil then 253 -- handle push errors for this node
252 push_errors[push_identifier] = 0; 254 if push_errors[push_identifier] == nil then
253 module:hook("iq-error/bare/"..stanza_id, handle_push_error); 255 push_errors[push_identifier] = 0;
254 module:hook("iq-result/bare/"..stanza_id, handle_push_success); 256 module:hook("iq-error/bare/"..stanza_id, handle_push_error);
255 end 257 module:hook("iq-result/bare/"..stanza_id, handle_push_success);
256 module:send(push_publish); 258 end
257 end 259 module:send(push_publish);
260 pushes = pushes + 1;
261 end
262 end
263 return pushes;
258 end 264 end
259 265
260 -- small helper function to extract relevant push settings 266 -- small helper function to extract relevant push settings
261 local function get_push_settings(stanza, session) 267 local function get_push_settings(stanza, session)
262 local to = stanza.attr.to; 268 local to = stanza.attr.to;
266 end 272 end
267 273
268 -- publish on offline message 274 -- publish on offline message
269 module:hook("message/offline/handle", function(event) 275 module:hook("message/offline/handle", function(event)
270 local node, user_push_services = get_push_settings(event.stanza, event.origin); 276 local node, user_push_services = get_push_settings(event.stanza, event.origin);
271 return handle_notify_request(event.stanza, node, user_push_services); 277 handle_notify_request(event.stanza, node, user_push_services);
272 end, 1); 278 end, 1);
273 279
274 -- publish on unacked smacks message 280 -- publish on unacked smacks message
275 local function process_smacks_stanza(stanza, session) 281 local function process_smacks_stanza(stanza, session)
276 if session.push_identifier then 282 if session.push_identifier then
348 else 354 else
349 notify_push_sevices[identifier] = push_info; 355 notify_push_sevices[identifier] = push_info;
350 end 356 end
351 end 357 end
352 358
353 return handle_notify_request(event.stanza, to, notify_push_sevices); 359 handle_notify_request(event.stanza, to, notify_push_sevices);
354 end 360 end
355 end 361 end
356 362
357 module:hook("smacks-hibernation-start", hibernate_session); 363 module:hook("smacks-hibernation-start", hibernate_session);
358 module:hook("smacks-hibernation-end", restore_session); 364 module:hook("smacks-hibernation-end", restore_session);
361 367
362 local function send_ping(event) 368 local function send_ping(event)
363 local user = event.user; 369 local user = event.user;
364 local user_push_services = push_store:get(user); 370 local user_push_services = push_store:get(user);
365 local push_services = event.push_services or user_push_services; 371 local push_services = event.push_services or user_push_services;
366 return handle_notify_request(nil, user, push_services); 372 handle_notify_request(nil, user, push_services);
367 end 373 end
368 -- can be used by other modules to ping one or more (or all) push endpoints 374 -- can be used by other modules to ping one or more (or all) push endpoints
369 module:hook("cloud-notify-ping", send_ping); 375 module:hook("cloud-notify-ping", send_ping);
370 376
371 -- TODO: this has to be done on first connect not on offline broadcast, else the counter will be incorrect 377 -- TODO: this has to be done on first connect not on offline broadcast, else the counter will be incorrect