Comparison

plugins/mod_s2s/mod_s2s.lua @ 4969:15183193c6a6

mod_s2s: Don't call ondisconnect manually, don't call conn:close() 3 times (!) and merge its logic and streamdisconnected into session_close - including now waiting for a reply </stream:stream> if there is the chance of further stanzas requiring delivery arriving. session.sends2s() on a half-closed stream returns false.
author Matthew Wild <mwild1@gmail.com>
date Sun, 22 Jul 2012 17:07:21 +0100
parent 4968:a6d3ac11a7af
child 4988:29bdf68ad142
comparison
equal deleted inserted replaced
4968:a6d3ac11a7af 4969:15183193c6a6
29 local cert_verify_identity = require "util.x509".verify_identity; 29 local cert_verify_identity = require "util.x509".verify_identity;
30 30
31 local s2sout = module:require("s2sout"); 31 local s2sout = module:require("s2sout");
32 32
33 local connect_timeout = module:get_option_number("s2s_timeout", 60); 33 local connect_timeout = module:get_option_number("s2s_timeout", 60);
34 local stream_close_timeout = module:get_option_number("s2s_close_timeout", 5);
34 35
35 local sessions = module:shared("sessions"); 36 local sessions = module:shared("sessions");
36 37
37 local log = module._log; 38 local log = module._log;
38 39
290 function stream_callbacks.streamclosed(session) 291 function stream_callbacks.streamclosed(session)
291 (session.log or log)("debug", "Received </stream:stream>"); 292 (session.log or log)("debug", "Received </stream:stream>");
292 session:close(); 293 session:close();
293 end 294 end
294 295
295 function stream_callbacks.streamdisconnected(session, err)
296 if err and err ~= "closed" and session.direction == "outgoing" and session.notopen then
297 (session.log or log)("debug", "s2s connection attempt failed: %s", err);
298 if s2sout.attempt_connection(session, err) then
299 (session.log or log)("debug", "...so we're going to try another target");
300 return true; -- Session lives for now
301 end
302 end
303 (session.log or log)("info", "s2s disconnected: %s->%s (%s)", tostring(session.from_host), tostring(session.to_host), tostring(err or "closed"));
304 s2s_destroy_session(session, err);
305 end
306
307 function stream_callbacks.error(session, error, data) 296 function stream_callbacks.error(session, error, data)
308 if error == "no-stream" then 297 if error == "no-stream" then
309 session:close("invalid-namespace"); 298 session:close("invalid-namespace");
310 elseif error == "parse-error" then 299 elseif error == "parse-error" then
311 session.log("debug", "Server-to-server XML parse error: %s", tostring(error)); 300 session.log("debug", "Server-to-server XML parse error: %s", tostring(error));
373 session.sends2s(reason); 362 session.sends2s(reason);
374 end 363 end
375 end 364 end
376 end 365 end
377 session.sends2s("</stream:stream>"); 366 session.sends2s("</stream:stream>");
378 if session.notopen or not session.conn:close() then 367
379 session.conn:close(true); -- Force FIXME: timer? 368 function session.sends2s() return false; end
380 end 369
381 session.conn:close(); 370 local reason = remote_reason or (reason and (reason.text or reason.condition)) or reason or "stream closed";
382 listener.ondisconnect(session.conn, remote_reason or (reason and (reason.text or reason.condition)) or reason or "stream closed"); 371 session.log("info", "%s s2s stream %s->%s closed: %s", session.direction, session.from_host or "(unknown host)", session.to_host or "(unknown host)", reason);
372
373 -- Authenticated incoming stream may still be sending us stanzas, so wait for </stream:stream> from remote
374 local conn = session.conn;
375 if not session.notopen and session.type == "s2sin" then
376 add_task(stream_close_timeout, function ()
377 if not session.destroyed then
378 session.log("warn", "Failed to receive a stream close response, closing connection anyway...");
379 s2s_destroy_session(session, reason);
380 conn:close();
381 end
382 end);
383 else
384 s2s_destroy_session(session, reason);
385 conn:close(); -- Close immediately, as this is an outgoing connection or is not authed
386 end
383 end 387 end
384 end 388 end
385 389
386 -- Session initialization logic shared by incoming and outgoing 390 -- Session initialization logic shared by incoming and outgoing
387 local function initialize_session(session) 391 local function initialize_session(session)
471 end 475 end
472 476
473 function listener.ondisconnect(conn, err) 477 function listener.ondisconnect(conn, err)
474 local session = sessions[conn]; 478 local session = sessions[conn];
475 if session then 479 if session then
476 if stream_callbacks.streamdisconnected(session, err) then 480 if err and session.direction == "outgoing" and session.notopen then
477 return; -- Connection lives, for now 481 (session.log or log)("debug", "s2s connection attempt failed: %s", err);
478 end 482 if s2sout.attempt_connection(session, err) then
479 end 483 (session.log or log)("debug", "...so we're going to try another target");
480 sessions[conn] = nil; 484 return; -- Session lives for now
485 end
486 end
487 (session.log or log)("debug", "s2s disconnected: %s->%s (%s)", tostring(session.from_host), tostring(session.to_host), tostring(err or "connection closed"));
488 s2s_destroy_session(session, err);
489 sessions[conn] = nil;
490 end
481 end 491 end
482 492
483 function listener.register_outgoing(conn, session) 493 function listener.register_outgoing(conn, session)
484 session.direction = "outgoing"; 494 session.direction = "outgoing";
485 sessions[conn] = session; 495 sessions[conn] = session;