plugins/mod_smacks.lua
changeset 12522 73ee3855f970
parent 12508 c589874fe348
child 12523 d935af51c644
equal deleted inserted replaced
12521:a8c17c95ef4d 12522:73ee3855f970
    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);