Software /
code /
prosody
Comparison
core/s2smanager.lua @ 434:0d7ba3742f7a
(Basic) IDNA and SRV fallback support
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Wed, 26 Nov 2008 23:44:30 +0000 |
parent | 360:e918c979ad1a |
child | 435:4087aa611de2 |
comparison
equal
deleted
inserted
replaced
433:afbf29498123 | 434:0d7ba3742f7a |
---|---|
6 local t_insert, t_sort = table.insert, table.sort; | 6 local t_insert, t_sort = table.insert, table.sort; |
7 local get_traceback = debug.traceback; | 7 local get_traceback = debug.traceback; |
8 local tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber | 8 local tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber |
9 = tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber; | 9 = tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber; |
10 | 10 |
11 local idna_to_ascii = require "util.encodings".idna.to_ascii; | |
11 local connlisteners_get = require "net.connlisteners".get; | 12 local connlisteners_get = require "net.connlisteners".get; |
12 local wraptlsclient = require "net.server".wraptlsclient; | 13 local wraptlsclient = require "net.server".wraptlsclient; |
13 local modulemanager = require "core.modulemanager"; | 14 local modulemanager = require "core.modulemanager"; |
14 local st = require "stanza"; | 15 local st = require "stanza"; |
15 local stanza = st.stanza; | 16 local stanza = st.stanza; |
82 end | 83 end |
83 | 84 |
84 function new_outgoing(from_host, to_host) | 85 function new_outgoing(from_host, to_host) |
85 local host_session = { to_host = to_host, from_host = from_host, notopen = true, type = "s2sout_unauthed", direction = "outgoing" }; | 86 local host_session = { to_host = to_host, from_host = from_host, notopen = true, type = "s2sout_unauthed", direction = "outgoing" }; |
86 hosts[from_host].s2sout[to_host] = host_session; | 87 hosts[from_host].s2sout[to_host] = host_session; |
87 local cl = connlisteners_get("xmppserver"); | 88 |
88 | 89 local log; |
89 local conn, handler = socket.tcp() | 90 do |
90 | 91 local conn_name = "s2sout"..tostring(conn):match("[a-f0-9]*$"); |
91 local connect_host, connect_port = to_host, 5269; | 92 log = logger_init(conn_name); |
92 | 93 host_session.log = log; |
93 local answer = dns.lookup("_xmpp-server._tcp."..to_host..".", "SRV"); | 94 end |
95 | |
96 attempt_connection(host_session); | |
97 | |
98 return host_session; | |
99 end | |
100 | |
101 | |
102 function attempt_connection(host_session, err) | |
103 local from_host, to_host = host_session.from_host, host_session.to_host; | |
104 local conn, handler = socket.tcp() | |
105 | |
106 local connect_host, connect_port = idna_to_ascii(to_host), 5269; | |
107 | |
108 if not err then -- This is our first attempt | |
109 local answer = dns.lookup("_xmpp-server._tcp."..connect_host..".", "SRV"); | |
94 | 110 |
95 if answer then | 111 if answer then |
96 log("debug", to_host.." has SRV records, handling..."); | 112 log("debug", to_host.." has SRV records, handling..."); |
97 local srv_hosts = {}; | 113 local srv_hosts = {}; |
98 host_session.srv_hosts = srv_hosts; | 114 host_session.srv_hosts = srv_hosts; |
100 t_insert(srv_hosts, record.srv); | 116 t_insert(srv_hosts, record.srv); |
101 end | 117 end |
102 t_sort(srv_hosts, compare_srv_priorities); | 118 t_sort(srv_hosts, compare_srv_priorities); |
103 | 119 |
104 local srv_choice = srv_hosts[1]; | 120 local srv_choice = srv_hosts[1]; |
121 host_session.srv_choice = 1; | |
105 if srv_choice then | 122 if srv_choice then |
106 connect_host, connect_port = srv_choice.target or to_host, srv_choice.port or connect_port; | 123 connect_host, connect_port = srv_choice.target or to_host, srv_choice.port or connect_port; |
107 log("debug", "Best record found, will connect to %s:%d", connect_host, connect_port); | 124 log("debug", "Best record found, will connect to %s:%d", connect_host, connect_port); |
108 end | 125 end |
109 end | 126 end |
110 | 127 elseif host_session.srv_hosts and #host_session.srv_hosts > host_session.srv_choice then -- Not our first attempt, and we also have SRV |
111 conn:settimeout(0); | 128 host_session.srv_choice = host_session.srv_choice + 1; |
112 local success, err = conn:connect(connect_host, connect_port); | 129 local srv_choice = host_session.srv_hosts[host_session.srv_choice]; |
113 if not success and err ~= "timeout" then | 130 connect_host, connect_port = srv_choice.target or to_host, srv_choice.port or connect_port; |
114 log("warn", "s2s connect() failed: %s", err); | 131 host_session.log("debug", "Attempt #%d: This time to %s:%d", host_session.srv_choice, connect_host, connect_port); |
115 end | 132 else |
116 | 133 host_session.log("debug", "Out of connection options, can't connect to %s", tostring(host_session.to_host)); |
117 conn = wraptlsclient(cl, conn, connect_host, connect_port, 0, 1, hosts[from_host].ssl_ctx ); | 134 -- We're out of options |
118 host_session.conn = conn; | 135 return false; |
119 | 136 end |
120 -- Register this outgoing connection so that xmppserver_listener knows about it | 137 |
121 -- otherwise it will assume it is a new incoming connection | 138 -- Ok, we're going to try to connect |
122 cl.register_outgoing(conn, host_session); | 139 conn:settimeout(0); |
123 | 140 local success, err = conn:connect(connect_host, connect_port); |
124 local log; | 141 if not success and err ~= "timeout" then |
125 do | 142 log("warn", "s2s connect() failed: %s", err); |
126 local conn_name = "s2sout"..tostring(conn):match("[a-f0-9]*$"); | 143 end |
127 log = logger_init(conn_name); | 144 |
128 host_session.log = log; | 145 local cl = connlisteners_get("xmppserver"); |
129 end | 146 conn = wraptlsclient(cl, conn, connect_host, connect_port, 0, 1, hosts[from_host].ssl_ctx ); |
130 | 147 host_session.conn = conn; |
131 local w = conn.write; | 148 |
132 host_session.sends2s = function (t) log("debug", "sending: %s", tostring(t)); w(tostring(t)); end | 149 -- Register this outgoing connection so that xmppserver_listener knows about it |
133 | 150 -- otherwise it will assume it is a new incoming connection |
134 conn.write(format([[<stream:stream xmlns='jabber:server' xmlns:db='jabber:server:dialback' xmlns:stream='http://etherx.jabber.org/streams' from='%s' to='%s' version='1.0'>]], from_host, to_host)); | 151 cl.register_outgoing(conn, host_session); |
135 | 152 |
136 return host_session; | 153 local w = conn.write; |
154 host_session.sends2s = function (t) log("debug", "sending: %s", tostring(t)); w(tostring(t)); end | |
155 | |
156 conn.write(format([[<stream:stream xmlns='jabber:server' xmlns:db='jabber:server:dialback' xmlns:stream='http://etherx.jabber.org/streams' from='%s' to='%s' version='1.0'>]], from_host, to_host)); | |
157 return true; | |
137 end | 158 end |
138 | 159 |
139 function streamopened(session, attr) | 160 function streamopened(session, attr) |
140 local send = session.sends2s; | 161 local send = session.sends2s; |
141 | 162 |
157 (session.log or log)("debug", "incoming s2s received <stream:stream>"); | 178 (session.log or log)("debug", "incoming s2s received <stream:stream>"); |
158 send("<?xml version='1.0'?>"); | 179 send("<?xml version='1.0'?>"); |
159 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()); | 180 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()); |
160 if session.to_host and not hosts[session.to_host] then | 181 if session.to_host and not hosts[session.to_host] then |
161 -- Attempting to connect to a host we don't serve | 182 -- Attempting to connect to a host we don't serve |
162 session:close("host-unknown"); | 183 session:close({ condition = "host-unknown"; text = "This host does not serve "..session.to_host }); |
163 return; | 184 return; |
164 end | 185 end |
165 if session.version >= 1.0 then | 186 if session.version >= 1.0 then |
166 send(st.stanza("stream:features") | 187 send(st.stanza("stream:features") |
167 :tag("dialback", { xmlns='urn:xmpp:features:dialback' }):tag("optional"):up():up()); | 188 :tag("dialback", { xmlns='urn:xmpp:features:dialback' }):tag("optional"):up():up()); |