X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=core%2Fs2smanager.lua;h=f444e8437ca64b54042ff3030c32785e825ad9df;hb=cdc1372950646dd6219b11693f6c46620e0beb0b;hp=3613707cf1a962712821991bc452ca72afc95609;hpb=cb8163b8edf21a93d510087ad373ae473a4a9f04;p=prosody.git diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 3613707c..f444e843 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -50,9 +50,11 @@ local incoming_s2s = incoming_s2s; module "s2smanager" -local function compare_srv_priorities(a,b) return a.priority < b.priority or a.weight < b.weight; end +function compare_srv_priorities(a,b) + return a.priority < b.priority or (a.priority == b.priority and a.weight > b.weight); +end -local function bounce_sendq(session) +local function bounce_sendq(session, reason) local sendq = session.sendq; if sendq then session.log("info", "sending error replies for "..#sendq.." queued stanzas because of failed outgoing connection to "..tostring(session.to_host)); @@ -70,6 +72,9 @@ local function bounce_sendq(session) reply.attr.type = "error"; reply:tag("error", {type = "cancel"}) :tag("remote-server-not-found", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}):up(); + if reason then + reply:tag("text", {xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas"}):text("Connection failed: "..reason):up(); + end core_process_stanza(dummy, reply); end sendq[i] = nil; @@ -79,15 +84,15 @@ local function bounce_sendq(session) end function send_to_host(from_host, to_host, data) + if not hosts[from_host] then + log("warn", "Attempt to send stanza from %s - a host we don't serve", from_host); + return false; + end local host = hosts[from_host].s2sout[to_host]; if host then -- We have a connection to this host already - if host.type == "s2sout_unauthed" and data.name ~= "db:verify" and ((not data.xmlns) or data.xmlns == "jabber:client" or data.xmlns == "jabber:server") then + if host.type == "s2sout_unauthed" and (data.name ~= "db:verify" or not host.dialback_key) and ((not data.xmlns) or data.xmlns == "jabber:client" or data.xmlns == "jabber:server") then (host.log or log)("debug", "trying to send over unauthed s2sout to "..to_host); - if not host.notopen and not host.dialback_key and host.sends2s then - host.log("debug", "dialback had not been initiated"); - initiate_dialback(host); - end -- Queue stanza until we are able to send it if host.sendq then t_insert(host.sendq, {tostring(data), st.reply(data)}); @@ -110,6 +115,7 @@ function send_to_host(from_host, to_host, data) else log("debug", "opening a new outgoing connection for this stanza"); local host_session = new_outgoing(from_host, to_host); + -- Store in buffer host_session.sendq = { {tostring(data), st.reply(data)} }; log("debug", "stanza [%s] queued until connection complete", tostring(data.name)); @@ -159,7 +165,7 @@ function new_outgoing(from_host, to_host) host_session.log = log; end - -- This is the first call, can't fail (the first step is DNS lookup) + -- Kick the connection attempting machine attempt_connection(host_session); if not host_session.sends2s then @@ -187,6 +193,10 @@ function attempt_connection(host_session, err) local from_host, to_host = host_session.from_host, host_session.to_host; local connect_host, connect_port = idna_to_ascii(to_host), 5269; + if not connect_host then + return false; + end + if not err then -- This is our first attempt log("debug", "First attempt to connect to %s, starting with SRV lookup...", to_host); host_session.connecting = true; @@ -217,7 +227,7 @@ function attempt_connection(host_session, err) if not ok then if not attempt_connection(host_session, err) then -- No more attempts will be made - destroy_session(host_session); + destroy_session(host_session, err); end end end, "_xmpp-server._tcp."..connect_host..".", "SRV"); @@ -277,7 +287,7 @@ function try_connect(host_session, connect_host, connect_port) log("debug", "DNS lookup failed to get a response for %s", connect_host); if not attempt_connection(host_session, "name resolution failed") then -- Retry if we can log("debug", "No other records to try for %s - destroying", host_session.to_host); - destroy_session(host_session); -- End of the line, we can't + destroy_session(host_session, "DNS resolution failed"); -- End of the line, we can't end end end, connect_host, "A", "IN"); @@ -299,6 +309,11 @@ function make_connect(host_session, connect_host, connect_port) local from_host, to_host = host_session.from_host, host_session.to_host; local conn, handler = socket.tcp() + + if not conn then + log("warn", "Failed to create outgoing connection, system error: %s", handler); + return false, handler; + end conn:settimeout(0); local success, err = conn:connect(connect_host, connect_port); @@ -357,17 +372,17 @@ function streamopened(session, attr) session.streamid = uuid_gen(); (session.log or log)("debug", "incoming s2s received "); - send(""); - send(stanza("stream:stream", { xmlns='jabber:server', ["xmlns:db"]='jabber:server:dialback', - ["xmlns:stream"]='http://etherx.jabber.org/streams', id=session.streamid, from=session.to_host, version=(session.version > 0 and "1.0" or nil) }):top_tag()); if session.to_host and not hosts[session.to_host] then -- Attempting to connect to a host we don't serve session:close({ condition = "host-unknown"; text = "This host does not serve "..session.to_host }); return; end + send(""); + send(stanza("stream:stream", { xmlns='jabber:server', ["xmlns:db"]='jabber:server:dialback', + ["xmlns:stream"]='http://etherx.jabber.org/streams', id=session.streamid, from=session.to_host, version=(session.version > 0 and "1.0" or nil) }):top_tag()); if session.version >= 1.0 then local features = st.stanza("stream:features"); - + if session.to_host then hosts[session.to_host].events.fire_event("s2s-stream-features", { session = session, features = features }); else @@ -390,7 +405,7 @@ function streamopened(session, attr) if send_buffer and #send_buffer > 0 then log("debug", "Sending s2s send_buffer now..."); for i, data in ipairs(send_buffer) do - session.sends2s(tostring(data)); + session.sends2s(data); send_buffer[i] = nil; end end @@ -479,12 +494,12 @@ function mark_connected(session) end end -function destroy_session(session) +function destroy_session(session, reason) (session.log or log)("info", "Destroying "..tostring(session.direction).." session "..tostring(session.from_host).."->"..tostring(session.to_host)); if session.direction == "outgoing" then hosts[session.from_host].s2sout[session.to_host] = nil; - bounce_sendq(session); + bounce_sendq(session, reason); elseif session.direction == "incoming" then incoming_s2s[session] = nil; end