main.lua
author matthew
Fri, 22 Aug 2008 21:09:04 +0000
changeset 0 3e3171b59028
child 1 b8787e859fd2
permissions -rw-r--r--
First commit, where do you want to go tomorrow?
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     1
require "luarocks.require"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     2
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     3
require "copas"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     4
require "socket"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     5
require "ssl"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     6
require "lxp"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     7
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     8
function log(type, area, message)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
     9
	print(type, area, message);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    10
end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    11
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    12
require "core.stanza_dispatch"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    13
require "core.rostermanager"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    14
require "core.offlinemessage"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    15
require "util.stanza"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    16
require "util.jid"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    17
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    18
-- Locals for faster access --
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    19
local t_insert = table.insert;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    20
local t_concat = table.concat;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    21
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
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    22
local m_random = math.random;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    23
local format = string.format;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    24
local st = stanza;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    25
------------------------------
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    26
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    27
users = {};
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    28
hosts = 	{ 
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    29
			["localhost"] = 	{
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    30
							type = "local";
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    31
							connected = true;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    32
							sessions = {};
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    33
						};
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    34
			["getjabber.ath.cx"] = 	{
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    35
							type = "local";
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    36
							connected = true;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    37
							sessions = {};
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    38
						};
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    39
		}
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    40
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    41
local hosts, users = hosts, users;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    42
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    43
local ssl_ctx, msg = ssl.newcontext { mode = "server", protocol = "sslv23", key = "/home/matthew/ssl_cert/server.key",
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    44
    certificate = "/home/matthew/ssl_cert/server.crt", capath = "/etc/ssl/certs", verify = "none", }
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    45
        
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    46
if not ssl_ctx then error("Failed to initialise SSL/TLS support: "..tostring(msg)); end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    47
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    48
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    49
function connect_host(host)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    50
	hosts[host] = { type = "remote", sendbuffer = {} };
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    51
end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    52
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    53
function handler(conn)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    54
	local copas_receive, copas_send = copas.receive, copas.send;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    55
	local reqdata, sktmsg;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    56
	local session = { sendbuffer = { external = {} }, conn = conn, notopen = true, priority = 0 }
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    57
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    58
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    59
	-- Logging functions --
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    60
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    61
	local mainlog, log = log;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    62
	do
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    63
		local conn_name = tostring(conn):match("%w+$");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    64
		log = function (type, area, message) mainlog(type, conn_name, message); end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    65
	end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    66
	local print = function (...) log("info", "core", t_concatall({...}, "\t")); end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    67
	session.log = log;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    68
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    69
	--	--	--
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    70
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    71
	-- Send buffers --
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    72
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    73
	local sendbuffer = session.sendbuffer;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    74
	local send = function (data) return t_insert(sendbuffer, tostring(data)); end;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    75
	local send_to = 	function (to, stanza)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    76
					local node, host, resource = jid.split(to);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    77
					print("Routing stanza to "..to..":", node, host, resource);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    78
					if not hosts[host] then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    79
						print("   ...but host offline, establishing connection");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    80
						connect_host(host);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    81
						t_insert(hosts[host].sendbuffer, stanza); -- This will be sent when s2s connection succeeds					
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    82
					elseif hosts[host].connected then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    83
						print("   ...putting in our external send buffer");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    84
						t_insert(sendbuffer.external, { node = node, host = host, resource = resource, data = stanza});
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    85
						print("   ...there are now "..tostring(#sendbuffer.external).." stanzas in the external send buffer");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    86
					end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    87
				end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    88
	session.send, session.send_to = send, send_to;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    89
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    90
	--	--	--
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    91
	print("Client connected");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    92
	conn = ssl.wrap(copas.wrap(conn), ssl_ctx);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    93
	
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    94
	do
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    95
		local succ, msg
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    96
		conn:settimeout(15)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    97
		while not succ do
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    98
			succ, msg = conn:dohandshake()
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
    99
			if not succ then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   100
				print("SSL: "..tostring(msg));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   101
				if msg == 'wantread' then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   102
					socket.select({conn}, nil)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   103
				elseif msg == 'wantwrite' then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   104
					socket.select(nil, {conn})
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   105
				else
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   106
					-- other error
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   107
				end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   108
			end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   109
		end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   110
	end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   111
	print("SSL handshake complete");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   112
	-- XML parser initialisation --
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   113
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   114
	local parser;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   115
	local stanza;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   116
	
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   117
	local stanza_dispatch = init_stanza_dispatcher(session);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   118
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   119
	local xml_handlers = {};
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   120
	
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   121
	do
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   122
		local ns_stack = { "" };
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   123
		local curr_ns = "";
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   124
		local curr_tag;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   125
		function xml_handlers:StartElement(name, attr)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   126
			curr_ns,name = name:match("^(.+):(%w+)$");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   127
			print("Tag received:", name, tostring(curr_ns));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   128
			if not stanza then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   129
				if session.notopen then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   130
					if name == "stream" then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   131
						session.host = attr.to or error("Client failed to specify destination hostname");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   132
			                        session.version = attr.version or 0;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   133
			                        session.streamid = m_random(1000000, 99999999);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   134
			                        print(session, session.host, "Client opened stream");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   135
			                        send("<?xml version='1.0'?>");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   136
			                        send(format("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='%s' from='%s' >", session.streamid, session.host));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   137
			                        --send("<stream:features>");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   138
			                        --send("<mechanism>PLAIN</mechanism>");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   139
        			                --send [[<register xmlns="http://jabber.org/features/iq-register"/> ]]
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   140
        			                --send("</stream:features>");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   141
						log("info", "core", "Stream opened successfully");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   142
						session.notopen = nil;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   143
						return;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   144
					end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   145
					error("Client failed to open stream successfully");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   146
				end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   147
				if name ~= "iq" and name ~= "presence" and name ~= "message" then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   148
					error("Client sent invalid top-level stanza");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   149
				end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   150
				stanza = st.stanza(name, { to = attr.to, type = attr.type, id = attr.id, xmlns = curr_ns });
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   151
				curr_tag = stanza;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   152
			else
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   153
				attr.xmlns = curr_ns;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   154
				stanza:tag(name, attr);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   155
			end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   156
		end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   157
		function xml_handlers:CharacterData(data)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   158
			if data:match("%S") then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   159
				stanza:text(data);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   160
			end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   161
		end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   162
		function xml_handlers:EndElement(name)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   163
			curr_ns,name = name:match("^(.+):(%w+)$");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   164
			--print("<"..name.."/>", tostring(stanza), tostring(#stanza.last_add < 1), tostring(stanza.last_add[#stanza.last_add].name));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   165
			if (not stanza) or #stanza.last_add < 0 or (#stanza.last_add > 0 and name ~= stanza.last_add[#stanza.last_add].name) then error("XML parse error in client stream"); end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   166
			-- Complete stanza
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   167
			print(name, tostring(#stanza.last_add));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   168
			if #stanza.last_add == 0 then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   169
				stanza_dispatch(stanza);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   170
				stanza = nil;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   171
			else
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   172
				stanza:up();
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   173
			end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   174
		end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   175
--[[		function xml_handlers:StartNamespaceDecl(namespace)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   176
			table.insert(ns_stack, namespace);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   177
			curr_ns = namespace;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   178
			log("debug", "parser", "Entering namespace "..tostring(curr_ns));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   179
		end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   180
		function xml_handlers:EndNamespaceDecl(namespace)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   181
			table.remove(ns_stack);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   182
			log("debug", "parser", "Leaving namespace "..tostring(curr_ns));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   183
			curr_ns = ns_stack[#ns_stack];
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   184
			log("debug", "parser", "Entering namespace "..tostring(curr_ns));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   185
		end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   186
]]
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   187
	end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   188
	parser = lxp.new(xml_handlers, ":");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   189
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   190
	--	--	--
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   191
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   192
	-- Main loop --
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   193
	print "Receiving..."
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   194
	reqdata = copas_receive(conn, 1);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   195
	print "Received"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   196
	while reqdata do
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   197
		parser:parse(reqdata);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   198
		if #sendbuffer.external > 0 then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   199
			-- Stanzas queued to go to other places, from us
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   200
			-- ie. other local users, or remote hosts that weren't connected before
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   201
			print(#sendbuffer.external.." stanzas queued for other recipients, sending now...");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   202
			for n, packet in pairs(sendbuffer.external) do
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   203
				if not hosts[packet.host] then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   204
					connect_host(packet.host);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   205
					t_insert(hosts[packet.host].sendbuffer, packet.data);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   206
				elseif hosts[packet.host].type == "local" then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   207
					print("   ...is to a local user")
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   208
					local destuser = hosts[packet.host].sessions[packet.node];
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   209
					if destuser and destuser.sessions then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   210
						if not destuser.sessions[packet.resource] then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   211
							local best_resource;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   212
							for resource, session in pairs(destuser.sessions) do
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   213
								if not best_session then best_session = session;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   214
								elseif session.priority >= best_session.priority and session.priority >= 0 then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   215
									best_session = session;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   216
								end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   217
							end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   218
							if not best_session then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   219
								offlinemessage.new(packet.node, packet.host, packet.data);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   220
							else
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   221
								print("resource '"..packet.resource.."' was not online, have chosen to send to '"..best_session.username.."@"..best_session.host.."/"..best_session.resource.."'");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   222
								packet.resource = best_session.resource;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   223
							end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   224
						end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   225
						if destuser.sessions[packet.resource] == session then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   226
							log("warn", "core", "Attempt to send stanza to self, dropping...");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   227
						else
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   228
							print("...sending...");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   229
							copas_send(destuser.sessions[packet.resource].conn, tostring(packet.data));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   230
							print("...sent")
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   231
						end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   232
					elseif packet.data.name == "message" then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   233
						print("   ...will be stored offline");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   234
						offlinemessage.new(packet.node, packet.host, packet.data);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   235
					elseif packet.data.name == "iq" then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   236
						print("   ...is an iq");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   237
						send(st.reply(packet.data)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   238
							:tag("error", { type = "cancel" })
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   239
								:tag("service-unavailable", { xmlns = "urn:ietf:params:xml:ns:xmpp-stanzas" }));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   240
					end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   241
					print("   ...removing from send buffer");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   242
					sendbuffer.external[n] = nil;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   243
				end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   244
			end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   245
		end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   246
		
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   247
		if #sendbuffer > 0 then 
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   248
			for n, data in ipairs(sendbuffer) do
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   249
				print "Sending..."
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   250
				copas_send(conn, data);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   251
				print "Sent"
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   252
				sendbuffer[n] = nil;
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   253
			end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   254
		end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   255
		print "Receiving..."
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   256
		repeat
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   257
			reqdata, sktmsg = copas_receive(conn, 1);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   258
			if sktmsg == 'wantread' then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   259
				print("Received... wantread");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   260
				--socket.select({conn}, nil)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   261
				--print("Socket ready now...");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   262
			elseif sktmsg then
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   263
				print("Received socket message:", sktmsg);
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   264
			end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   265
		until reqdata or sktmsg == "closed";
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   266
		print("Received", tostring(reqdata));
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   267
	end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   268
	log("info", "core", "Client disconnected, connection closed");
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   269
end
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   270
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   271
server = socket.bind("*", 5223)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   272
assert(server, "Failed to bind to socket")
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   273
copas.addserver(server, handler)
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   274
3e3171b59028 First commit, where do you want to go tomorrow?
matthew
parents:
diff changeset
   275
copas.loop();