Changeset

331:830fd67f9378

Quite some changes, to: - Small logging fix for s2smanager - Send a stream error if an incoming s2s connection is to an unrecognised hostname (fixes #11) - init_xmlhandlers now takes a table of callbacks (includes changes to net/xmpp*_listener for this) - Move sending of unavailable presence to where it should be, sessionmanager.destroy_session - Fix sending of stream errors to wrong connection
author Matthew Wild <mwild1@gmail.com>
date Tue, 18 Nov 2008 17:52:33 +0000
parents 330:d9d4c1de16ce
children 332:51e130b5c8de
files core/s2smanager.lua core/sessionmanager.lua core/xmlhandlers.lua net/xmppclient_listener.lua net/xmppserver_listener.lua
diffstat 5 files changed, 44 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/core/s2smanager.lua	Tue Nov 18 14:42:45 2008 +0000
+++ b/core/s2smanager.lua	Tue Nov 18 17:52:33 2008 +0000
@@ -52,7 +52,7 @@
 			-- FIXME
 			if host.from_host ~= from_host then
 				log("error", "WARNING! This might, possibly, be a bug, but it might not...");
-				log("error", "We are going to send from %s instead of %s", host.from_host, from_host);
+				log("error", "We are going to send from %s instead of %s", tostring(host.from_host), tostring(from_host));
 			end
 			host.sends2s(data);
 			host.log("debug", "stanza sent over "..host.type);
@@ -137,6 +137,11 @@
 		print(session, session.from_host, "incoming s2s stream opened");
 		send("<?xml version='1.0'?>");
 		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 }):top_tag());
+		if session.to_host and not hosts[session.to_host] then
+			-- Attempting to connect to a host we don't serve
+			session:disconnect("host-unknown");
+			return;
+		end
 	elseif session.direction == "outgoing" then
 		-- If we are just using the connection for verifying dialback keys, we won't try and auth it
 		if not attr.id then error("stream response did not give us a streamid!!!"); end
@@ -218,9 +223,13 @@
 
 function destroy_session(session)
 	(session.log or log)("info", "Destroying "..tostring(session.direction).." session "..tostring(session.from_host).."->"..tostring(session.to_host));
+	
+	-- FIXME: Flush sendq here/report errors to originators
+	
 	if session.direction == "outgoing" then
 		hosts[session.from_host].s2sout[session.to_host] = nil;
 	end
+	
 	session.conn = nil;
 	session.disconnect = nil;
 	for k in pairs(session) do
--- a/core/sessionmanager.lua	Tue Nov 18 14:42:45 2008 +0000
+++ b/core/sessionmanager.lua	Tue Nov 18 17:52:33 2008 +0000
@@ -35,6 +35,16 @@
 
 function destroy_session(session)
 	(session.log or log)("info", "Destroying session");
+	
+	-- Send unavailable presence
+	if session.presence and session.presence.attr.type ~= "unavailable" then
+		local pres = st.presence{ type = "unavailable" };
+		if err == "closed" then err = "connection closed"; end
+		pres:tag("status"):text("Disconnected: "..err);
+		session.stanza_dispatch(pres);
+	end
+	
+	-- Remove session/resource from user's session list
 	if session.host and session.username then
 		if session.resource then
 			hosts[session.host].sessions[session.username].sessions[session.resource] = nil;
@@ -46,8 +56,7 @@
 			end
 		end
 	end
-	session.conn = nil;
-	session.disconnect = nil;
+	
 	for k in pairs(session) do
 		if k ~= "trace" then
 			session[k] = nil;
--- a/core/xmlhandlers.lua	Tue Nov 18 14:42:45 2008 +0000
+++ b/core/xmlhandlers.lua	Tue Nov 18 17:52:33 2008 +0000
@@ -25,7 +25,7 @@
 						["http://www.w3.org/XML/1998/namespace"] = "xml";
 				}
 
-function init_xmlhandlers(session, streamopened)
+function init_xmlhandlers(session, stream_callbacks)
 		local ns_stack = { "" };
 		local curr_ns = "";
 		local curr_tag;
@@ -36,6 +36,9 @@
 		
 		local send = session.send;
 		
+		local cb_streamopened = stream_callbacks.streamopened;
+		local cb_streamclosed = stream_callbacks.streamclosed;
+		
 		local stanza
 		function xml_handlers:StartElement(name, attr)
 			if stanza and #chardata > 0 then
@@ -65,8 +68,9 @@
 			
 			if not stanza then --if we are not currently inside a stanza
 				if session.notopen then
-					if name == "stream" then
-						streamopened(session, attr);
+					print("client opening with "..tostring(name));
+					if name == "stream" and cb_streamopened then
+						cb_streamopened(session, attr);
 						return;
 					end
 					error("Client failed to open stream successfully");
@@ -75,7 +79,7 @@
 					error("Client sent invalid top-level stanza");
 				end
 				
-				stanza = st.stanza(name, attr); --{ to = attr.to, type = attr.type, id = attr.id, xmlns = curr_ns });
+				stanza = st.stanza(name, attr);
 				curr_tag = stanza;
 			else -- we are inside a stanza, so add a tag
 				attr.xmlns = nil;
@@ -93,9 +97,9 @@
 		function xml_handlers:EndElement(name)
 			curr_ns,name = name:match("^(.+)|([%w%-]+)$");
 			if (not stanza) or #stanza.last_add < 0 or (#stanza.last_add > 0 and name ~= stanza.last_add[#stanza.last_add].name) then 
-				if name == "stream" then
+				if name == "stream" and cb_streamclosed then
 					log("debug", "Stream closed");
-					sm_destroy_session(session);
+					cb_streamclosed(session);
 					return;
 				elseif name == "error" then
 					error("Stream error: "..tostring(name)..": "..tostring(stanza));
--- a/net/xmppclient_listener.lua	Tue Nov 18 14:42:45 2008 +0000
+++ b/net/xmppclient_listener.lua	Tue Nov 18 17:52:33 2008 +0000
@@ -13,8 +13,11 @@
 local format = string.format;
 local sm_new_session, sm_destroy_session = sessionmanager.new_session, sessionmanager.destroy_session; --import("core.sessionmanager", "new_session", "destroy_session");
 local sm_streamopened = sessionmanager.streamopened;
+local sm_streamclosed = sessionmanager.streamclosed;
 local st = stanza;
 
+local stream_callbacks = { streamopened = sm_streamopened, streamclosed = sm_streamclosed };
+
 local sessions = {};
 local xmppclient = { default_port = 5222 };
 
@@ -22,7 +25,7 @@
 
 local function session_reset_stream(session)
 	-- Reset stream
-		local parser = lxp.new(init_xmlhandlers(session, sm_streamopened), "|");
+		local parser = lxp.new(init_xmlhandlers(session, stream_callbacks), "|");
 		session.parser = parser;
 		
 		session.notopen = true;
@@ -107,12 +110,6 @@
 function xmppclient.disconnect(conn, err)
 	local session = sessions[conn];
 	if session then
-		if session.presence and session.presence.attr.type ~= "unavailable" then
-			local pres = st.presence{ type = "unavailable" };
-			if err == "closed" then err = "connection closed"; end
-			pres:tag("status"):text("Disconnected: "..err);
-			session.stanza_dispatch(pres);
-		end
 		(session.log or log)("info", "Client disconnected: %s", err);
 		sm_destroy_session(session);
 		sessions[conn]  = nil;
--- a/net/xmppserver_listener.lua	Tue Nov 18 14:42:45 2008 +0000
+++ b/net/xmppserver_listener.lua	Tue Nov 18 17:52:33 2008 +0000
@@ -5,8 +5,11 @@
 local sm_new_session = require "core.sessionmanager".new_session;
 local s2s_new_incoming = require "core.s2smanager".new_incoming;
 local s2s_streamopened = require "core.s2smanager".streamopened;
+local s2s_streamclosed = require "core.s2smanager".streamopened;
 local s2s_destroy_session = require "core.s2smanager".destroy_session;
 
+local stream_callbacks = { streamopened = s2s_streamopened, streamclosed = s2s_streamclosed };
+
 local connlisteners_register = require "net.connlisteners".register;
 
 local t_insert = table.insert;
@@ -24,7 +27,7 @@
 
 local function session_reset_stream(session)
 	-- Reset stream
-		local parser = lxp.new(init_xmlhandlers(session, s2s_streamopened), "|");
+		local parser = lxp.new(init_xmlhandlers(session, stream_callbacks), "|");
 		session.parser = parser;
 		
 		session.notopen = true;
@@ -43,7 +46,7 @@
 		if reason then
 			if type(reason) == "string" then -- assume stream error
 				log("info", "Disconnecting %s[%s], <stream:error> is: %s", session.host or "(unknown host)", session.type, reason);
-				session.send(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }));
+				session.sends2s(st.stanza("stream:error"):tag(reason, {xmlns = 'urn:ietf:params:xml:ns:xmpp-streams' }));
 			elseif type(reason) == "table" then
 				if reason.condition then
 					local stanza = st.stanza("stream:error"):tag(reason.condition, stream_xmlns_attr):up();
@@ -54,14 +57,14 @@
 						stanza:add_child(reason.extra);
 					end
 					log("info", "Disconnecting %s[%s], <stream:error> is: %s", session.host or "(unknown host)", session.type, tostring(stanza));
-					session.send(stanza);
+					session.sends2s(stanza);
 				elseif reason.name then -- a stanza
-					log("info", "Disconnecting %s[%s], <stream:error> is: %s", session.host or "(unknown host)", session.type, tostring(reason));
-					session.send(reason);
+					log("info", "Disconnecting %s->%s[%s], <stream:error> is: %s", session.from_host or "(unknown host)", session.to_host or "(unknown host)", session.type, tostring(reason));
+					session.sends2s(reason);
 				end
 			end
 		end
-		session.send("</stream:stream>");
+		session.sends2s("</stream:stream>");
 		session.conn.close();
 		xmppserver.disconnect(session.conn, "stream error");
 	end
@@ -100,9 +103,6 @@
 		-- Debug version --
 		local function handleerr(err) print("Traceback:", err, debug.traceback()); end
 		session.stanza_dispatch = function (stanza) return select(2, xpcall(function () return core_process_stanza(session, stanza); end, handleerr));  end
-
---		session.stanza_dispatch = function (stanza) return core_process_stanza(session, stanza); end
-
 	end
 	if data then
 		session.data(conn, data);