core/s2smanager.lua

changeset 282
80e7de32b618
parent 269
3cfac0e5e6ca
child 327
9439362caacc
equal deleted inserted replaced
280:516f4c901991 282:80e7de32b618
2 local hosts = hosts; 2 local hosts = hosts;
3 local sessions = sessions; 3 local sessions = sessions;
4 local socket = require "socket"; 4 local socket = require "socket";
5 local format = string.format; 5 local format = string.format;
6 local t_insert = table.insert; 6 local t_insert = table.insert;
7 local get_traceback = debug.traceback;
7 local tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber 8 local tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber
8 = tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber; 9 = tostring, pairs, ipairs, getmetatable, print, newproxy, error, tonumber;
9 10
10 local connlisteners_get = require "net.connlisteners".get; 11 local connlisteners_get = require "net.connlisteners".get;
11 local wraptlsclient = require "net.server".wraptlsclient; 12 local wraptlsclient = require "net.server".wraptlsclient;
12 local modulemanager = require "core.modulemanager"; 13 local modulemanager = require "core.modulemanager";
14 local st = require "stanza";
15 local stanza = st.stanza;
13 16
14 local uuid_gen = require "util.uuid".generate; 17 local uuid_gen = require "util.uuid".generate;
15 18
16 local logger_init = require "util.logger".init; 19 local logger_init = require "util.logger".init;
17 20
19 22
20 local md5_hash = require "util.hashes".md5; 23 local md5_hash = require "util.hashes".md5;
21 24
22 local dialback_secret = "This is very secret!!! Ha!"; 25 local dialback_secret = "This is very secret!!! Ha!";
23 26
24 local srvmap = { ["gmail.com"] = "talk.google.com", ["identi.ca"] = "longlance.controlezvous.ca", ["cdr.se"] = "jabber.cdr.se" }; 27 local srvmap = { ["gmail.com"] = "talk.google.com", ["identi.ca"] = "hampton.controlezvous.ca", ["cdr.se"] = "jabber.cdr.se" };
25 28
26 module "s2smanager" 29 module "s2smanager"
27 30
28 function connect_host(from_host, to_host)
29 end
30
31 function send_to_host(from_host, to_host, data) 31 function send_to_host(from_host, to_host, data)
32 local host = hosts[to_host]; 32 local host = hosts[from_host].s2sout[to_host];
33 if host then 33 if host then
34 -- Write to connection 34 -- We have a connection to this host already
35 if host.type == "s2sout_unauthed" and not host.notopen and not host.dialback_key then 35 if host.type == "s2sout_unauthed" then
36 log("debug", "trying to send over unauthed s2sout to "..to_host..", authing it now..."); 36 host.log("debug", "trying to send over unauthed s2sout to "..to_host..", authing it now...");
37 initiate_dialback(host); 37 if not host.notopen and not host.dialback_key then
38 if not host.sendq then host.sendq = { data }; 38 host.log("debug", "dialback had not been initiated");
39 else t_insert(host.sendq, data); end 39 initiate_dialback(host);
40 end
41
42 -- Queue stanza until we are able to send it
43 if host.sendq then t_insert(host.sendq, data);
44 else host.sendq = { data }; end
45 elseif host.type == "local" or host.type == "component" then
46 log("error", "Trying to send a stanza to ourselves??")
47 log("error", "Traceback: %s", get_traceback());
48 log("error", "Stanza: %s", tostring(data));
40 else 49 else
41 log("debug", "going to send stanza to "..to_host.." from "..from_host); 50 (host.log or log)("debug", "going to send stanza to "..to_host.." from "..from_host);
42 -- FIXME 51 -- FIXME
43 if hosts[to_host].from_host ~= from_host then log("error", "WARNING! This might, possibly, be a bug, but it might not..."); end 52 if host.from_host ~= from_host then
44 hosts[to_host].sends2s(data); 53 log("error", "WARNING! This might, possibly, be a bug, but it might not...");
45 log("debug", "stanza sent over "..hosts[to_host].type); 54 log("error", "We are going to send from %s instead of %s", host.from_host, from_host);
55 end
56 host.sends2s(data);
57 host.log("debug", "stanza sent over "..host.type);
46 end 58 end
47 else 59 else
48 log("debug", "opening a new outgoing connection for this stanza"); 60 log("debug", "opening a new outgoing connection for this stanza");
49 local host_session = new_outgoing(from_host, to_host); 61 local host_session = new_outgoing(from_host, to_host);
50 -- Store in buffer 62 -- Store in buffer
51 host_session.sendq = { data }; 63 host_session.sendq = { data };
52 end 64 end
53 end 65 end
54 66
55 function disconnect_host(host)
56
57 end
58
59 local open_sessions = 0; 67 local open_sessions = 0;
60 68
61 function new_incoming(conn) 69 function new_incoming(conn)
62 local session = { conn = conn, type = "s2sin_unauthed", direction = "incoming" }; 70 local session = { conn = conn, type = "s2sin_unauthed", direction = "incoming" };
63 if true then 71 if true then
70 return session; 78 return session;
71 end 79 end
72 80
73 function new_outgoing(from_host, to_host) 81 function new_outgoing(from_host, to_host)
74 local host_session = { to_host = to_host, from_host = from_host, notopen = true, type = "s2sout_unauthed", direction = "outgoing" }; 82 local host_session = { to_host = to_host, from_host = from_host, notopen = true, type = "s2sout_unauthed", direction = "outgoing" };
75 hosts[to_host] = host_session; 83 hosts[from_host].s2sout[to_host] = host_session;
76 local cl = connlisteners_get("xmppserver"); 84 local cl = connlisteners_get("xmppserver");
77 85
78 local conn, handler = socket.tcp() 86 local conn, handler = socket.tcp()
79 87
88 --FIXME: Below parameters (ports/ip) are incorrect (use SRV)
89 to_host = srvmap[to_host] or to_host;
90
91 conn:settimeout(0);
92 local success, err = conn:connect(to_host, 5269);
93 if not success then
94 log("warn", "s2s connect() failed: %s", err);
95 end
96
97 conn = wraptlsclient(cl, conn, to_host, 5269, 0, 1, hosts[from_host].ssl_ctx );
98 host_session.conn = conn;
80 99
81 -- Register this outgoing connection so that xmppserver_listener knows about it 100 -- Register this outgoing connection so that xmppserver_listener knows about it
82 -- otherwise it will assume it is a new incoming connection 101 -- otherwise it will assume it is a new incoming connection
83 cl.register_outgoing(conn, host_session); 102 cl.register_outgoing(conn, host_session);
84 103
85 --FIXME: Below parameters (ports/ip) are incorrect (use SRV)
86 to_host = srvmap[to_host] or to_host;
87 conn:settimeout(0.1);
88 conn:connect(to_host, 5269);
89 conn = wraptlsclient(cl, conn, to_host, 5269, 0, 1, hosts[from_host].ssl_ctx );
90 host_session.conn = conn;
91
92 do 104 do
93 local conn_name = "s2sout"..tostring(conn):match("[a-f0-9]*$"); 105 local conn_name = "s2sout"..tostring(conn):match("[a-f0-9]*$");
94 host_session.log = logger_init(conn_name); 106 host_session.log = logger_init(conn_name);
95 end 107 end
96 108
101 113
102 return host_session; 114 return host_session;
103 end 115 end
104 116
105 function streamopened(session, attr) 117 function streamopened(session, attr)
106 session.log("debug", "s2s stream opened");
107 local send = session.sends2s; 118 local send = session.sends2s;
108 119
109 session.version = tonumber(attr.version) or 0; 120 session.version = tonumber(attr.version) or 0;
110 if session.version >= 1.0 and not (attr.to and attr.from) then 121 if session.version >= 1.0 and not (attr.to and attr.from) then
111 print("to: "..tostring(attr.to).." from: "..tostring(attr.from)); 122 print("to: "..tostring(attr.to).." from: "..tostring(attr.from));
122 session.from_host = attr.from; 133 session.from_host = attr.from;
123 134
124 session.streamid = uuid_gen(); 135 session.streamid = uuid_gen();
125 print(session, session.from_host, "incoming s2s stream opened"); 136 print(session, session.from_host, "incoming s2s stream opened");
126 send("<?xml version='1.0'?>"); 137 send("<?xml version='1.0'?>");
127 send(format("<stream:stream xmlns='jabber:server' xmlns:db='jabber:server:dialback' xmlns:stream='http://etherx.jabber.org/streams' id='%s' from='%s'>", session.streamid, session.to_host)); 138 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());
128 elseif session.direction == "outgoing" then 139 elseif session.direction == "outgoing" then
129 -- If we are just using the connection for verifying dialback keys, we won't try and auth it 140 -- If we are just using the connection for verifying dialback keys, we won't try and auth it
130 if not attr.id then error("stream response did not give us a streamid!!!"); end 141 if not attr.id then error("stream response did not give us a streamid!!!"); end
131 session.streamid = attr.id; 142 session.streamid = attr.id;
132 143
145 for _, feature in ipairs(features) do 156 for _, feature in ipairs(features) do
146 send(tostring(feature)); 157 send(tostring(feature));
147 end 158 end
148 159
149 send("</stream:features>");]] 160 send("</stream:features>");]]
150 log("info", "s2s stream opened successfully"); 161
151 session.notopen = nil; 162 session.notopen = nil;
152 end 163 end
153 164
154 function initiate_dialback(session) 165 function initiate_dialback(session)
155 -- generate dialback key 166 -- generate dialback key
192 function session.send(data) send_to_host(to, from, data); end 203 function session.send(data) send_to_host(to, from, data); end
193 204
194 205
195 if session.direction == "outgoing" then 206 if session.direction == "outgoing" then
196 if sendq then 207 if sendq then
197 session.log("debug", "sending queued stanzas across new outgoing connection to "..session.to_host); 208 session.log("debug", "sending "..#sendq.." queued stanzas across new outgoing connection to "..session.to_host);
198 for i, data in ipairs(sendq) do 209 for i, data in ipairs(sendq) do
199 send(data); 210 send(data);
200 sendq[i] = nil; 211 sendq[i] = nil;
201 end 212 end
202 session.sendq = nil; 213 session.sendq = nil;
205 end 216 end
206 217
207 function destroy_session(session) 218 function destroy_session(session)
208 (session.log or log)("info", "Destroying "..tostring(session.direction).." session "..tostring(session.from_host).."->"..tostring(session.to_host)); 219 (session.log or log)("info", "Destroying "..tostring(session.direction).." session "..tostring(session.from_host).."->"..tostring(session.to_host));
209 if session.direction == "outgoing" then 220 if session.direction == "outgoing" then
210 hosts[session.to_host] = nil; 221 hosts[session.from_host].s2sout[session.to_host] = nil;
211 end 222 end
212 session.conn = nil; 223 session.conn = nil;
213 session.disconnect = nil; 224 session.disconnect = nil;
214 for k in pairs(session) do 225 for k in pairs(session) do
215 if k ~= "trace" then 226 if k ~= "trace" then

mercurial