83 |
83 |
84 local all_old_sessions = module:open_store("smacks_h"); |
84 local all_old_sessions = module:open_store("smacks_h"); |
85 local old_session_registry = module:open_store("smacks_h", "map"); |
85 local old_session_registry = module:open_store("smacks_h", "map"); |
86 local session_registry = module:shared "/*/smacks/resumption-tokens"; -- > user@host/resumption-token --> resource |
86 local session_registry = module:shared "/*/smacks/resumption-tokens"; -- > user@host/resumption-token --> resource |
87 |
87 |
|
88 local function track_session(session, id) |
|
89 session_registry[jid.join(session.username, session.host, id or session.resumption_token)] = session; |
|
90 session.resumption_token = id; |
|
91 end |
|
92 |
|
93 local function save_old_session(session) |
|
94 session_registry[jid.join(session.username, session.host, session.resumption_token)] = nil; |
|
95 return old_session_registry:set(session.username, session.resumption_token, |
|
96 { h = session.handled_stanza_count; t = os.time() }) |
|
97 end |
|
98 |
|
99 local function clear_old_session(session, id) |
|
100 session_registry[jid.join(session.username, session.host, id or session.resumption_token)] = nil; |
|
101 return old_session_registry:set(session.username, id or session.resumption_token, nil) |
|
102 end |
|
103 |
88 local ack_errors = require"util.error".init("mod_smacks", xmlns_sm3, { |
104 local ack_errors = require"util.error".init("mod_smacks", xmlns_sm3, { |
89 head = { condition = "undefined-condition"; text = "Client acknowledged more stanzas than sent by server" }; |
105 head = { condition = "undefined-condition"; text = "Client acknowledged more stanzas than sent by server" }; |
90 tail = { condition = "undefined-condition"; text = "Client acknowledged less stanzas than already acknowledged" }; |
106 tail = { condition = "undefined-condition"; text = "Client acknowledged less stanzas than already acknowledged" }; |
91 pop = { condition = "internal-server-error"; text = "Something went wrong with Stream Management" }; |
107 pop = { condition = "internal-server-error"; text = "Something went wrong with Stream Management" }; |
92 overflow = { condition = "resource-constraint", text = "Too many unacked stanzas remaining, session can't be resumed" } |
108 overflow = { condition = "resource-constraint", text = "Too many unacked stanzas remaining, session can't be resumed" } |
235 module:hook("pre-session-close", function(event) |
251 module:hook("pre-session-close", function(event) |
236 local session = event.session; |
252 local session = event.session; |
237 if session.smacks == nil then return end |
253 if session.smacks == nil then return end |
238 if session.resumption_token then |
254 if session.resumption_token then |
239 session.log("debug", "Revoking resumption token"); |
255 session.log("debug", "Revoking resumption token"); |
240 session_registry[jid.join(session.username, session.host, session.resumption_token)] = nil; |
256 clear_old_session(session); |
241 old_session_registry:set(session.username, session.resumption_token, nil); |
|
242 session.resumption_token = nil; |
257 session.resumption_token = nil; |
243 else |
258 else |
244 session.log("debug", "Session not resumable"); |
259 session.log("debug", "Session not resumable"); |
245 end |
260 end |
246 if session.hibernating_watchdog then |
261 if session.hibernating_watchdog then |
311 local resume_max; |
326 local resume_max; |
312 local resume_token; |
327 local resume_token; |
313 local resume = stanza.attr.resume; |
328 local resume = stanza.attr.resume; |
314 if resume == "true" or resume == "1" then |
329 if resume == "true" or resume == "1" then |
315 resume_token = new_id(); |
330 resume_token = new_id(); |
316 session_registry[jid.join(session.username, session.host, resume_token)] = session; |
331 track_session(session, resume_token); |
317 session.resumption_token = resume_token; |
|
318 resume_max = tostring(resume_timeout); |
332 resume_max = tostring(resume_timeout); |
319 end |
333 end |
320 (session.sends2s or session.send)(st.stanza("enabled", { xmlns = xmlns_sm, id = resume_token, resume = resume, max = resume_max })); |
334 (session.sends2s or session.send)(st.stanza("enabled", { xmlns = xmlns_sm, id = resume_token, resume = resume, max = resume_max })); |
321 return true; |
335 return true; |
322 end |
336 end |
480 session.log("debug", "The session has already been resumed or replaced"); |
494 session.log("debug", "The session has already been resumed or replaced"); |
481 return |
495 return |
482 end |
496 end |
483 |
497 |
484 session.log("debug", "Destroying session for hibernating too long"); |
498 session.log("debug", "Destroying session for hibernating too long"); |
485 session_registry[jid.join(session.username, session.host, session.resumption_token)] = nil; |
499 save_old_session(session); |
486 old_session_registry:set(session.username, session.resumption_token, |
|
487 { h = session.handled_stanza_count; t = os.time() }); |
|
488 session.resumption_token = nil; |
500 session.resumption_token = nil; |
489 session.resending_unacked = true; -- stop outgoing_stanza_filter from re-queueing anything anymore |
501 session.resending_unacked = true; -- stop outgoing_stanza_filter from re-queueing anything anymore |
490 sessionmanager.destroy_session(session, "Hibernating too long"); |
502 sessionmanager.destroy_session(session, "Hibernating too long"); |
491 sessions_expired(1); |
503 sessions_expired(1); |
492 end); |
504 end); |
539 if old_session then |
551 if old_session then |
540 session.log("debug", "Tried to resume old expired session with id %s", id); |
552 session.log("debug", "Tried to resume old expired session with id %s", id); |
541 session.send(st.stanza("failed", { xmlns = xmlns_sm, h = format_h(old_session.h) }) |
553 session.send(st.stanza("failed", { xmlns = xmlns_sm, h = format_h(old_session.h) }) |
542 :tag("item-not-found", { xmlns = xmlns_errors }) |
554 :tag("item-not-found", { xmlns = xmlns_errors }) |
543 ); |
555 ); |
544 old_session_registry:set(session.username, id, nil); |
556 clear_old_session(session, id); |
545 resumption_expired(1); |
557 resumption_expired(1); |
546 else |
558 else |
547 session.log("debug", "Tried to resume non-existent session with id %s", id); |
559 session.log("debug", "Tried to resume non-existent session with id %s", id); |
548 session.send(st.stanza("failed", { xmlns = xmlns_sm }) |
560 session.send(st.stanza("failed", { xmlns = xmlns_sm }) |
549 :tag("item-not-found", { xmlns = xmlns_errors }) |
561 :tag("item-not-found", { xmlns = xmlns_errors }) |
696 -- counter value, so it can be communicated to the client when it tries to |
708 -- counter value, so it can be communicated to the client when it tries to |
697 -- resume the lost session after a restart. |
709 -- resume the lost session after a restart. |
698 for _, user in pairs(local_sessions) do |
710 for _, user in pairs(local_sessions) do |
699 for _, session in pairs(user.sessions) do |
711 for _, session in pairs(user.sessions) do |
700 if session.resumption_token then |
712 if session.resumption_token then |
701 if old_session_registry:set(session.username, session.resumption_token, |
713 if save_old_session(session) then |
702 { h = session.handled_stanza_count; t = os.time() }) then |
|
703 session.resumption_token = nil; |
714 session.resumption_token = nil; |
704 |
715 |
705 -- Deal with unacked stanzas |
716 -- Deal with unacked stanzas |
706 if session.outgoing_stanza_queue then |
717 if session.outgoing_stanza_queue then |
707 handle_unacked_stanzas(session); |
718 handle_unacked_stanzas(session); |