main.lua
changeset 5 57e4eb3aeac0
child 6 7ad47ce20394
equal deleted inserted replaced
-1:000000000000 5:57e4eb3aeac0
       
     1 require "luarocks.require"
       
     2 
       
     3 server = require "server"
       
     4 require "socket"
       
     5 require "ssl"
       
     6 require "lxp"
       
     7 
       
     8 function log(type, area, message)
       
     9 	print(type, area, message);
       
    10 end
       
    11 
       
    12 require "core.stanza_dispatch"
       
    13 init_xmlhandlers = require "core.xmlhandlers"
       
    14 require "core.rostermanager"
       
    15 require "core.offlinemessage"
       
    16 require "core.usermanager"
       
    17 require "util.stanza"
       
    18 require "util.jid"
       
    19 
       
    20 -- Locals for faster access --
       
    21 local t_insert = table.insert;
       
    22 local t_concat = table.concat;
       
    23 local t_concatall = function (t, sep) local tt = {}; for _, s in ipairs(t) do t_insert(tt, tostring(s)); end return t_concat(tt, sep); end
       
    24 local m_random = math.random;
       
    25 local format = string.format;
       
    26 local st = stanza;
       
    27 ------------------------------
       
    28 
       
    29 sessions = {};
       
    30 hosts = 	{ 
       
    31 			["localhost"] = 	{
       
    32 							type = "local";
       
    33 							connected = true;
       
    34 							sessions = {};
       
    35 						};
       
    36 			["getjabber.ath.cx"] = 	{
       
    37 							type = "local";
       
    38 							connected = true;
       
    39 							sessions = {};
       
    40 						};
       
    41 		}
       
    42 
       
    43 local hosts, users = hosts, users;
       
    44 
       
    45 --local ssl_ctx, msg = ssl.newcontext { mode = "server", protocol = "sslv23", key = "/home/matthew/ssl_cert/server.key",
       
    46 --    certificate = "/home/matthew/ssl_cert/server.crt", capath = "/etc/ssl/certs", verify = "none", }
       
    47 --        
       
    48 --if not ssl_ctx then error("Failed to initialise SSL/TLS support: "..tostring(msg)); end
       
    49 
       
    50 
       
    51 local ssl_ctx = { mode = "server", protocol = "sslv23", key = "/home/matthew/ssl_cert/server.key",
       
    52     certificate = "/home/matthew/ssl_cert/server.crt", capath = "/etc/ssl/certs", verify = "none", }
       
    53 
       
    54 
       
    55 function connect_host(host)
       
    56 	hosts[host] = { type = "remote", sendbuffer = {} };
       
    57 end
       
    58 
       
    59 local function send_to(session, to, stanza)
       
    60 	local node, host, resource = jid.split(to);
       
    61 	if not hosts[host] then
       
    62 		-- s2s
       
    63 	elseif hosts[host].type == "local" then
       
    64 		print("   ...is to a local user")
       
    65 		local destuser = hosts[host].sessions[node];
       
    66 		if destuser and destuser.sessions then
       
    67 			if not destuser.sessions[resource] then
       
    68 				local best_session;
       
    69 				for resource, session in pairs(destuser.sessions) do
       
    70 					if not best_session then best_session = session;
       
    71 					elseif session.priority >= best_session.priority and session.priority >= 0 then
       
    72 						best_session = session;
       
    73 					end
       
    74 				end
       
    75 				if not best_session then
       
    76 					offlinemessage.new(node, host, stanza);
       
    77 				else
       
    78 					print("resource '"..resource.."' was not online, have chosen to send to '"..best_session.username.."@"..best_session.host.."/"..best_session.resource.."'");
       
    79 					resource = best_session.resource;
       
    80 				end
       
    81 			end
       
    82 			if destuser.sessions[resource] == session then
       
    83 				log("warn", "core", "Attempt to send stanza to self, dropping...");
       
    84 			else
       
    85 				print("...sending...", tostring(stanza));
       
    86 				--destuser.sessions[resource].conn.write(tostring(data));
       
    87 				print("   to conn ", destuser.sessions[resource].conn);
       
    88 				destuser.sessions[resource].conn.write(tostring(stanza));
       
    89 				print("...sent")
       
    90 			end
       
    91 		elseif stanza.name == "message" then
       
    92 			print("   ...will be stored offline");
       
    93 			offlinemessage.new(node, host, stanza);
       
    94 		elseif stanza.name == "iq" then
       
    95 			print("   ...is an iq");
       
    96 			session.send(st.reply(stanza)
       
    97 				:tag("error", { type = "cancel" })
       
    98 					:tag("service-unavailable", { xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas" }));
       
    99 		end
       
   100 		print("   ...done routing");
       
   101 	end
       
   102 end
       
   103 
       
   104 function handler(conn, data, err)
       
   105 	local session = sessions[conn];
       
   106 	
       
   107 	if not session then
       
   108 		sessions[conn] = { conn = conn, notopen = true, priority = 0 };
       
   109 		session = sessions[conn];
       
   110 
       
   111 		-- Logging functions --
       
   112 
       
   113 		local mainlog, log = log;
       
   114 		do
       
   115 			local conn_name = tostring(conn):match("%w+$");
       
   116 			log = function (type, area, message) mainlog(type, conn_name, message); end
       
   117 		end
       
   118 		local print = function (...) log("info", "core", t_concatall({...}, "\t")); end
       
   119 		session.log = log;
       
   120 
       
   121 		--	--	--
       
   122 
       
   123 		-- Send buffers --
       
   124 
       
   125 		local send = function (data) print("Sending...", tostring(data)); conn.write(tostring(data)); end;
       
   126 		session.send, session.send_to = send, send_to;
       
   127 
       
   128 			print("Client connected");
       
   129 		
       
   130 			session.stanza_dispatch = init_stanza_dispatcher(session);
       
   131 			session.xml_handlers = init_xmlhandlers(session);
       
   132 			session.parser = lxp.new(session.xml_handlers, ":");
       
   133 			
       
   134 			function session.disconnect(err)
       
   135 				if session.last_presence.attr.type ~= "unavailable" then
       
   136 					local pres = st.presence{ type = "unavailable" };
       
   137 					if err == "closed" then err = "connection closed"; end
       
   138 					pres:tag("status"):text("Disconnected: "..err);
       
   139 					session.stanza_dispatch(pres);
       
   140 				end
       
   141 				hosts[session.host].sessions[session.username] = nil;
       
   142 				session = nil;
       
   143 				print("Disconnected: "..err);
       
   144 			end
       
   145 		end
       
   146 	if data then
       
   147 		session.parser:parse(data);
       
   148 	end
       
   149 	
       
   150 	--log("info", "core", "Client disconnected, connection closed");
       
   151 end
       
   152 
       
   153 function disconnect(conn, err)
       
   154 	sessions[conn].disconnect(err);
       
   155 end
       
   156 
       
   157 print("ssl_ctx:", type(ssl_ctx));
       
   158 
       
   159 setmetatable(_G, { __index = function (t, k) print("WARNING: ATTEMPT TO READ A NIL GLOBAL!!!", k); error("Attempt to read a non-existent global. Naughty boy.", 2); end, __newindex = function (t, k, v) print("ATTEMPT TO SET A GLOBAL!!!!", tostring(k).." = "..tostring(v)); error("Attempt to set a global. Naughty boy.", 2); end }) --]][][[]][];
       
   160 
       
   161 
       
   162 local protected_handler = function (...) local success, ret = pcall(handler, ...); if not success then print("ERROR on "..tostring((select(1, ...)))..": "..ret); end end;
       
   163 local protected_disconnect = function (...) local success, ret = pcall(disconnect, ...); if not success then print("ERROR on "..tostring((select(1, ...))).." disconnect: "..ret); end end;
       
   164 
       
   165 print( server.add( { listener = protected_handler, disconnect = protected_disconnect }, 5222, "*", 1, nil ) )    -- server.add will send a status message
       
   166 print( server.add( { listener = protected_handler, disconnect = protected_disconnect }, 5223, "*", 1, ssl_ctx ) )    -- server.add will send a status message
       
   167 
       
   168 server.loop();