Mercurial > prosody-modules
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 |
