Changeset

4964:c9b8ec3eb1e9

mod_c2s: Don't call ondisconnect manually on close, it is now called by net.server. Replace with inline code for destroying the session, and also waiting for a reply </stream:stream> if there is a chance of further data sent by the client. session.send() on a half-closed stream returns false (and does not deliver the data).
author Matthew Wild <mwild1@gmail.com>
date Sun, 22 Jul 2012 16:59:12 +0100
parents 4963:54e2c83af127
children 4965:c1685f0441b7
files plugins/mod_c2s.lua
diffstat 1 files changed, 23 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/plugins/mod_c2s.lua	Sun Jul 22 16:54:58 2012 +0100
+++ b/plugins/mod_c2s.lua	Sun Jul 22 16:59:12 2012 +0100
@@ -24,6 +24,7 @@
 local log = module._log;
 
 local c2s_timeout = module:get_option_number("c2s_timeout");
+local stream_close_timeout = module:get_option_number("c2s_close_timeout", 5);
 local opt_keepalives = module:get_option_boolean("tcp_keepalives", false);
 
 local sessions = module:shared("sessions");
@@ -143,8 +144,27 @@
 			end
 		end
 		session.send("</stream:stream>");
-		session.conn:close();
-		listener.ondisconnect(session.conn, (reason and (reason.text or reason.condition)) or reason or "session closed");
+		
+		function session.send() return false; end
+		
+		local reason = (reason and (reason.text or reason.condition)) or reason or "session closed";
+		session.log("info", "c2s stream for %s closed: %s", session.full_jid or ("<"..session.ip..">"), reason);
+
+		-- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote
+		local conn = session.conn;
+		if reason == "session closed" and not session.notopen and session.type == "c2s" then
+			-- Grace time to process data from authenticated cleanly-closed stream
+			add_task(stream_close_timeout, function ()
+				if not session.destroyed then
+					session.log("warn", "Failed to receive a stream close response, closing connection anyway...");
+					sm_destroy_session(session, reason);
+					conn:close();
+				end
+			end);
+		else
+			sm_destroy_session(session, reason);
+			conn:close();
+		end
 	end
 end
 
@@ -208,10 +228,9 @@
 function listener.ondisconnect(conn, err)
 	local session = sessions[conn];
 	if session then
-		(session.log or log)("info", "Client disconnected: %s", err);
+		(session.log or log)("info", "Client disconnected: %s", err or "connection closed");
 		sm_destroy_session(session, err);
 		sessions[conn]  = nil;
-		session = nil;
 	end
 end