changeset 68:0df3e4d1f1a3

mod_proxy65: Reviewed and re-factored the code, added proxy_address to specify the address which the proxy advertises for clients to connect to
author Matthew Wild <mwild1@gmail.com>
date Sat, 31 Oct 2009 00:41:47 +0000
parents e839b4453387
children 87dfd34dceb2
files mod_proxy65/mod_proxy65.lua
diffstat 1 files changed, 55 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/mod_proxy65/mod_proxy65.lua	Fri Oct 30 01:32:12 2009 +0100
+++ b/mod_proxy65/mod_proxy65.lua	Sat Oct 31 00:41:47 2009 +0000
@@ -22,24 +22,21 @@
 local add_task = require "util.timer".add_task;
 local max_dns_depth = config.get("*", "core", "dns_max_depth") or 3;
 local dns_timeout = config.get("*", "core", "dns_timeout") or 60;
-local serialize = require "util.serialization".serialize;
 local sha1 = require "util.hashes".sha1;
 
 local replies_cache = {};
-local _host = module:get_host();
-local _name = "SOCKS5 Bytestreams Service";
-local connlistener = {registered=false};
-local _config = {};
-local sessions = {};
-local transfers = {};
-local component;
+local host = module:get_host();
+local name = "SOCKS5 Bytestreams Service";
+local sessions, transfers, component = {}, {}, nil;
 
-_config.port = config_get(_host, "core", "port");
-_config.interface = config_get(_host, "core", "interface");
+local proxy_port = config_get(host, "core", "proxy65_port") or 5000;
+local proxy_interface = config_get(host, "core", "proxy65_interface") or "*";
+local proxy_address = config_get(host, "core", "proxy65_address") or (proxy_interface ~= "*" and proxy_interface) or module.host;
 
-if _config.port == nil then
-	_config.port = 5000;
-end
+local connlistener = {
+	registered = false, default_port = proxy_port, 
+	default_interface = proxy_interface, default_mode = "*a"
+	};
 
 local function bin2hex(bin)
 	return bin:gsub(".", function (c) return ("%02x"):format(c:byte()); end)
@@ -49,10 +46,8 @@
 	local w = function(s) conn.write(s:gsub("\n", "\r\n")); end;
 	local session = { conn = conn;
 			send = function (t) w(tostring(t)); end;
-			print = function (t) w("| "..tostring(t).."\n"); end;
 			disconnect = function () conn.close(); end;
 			};
-	
 	return session;
 end
 
@@ -112,14 +107,17 @@
 end
 
 function connlistener.disconnect(conn, err)
-
+	if sessions[conn] then
+		-- Clean up any session-related stuff here
+		sessions[conn] = nil;
+	end
 end
 
 local function get_disco_info(stanza)
 	local reply = replies_cache.disco_info;
 	if reply == nil then
-	 	reply = st.iq({type='result', from=_host}):query("http://jabber.org/protocol/disco#info")
-			:tag("identity", {category='proxy', type='bytestreams', name=_name}):up()
+	 	reply = st.iq({type='result', from=host}):query("http://jabber.org/protocol/disco#info")
+			:tag("identity", {category='proxy', type='bytestreams', name=name}):up()
 			:tag("feature", {var="http://jabber.org/protocol/bytestreams"});
 		replies_cache.disco_info = reply;
 	end
@@ -132,7 +130,7 @@
 local function get_disco_items(stanza)
 	local reply = replies_cache.disco_items;
 	if reply == nil then
-	 	reply = st.iq({type='result', from=_host}):query("http://jabber.org/protocol/disco#items");
+	 	reply = st.iq({type='result', from=host}):query("http://jabber.org/protocol/disco#items");
 		replies_cache.disco_info = reply;
 	end
 	
@@ -145,9 +143,9 @@
 	local reply = replies_cache.stream_host;
 	local sid = stanza.tags[1].attr.sid;
 	if reply == nil then
-		reply = st.iq({type="result", from=_host})
+		reply = st.iq({type="result", from=host})
 			:query("http://jabber.org/protocol/bytestreams")
-			:tag("streamhost", {jid=_host, host=_config.interface, port=_config.port}); -- TODO get the correct data
+			:tag("streamhost", {jid=host, host=proxy_address, port=proxy_port}); -- TODO get the correct data
 		replies_cache.stream_host = reply;
 	end
 	
@@ -158,18 +156,13 @@
 end
 
 module.unload = function()
-	component_deregister(_host);
+	component_deregister(host);
 	connlisteners_deregister("proxy65");
 end
 
 local function set_activation(stanza)
-	local from = nil;
-	local to = nil;
-	local sid = nil;
-	local reply = nil;
-	if stanza.attr ~= nil then
-		from = stanza.attr.from;
-	end
+	local from, to, sid, reply = nil;
+	from = stanza.attr.from;
 	if stanza.tags[1] ~= nil and tostring(stanza.tags[1].name) == "query" then
 		if stanza.tags[1].attr ~= nil then
 			sid = stanza.tags[1].attr.sid;
@@ -179,106 +172,48 @@
 		end
 	end
 	if from ~= nil and to ~= nil and sid ~= nil then
-		reply = st.iq({type="result", from=_host});
+		reply = st.iq({type="result", from=host});
 		reply.attr.id = stanza.attr.id;
 	end
 	return reply, from, to, sid;
 end
 
-local function forward(initiator, target)
-	module:log("debug", "forward it ....");
-end
-
-
-local function register()
-	connlistener.default_port = _config.port;
-	connlistener.default_interface = "*"; 
-	connlistener.default_mode = "*a";
-	connlistener.registered = connlisteners_register('proxy65', connlistener);
-	if(connlistener.registered == false) then
-		error("Proxy65: Could not establish a connection listener. Check your configuration please.");
-	else
-		connlistener.handler = connlisteners_start('proxy65');
-		module:add_item("proxy65", {jid=_host, name=_name})
-		component = component_register(_host, function(origin, stanza)
-			local to_node, to_host, to_resource = jid_split(stanza.attr.to);
-			if to_node == nil then
-				local type = stanza.attr.type;
-				if type == "error" or type == "result" then return; end
-				if stanza.name == "iq" and type == "get" then
-					local xmlns = stanza.tags[1].attr.xmlns
-					if xmlns == "http://jabber.org/protocol/disco#info" then
-						origin.send(get_disco_info(stanza));
-						return true;
-					elseif xmlns == "http://jabber.org/protocol/disco#items" then
-						origin.send(get_disco_items(stanza));
-						return true;
-					elseif xmlns == "http://jabber.org/protocol/bytestreams" then
-						origin.send(get_stream_host(stanza));
-						return true;
-					end
-				elseif stanza.name == "iq" and type == "set" then
-					local reply, from, to, sid = set_activation(stanza);
-					if reply ~= nil and from ~= nil and to ~= nil and sid ~= nil then
-						local sha = sha1(sid .. from .. to, true);
-						if transfers[sha] == nil then
-							module:log("error", "transfers[sha]: nil");
-						elseif(transfers[sha] ~= nil and transfers[sha].initiator ~= nil and transfers[sha].target ~= nil) then
-							origin.send(reply);
-							transfers[sha].activated = true;
-						end
-					end
+function handle_to_domain(origin, stanza)
+	local to_node, to_host, to_resource = jid_split(stanza.attr.to);
+	if to_node == nil then
+		local type = stanza.attr.type;
+		if type == "error" or type == "result" then return; end
+		if stanza.name == "iq" and type == "get" then
+			local xmlns = stanza.tags[1].attr.xmlns
+			if xmlns == "http://jabber.org/protocol/disco#info" then
+				origin.send(get_disco_info(stanza));
+				return true;
+			elseif xmlns == "http://jabber.org/protocol/disco#items" then
+				origin.send(get_disco_items(stanza));
+				return true;
+			elseif xmlns == "http://jabber.org/protocol/bytestreams" then
+				origin.send(get_stream_host(stanza));
+				return true;
+			end
+		elseif stanza.name == "iq" and type == "set" then
+			local reply, from, to, sid = set_activation(stanza);
+			if reply ~= nil and from ~= nil and to ~= nil and sid ~= nil then
+				local sha = sha1(sid .. from .. to, true);
+				if transfers[sha] == nil then
+					module:log("error", "transfers[sha]: nil");
+				elseif(transfers[sha] ~= nil and transfers[sha].initiator ~= nil and transfers[sha].target ~= nil) then
+					origin.send(reply);
+					transfers[sha].activated = true;
 				end
 			end
-			return;
-		end);
+		end
 	end
+	return;
 end
 
-local function getDefaultIP(host)
-	local handle;
-	handle = adns.lookup(function (reply)
-		handle = nil;
-
-		-- COMPAT: This is a compromise for all you CNAME-(ab)users :)
-		if not (reply and reply[#reply] and reply[#reply].a) then
-			local count = max_dns_depth;
-			reply = dns.peek(host, "CNAME", "IN");
-			while count > 0 and reply and reply[#reply] and not reply[#reply].a and reply[#reply].cname do
-				module:log("debug", "Looking up %s (DNS depth is %d)", tostring(reply[#reply].cname), count);
-				reply = dns.peek(reply[#reply].cname, "A", "IN") or dns.peek(reply[#reply].cname, "CNAME", "IN");
-				count = count - 1;
-			end
-		end
-		-- end of CNAME resolving
-
-		if reply and reply[#reply] and reply[#reply].a then
-			module:log("debug", "DNS reply for %s gives us %s", host, reply[#reply].a);
-			_config.interface = reply[#reply].a
-			return register();
-		else
-			module:log("debug", "DNS lookup failed to get a response for %s", host);
-			if host:find(".") ~= nil then
-				host = host:gsub("^[^%.]*%.", "");
-				if host:find(".") ~= nil then -- still one dot left?
-					return getDefaultIP(host);
-				end
-			end
-			error("Proxy65: Could not get an interface to bind to. Please configure one.");
-		end
-	end, host, "A", "IN");
-
-	-- Set handler for DNS timeout
-	add_task(dns_timeout, function ()
-		if handle then
-			adns.cancel(handle, true);
-		end
-	end);
-	return true;
+if not connlisteners_register('proxy65', connlistener) then
+	error("mod_proxy65: Could not establish a connection listener. Check your configuration please.");
 end
 
-if _config.interface ~= nil then
-	register();
-else
-	getDefaultIP(_host); -- try to DNS lookup module:host()
-end
+connlisteners_start('proxy65');
+component = component_register(host, handle_to_domain);