module:get_option_set("s2s_secure_domains", {})._items, module:get_option_set("s2s_insecure_domains", {})._items;
local require_encryption = module:get_option_boolean("s2s_require_encryption", false);
+local measure_connections = module:measure("connections", "counter");
+
local sessions = module:shared("sessions");
local log = module._log;
local function bounce_sendq(session, reason)
local sendq = session.sendq;
if not sendq then return; end
- session.log("info", "sending error replies for "..#sendq.." queued stanzas because of failed outgoing connection to "..tostring(session.to_host));
+ session.log("info", "Sending error replies for "..#sendq.." queued stanzas because of failed outgoing connection to "..tostring(session.to_host));
local dummy = {
type = "s2sin";
send = function(s)
(session.log or log)("error", "Replying to to an s2s error reply, please report this! Traceback: %s", traceback());
end;
dummy = true;
+ close = function ()
+ (session.log or log)("error", "Attempting to close the dummy origin of s2s error replies, please report this! Traceback: %s", traceback());
+ end;
};
for i, data in ipairs(sendq) do
local reply = data[2];
-- so the stream is ready for stanzas. RFC 6120 Section 4.3
mark_connected(session);
return true;
+ elseif not session.dialback_verifying then
+ session.log("warn", "No SASL EXTERNAL offer and Dialback doesn't seem to be enabled, giving up");
+ session:close();
+ return false;
end
end, -1);
end
-- Stream is authorised, and ready for normal stanzas
function mark_connected(session)
- local sendq, send = session.sendq, session.sends2s;
+ local sendq = session.sendq;
local from, to = session.from_host, session.to_host;
if session.direction == "outgoing" then
if sendq then
session.log("debug", "sending %d queued stanzas across new outgoing connection to %s", #sendq, session.to_host);
+ local send = session.sends2s;
for i, data in ipairs(sendq) do
send(data[1]);
sendq[i] = nil;
local xmlns_xmpp_streams = "urn:ietf:params:xml:ns:xmpp-streams";
function stream_callbacks.streamopened(session, attr)
- local send = session.sends2s;
-
session.version = tonumber(attr.version) or 0;
-- TODO: Rename session.secure to session.encrypted
end
session:open_stream(session.to_host, session.from_host)
+ session.notopen = nil;
if session.version >= 1.0 then
local features = st.stanza("stream:features");
(session.log or log)("warn", "No 'to' on stream header from %s means we can't offer any features", from or session.ip or "unknown host");
end
- log("debug", "Sending stream features: %s", tostring(features));
- send(features);
+ if ( session.type == "s2sin" or session.type == "s2sout" ) or features.tags[1] then
+ log("debug", "Sending stream features: %s", tostring(features));
+ session.sends2s(features);
+ else
+ (session.log or log)("warn", "No features to offer, giving up");
+ session:close({ condition = "undefined-condition", text = "No features to offer" });
+ end
end
- session.notopen = nil;
elseif session.direction == "outgoing" then
session.notopen = nil;
if not attr.id then
if not from or (hosts[from] and hosts[from].modules.dialback) then
attr["xmlns:db"] = 'jabber:server:dialback';
end
+ if not from then
+ attr.from = '';
+ end
+ if not to then
+ attr.to = '';
+ end
end
-- Session initialization logic shared by incoming and outgoing
end
function listener.onconnect(conn)
+ measure_connections(1);
conn:setoption("keepalive", opt_keepalives);
local session = sessions[conn];
if not session then -- New incoming connection
end
function listener.ondisconnect(conn, err)
+ measure_connections(-1);
local session = sessions[conn];
if session then
sessions[conn] = nil;
function listener.onreadtimeout(conn)
local session = sessions[conn];
+ local host = session.host or session.to_host;
if session then
- return (hosts[session.host] or prosody).events.fire_event("s2s-read-timeout", { session = session });
+ return (hosts[host] or prosody).events.fire_event("s2s-read-timeout", { session = session });
end
end