Software /
code /
prosody
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; |