comparison mod_smacks/mod_smacks.lua @ 3935:c49fea05772e

mod_smacks: handle mam-enabled session internally This obsoletes mod_smacks_offline and supersedes mod_smacks_noerror with mod_smacks_nooffline_noerror
author tmolitor <thilo@eightysoft.de>
date Sun, 08 Mar 2020 19:49:47 +0100
parents b5d367798570
children e93e58b33bf6
comparison
equal deleted inserted replaced
3928:7e7ac4af6e0c 3935:c49fea05772e
43 local max_old_sessions = module:get_option_number("smacks_max_old_sessions", 10); 43 local max_old_sessions = module:get_option_number("smacks_max_old_sessions", 10);
44 local core_process_stanza = prosody.core_process_stanza; 44 local core_process_stanza = prosody.core_process_stanza;
45 local sessionmanager = require"core.sessionmanager"; 45 local sessionmanager = require"core.sessionmanager";
46 46
47 assert(max_hibernated_sessions > 0, "smacks_max_hibernated_sessions must be greater than 0"); 47 assert(max_hibernated_sessions > 0, "smacks_max_hibernated_sessions must be greater than 0");
48 assert(max_old_sessions > 0, "smacks_old_sessions must be greater than 0"); 48 assert(max_old_sessions > 0, "smacks_max_old_sessions must be greater than 0");
49 49
50 local c2s_sessions = module:shared("/*/c2s/sessions"); 50 local c2s_sessions = module:shared("/*/c2s/sessions");
51 51
52 local function init_session_cache(max_entries, evict_callback) 52 local function init_session_cache(max_entries, evict_callback)
53 -- old prosody version < 0.10 (no limiting at all!) 53 -- old prosody version < 0.10 (no limiting at all!)
108 if stopped then return; end 108 if stopped then return; end
109 return callback(t); 109 return callback(t);
110 end); 110 end);
111 if timer and timer.stop then return timer; end -- new prosody api includes stop() function 111 if timer and timer.stop then return timer; end -- new prosody api includes stop() function
112 return { 112 return {
113 stop = function () stopped = true end; 113 stop = function(self) stopped = true end;
114 timer; 114 timer;
115 }; 115 };
116 end 116 end
117 117
118 local function delayed_ack_function(session) 118 local function delayed_ack_function(session)
391 --TODO: Optimise... incoming stanzas should be handled by a per-session 391 --TODO: Optimise... incoming stanzas should be handled by a per-session
392 -- function that has a counter as an upvalue (no table indexing for increments, 392 -- function that has a counter as an upvalue (no table indexing for increments,
393 -- and won't slow non-198 sessions). We can also then remove the .handled flag 393 -- and won't slow non-198 sessions). We can also then remove the .handled flag
394 -- on stanzas 394 -- on stanzas
395 395
396 function handle_unacked_stanzas(session) 396 local function handle_unacked_stanzas(session)
397 local queue = session.outgoing_stanza_queue; 397 local queue = session.outgoing_stanza_queue;
398 local error_attr = { type = "cancel" }; 398 local error_attr = { type = "cancel" };
399 if #queue > 0 then 399 if #queue > 0 then
400 session.outgoing_stanza_queue = {}; 400 session.outgoing_stanza_queue = {};
401 for i=1,#queue do 401 for i=1,#queue do
409 end 409 end
410 end 410 end
411 end 411 end
412 end 412 end
413 end 413 end
414
415 -- don't send delivery errors for messages which will be delivered by mam later on
416 module:hook("delivery/failure", function(event)
417 local session, stanza = event.session, event.stanza;
418 -- Only deal with authenticated (c2s) sessions
419 if session.username then
420 if stanza.name == "message" and stanza.attr.xmlns == nil and
421 ( stanza.attr.type == "chat" or ( stanza.attr.type or "normal" ) == "normal" ) then
422 -- do nothing here for normal messages and don't send out "message delivery errors",
423 -- because messages are already in MAM at this point (no need to frighten users)
424 if session.mam_requested and stanza._was_archived then
425 return true; -- stanza handled, don't send an error
426 end
427 -- store message in offline store, if this client does not use mam *and* was the last client online
428 local sessions = prosody.hosts[module.host].sessions[session.username] and
429 prosody.hosts[module.host].sessions[session.username].sessions or nil;
430 if sessions and next(sessions) == session.resource and next(sessions, session.resource) == nil then
431 module:fire_event("message/offline/handle", { origin = session, stanza = stanza } );
432 return true; -- stanza handled, don't send an error
433 end
434 end
435 end
436 end);
437
438 -- mark stanzas as archived --> this will allow us to send back errors for stanzas not archived
439 -- because the user configured the server to do so ("no-archive"-setting for one special contact for example)
440 module:hook("archive-message-added", function(event)
441 local session, stanza, for_user, stanza_id = event.origin, event.stanza, event.for_user, event.id;
442 if session then session.log("debug", "Marking stanza as archived, archive_id: %s, stanza: %s", tostring(stanza_id), tostring(stanza:top_tag())); end
443 if not session then module:log("debug", "Marking stanza as archived in unknown session, archive_id: %s, stanza: %s", tostring(stanza_id), tostring(stanza:top_tag())); end
444 stanza._was_archived = true;
445 end);
414 446
415 module:hook("pre-resource-unbind", function (event) 447 module:hook("pre-resource-unbind", function (event)
416 local session, err = event.session, event.error; 448 local session, err = event.session, event.error;
417 if session.smacks then 449 if session.smacks then
418 if not session.resumption_token then 450 if not session.resumption_token then
529 original_session.log("debug", "mod_smacks closing an old connection for this session"); 561 original_session.log("debug", "mod_smacks closing an old connection for this session");
530 local conn = original_session.conn; 562 local conn = original_session.conn;
531 c2s_sessions[conn] = nil; 563 c2s_sessions[conn] = nil;
532 conn:close(); 564 conn:close();
533 end 565 end
566 local migrated_session_log = session.log;
534 original_session.ip = session.ip; 567 original_session.ip = session.ip;
535 original_session.conn = session.conn; 568 original_session.conn = session.conn;
536 original_session.send = session.send; 569 original_session.send = session.send;
537 original_session.close = session.close; 570 original_session.close = session.close;
538 original_session.filter = session.filter; 571 original_session.filter = session.filter;
563 local queue = original_session.outgoing_stanza_queue; 596 local queue = original_session.outgoing_stanza_queue;
564 session.log("debug", "resending all unacked stanzas that are still queued after resume, #queue = %d", #queue); 597 session.log("debug", "resending all unacked stanzas that are still queued after resume, #queue = %d", #queue);
565 for i=1,#queue do 598 for i=1,#queue do
566 session.send(queue[i]); 599 session.send(queue[i]);
567 end 600 end
568 session.log("debug", "all stanzas resent, now disabling send() in this session, #queue = %d", #queue); 601 session.log("debug", "all stanzas resent, now disabling send() in this migrated session, #queue = %d", #queue);
569 function session.send(stanza) 602 function session.send(stanza)
570 session.log("warn", "Tried to send stanza on old session migrated by smacks resume (maybe there is a bug?): %s", tostring(stanza)); 603 migrated_session_log("error", "Tried to send stanza on old session migrated by smacks resume (maybe there is a bug?): %s", tostring(stanza));
571 return false; 604 return false;
572 end 605 end
573 module:fire_event("smacks-hibernation-end", {origin = session, resumed = original_session, queue = queue}); 606 module:fire_event("smacks-hibernation-end", {origin = session, resumed = original_session, queue = queue});
574 request_ack_if_needed(original_session, true, "handle_resume"); 607 request_ack_if_needed(original_session, true, "handle_resume");
575 else 608 else