# HG changeset patch # User Matthew Wild # Date 1256949707 0 # Node ID 0df3e4d1f1a356c3f77052b9905aec4ab3c25fca # Parent e839b4453387bae48f9963a3d0c792e90a70c0ff mod_proxy65: Reviewed and re-factored the code, added proxy_address to specify the address which the proxy advertises for clients to connect to diff -r e839b4453387 -r 0df3e4d1f1a3 mod_proxy65/mod_proxy65.lua --- 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);