Software /
code /
prosody
Changeset
1144:fbd65e966316
Merge with 0.4
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Wed, 13 May 2009 16:55:20 +0100 |
parents | 1142:0e02b3301e80 (diff) 1143:5bab3eb566ad (current diff) |
children | 1145:06051191913d |
files | core/stanza_router.lua |
diffstat | 16 files changed, 539 insertions(+), 47 deletions(-) [+] |
line wrap: on
line diff
--- a/core/componentmanager.lua Wed May 13 16:54:46 2009 +0100 +++ b/core/componentmanager.lua Wed May 13 16:55:20 2009 +0100 @@ -80,8 +80,7 @@ function create_component(host, component) -- TODO check for host well-formedness - local session = session or { type = "component", host = host, connected = true, s2sout = {} }; - return session; + return { type = "component", host = host, connected = true, s2sout = {} }; end function register_component(host, component, session)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/eventmanager2.lua Wed May 13 16:55:20 2009 +0100 @@ -0,0 +1,6 @@ + +local events = require "util.events".new(); + +module "eventmanager" + +return events;
--- a/core/stanza_router.lua Wed May 13 16:54:46 2009 +0100 +++ b/core/stanza_router.lua Wed May 13 16:55:20 2009 +0100 @@ -10,6 +10,8 @@ local log = require "util.logger".init("stanzarouter") +local hosts = _G.hosts; + local st = require "util.stanza"; local send_s2s = require "core.s2smanager".send_to_host; local user_exists = require "core.usermanager".user_exists; @@ -24,9 +26,9 @@ local modules_handle_stanza = require "core.modulemanager".handle_stanza; local component_handle_stanza = require "core.componentmanager".handle_stanza; -local handle_outbound_presence_subscriptions_and_probes = require "core.presencemanager".handle_outbound_presence_subscriptions_and_probes; -local handle_inbound_presence_subscriptions_and_probes = require "core.presencemanager".handle_inbound_presence_subscriptions_and_probes; -local handle_normal_presence = require "core.presencemanager".handle_normal_presence; +local handle_outbound_presence_subscriptions_and_probes = function()end;--require "core.presencemanager".handle_outbound_presence_subscriptions_and_probes; +local handle_inbound_presence_subscriptions_and_probes = function()end;--require "core.presencemanager".handle_inbound_presence_subscriptions_and_probes; +local handle_normal_presence = function()end;--require "core.presencemanager".handle_normal_presence; local format = string.format; local tostring = tostring; @@ -40,6 +42,7 @@ local jid_split = require "util.jid".split; local jid_prepped_split = require "util.jid".prepped_split; local print = print; +local fire_event = require "core.eventmanager2".fire_event; local function checked_error_reply(origin, stanza) if (stanza.attr.xmlns == "jabber:client" or stanza.attr.xmlns == "jabber:server") and stanza.attr.type ~= "error" and stanza.attr.type ~= "result" then origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); -- FIXME correct error? @@ -105,6 +108,8 @@ -- FIXME do stanzas not of jabber:client get handled by components? if (origin.type == "s2sin" or origin.type == "c2s" or origin.type == "component") and (not xmlns or xmlns == "jabber:server" or xmlns == "jabber:client") then + local event_data = {origin=origin, stanza=stanza}; + fire_event(tostring(host or origin.host).."/"..stanza.name, event_data); if origin.type == "s2sin" and not origin.dummy then local host_status = origin.hosts[from_host]; if not host_status or not host_status.authed then -- remote server trying to impersonate some other server? @@ -145,7 +150,7 @@ -- that is, they are handled by this server function core_handle_stanza(origin, stanza) -- Handlers - if modules_handle_stanza(select(2, jid_split(stanza.attr.to)) or origin.host, origin, stanza) then return; end + if modules_handle_stanza(select(2, jid_split(stanza.attr.to)) or origin.host or origin.to_host, origin, stanza) then return; end if origin.type == "c2s" or origin.type == "s2sin" then if origin.type == "c2s" then if stanza.name == "presence" and origin.roster then
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fallbacks/bit.lua Wed May 13 16:55:20 2009 +0100 @@ -0,0 +1,137 @@ + +local type = type; +local tonumber = tonumber; +local setmetatable = setmetatable; +local error = error; +local tostring = tostring; +local print = print; + +local xor_map = {[0]=0;[1]=1;[2]=2;[3]=3;[4]=4;[5]=5;[6]=6;[7]=7;[8]=8;[9]=9;[10]=10;[11]=11;[12]=12;[13]=13;[14]=14;[15]=15;[16]=1;[17]=0;[18]=3;[19]=2;[20]=5;[21]=4;[22]=7;[23]=6;[24]=9;[25]=8;[26]=11;[27]=10;[28]=13;[29]=12;[30]=15;[31]=14;[32]=2;[33]=3;[34]=0;[35]=1;[36]=6;[37]=7;[38]=4;[39]=5;[40]=10;[41]=11;[42]=8;[43]=9;[44]=14;[45]=15;[46]=12;[47]=13;[48]=3;[49]=2;[50]=1;[51]=0;[52]=7;[53]=6;[54]=5;[55]=4;[56]=11;[57]=10;[58]=9;[59]=8;[60]=15;[61]=14;[62]=13;[63]=12;[64]=4;[65]=5;[66]=6;[67]=7;[68]=0;[69]=1;[70]=2;[71]=3;[72]=12;[73]=13;[74]=14;[75]=15;[76]=8;[77]=9;[78]=10;[79]=11;[80]=5;[81]=4;[82]=7;[83]=6;[84]=1;[85]=0;[86]=3;[87]=2;[88]=13;[89]=12;[90]=15;[91]=14;[92]=9;[93]=8;[94]=11;[95]=10;[96]=6;[97]=7;[98]=4;[99]=5;[100]=2;[101]=3;[102]=0;[103]=1;[104]=14;[105]=15;[106]=12;[107]=13;[108]=10;[109]=11;[110]=8;[111]=9;[112]=7;[113]=6;[114]=5;[115]=4;[116]=3;[117]=2;[118]=1;[119]=0;[120]=15;[121]=14;[122]=13;[123]=12;[124]=11;[125]=10;[126]=9;[127]=8;[128]=8;[129]=9;[130]=10;[131]=11;[132]=12;[133]=13;[134]=14;[135]=15;[136]=0;[137]=1;[138]=2;[139]=3;[140]=4;[141]=5;[142]=6;[143]=7;[144]=9;[145]=8;[146]=11;[147]=10;[148]=13;[149]=12;[150]=15;[151]=14;[152]=1;[153]=0;[154]=3;[155]=2;[156]=5;[157]=4;[158]=7;[159]=6;[160]=10;[161]=11;[162]=8;[163]=9;[164]=14;[165]=15;[166]=12;[167]=13;[168]=2;[169]=3;[170]=0;[171]=1;[172]=6;[173]=7;[174]=4;[175]=5;[176]=11;[177]=10;[178]=9;[179]=8;[180]=15;[181]=14;[182]=13;[183]=12;[184]=3;[185]=2;[186]=1;[187]=0;[188]=7;[189]=6;[190]=5;[191]=4;[192]=12;[193]=13;[194]=14;[195]=15;[196]=8;[197]=9;[198]=10;[199]=11;[200]=4;[201]=5;[202]=6;[203]=7;[204]=0;[205]=1;[206]=2;[207]=3;[208]=13;[209]=12;[210]=15;[211]=14;[212]=9;[213]=8;[214]=11;[215]=10;[216]=5;[217]=4;[218]=7;[219]=6;[220]=1;[221]=0;[222]=3;[223]=2;[224]=14;[225]=15;[226]=12;[227]=13;[228]=10;[229]=11;[230]=8;[231]=9;[232]=6;[233]=7;[234]=4;[235]=5;[236]=2;[237]=3;[238]=0;[239]=1;[240]=15;[241]=14;[242]=13;[243]=12;[244]=11;[245]=10;[246]=9;[247]=8;[248]=7;[249]=6;[250]=5;[251]=4;[252]=3;[253]=2;[254]=1;[255]=0;}; +local or_map = {[0]=0;[1]=1;[2]=2;[3]=3;[4]=4;[5]=5;[6]=6;[7]=7;[8]=8;[9]=9;[10]=10;[11]=11;[12]=12;[13]=13;[14]=14;[15]=15;[16]=1;[17]=1;[18]=3;[19]=3;[20]=5;[21]=5;[22]=7;[23]=7;[24]=9;[25]=9;[26]=11;[27]=11;[28]=13;[29]=13;[30]=15;[31]=15;[32]=2;[33]=3;[34]=2;[35]=3;[36]=6;[37]=7;[38]=6;[39]=7;[40]=10;[41]=11;[42]=10;[43]=11;[44]=14;[45]=15;[46]=14;[47]=15;[48]=3;[49]=3;[50]=3;[51]=3;[52]=7;[53]=7;[54]=7;[55]=7;[56]=11;[57]=11;[58]=11;[59]=11;[60]=15;[61]=15;[62]=15;[63]=15;[64]=4;[65]=5;[66]=6;[67]=7;[68]=4;[69]=5;[70]=6;[71]=7;[72]=12;[73]=13;[74]=14;[75]=15;[76]=12;[77]=13;[78]=14;[79]=15;[80]=5;[81]=5;[82]=7;[83]=7;[84]=5;[85]=5;[86]=7;[87]=7;[88]=13;[89]=13;[90]=15;[91]=15;[92]=13;[93]=13;[94]=15;[95]=15;[96]=6;[97]=7;[98]=6;[99]=7;[100]=6;[101]=7;[102]=6;[103]=7;[104]=14;[105]=15;[106]=14;[107]=15;[108]=14;[109]=15;[110]=14;[111]=15;[112]=7;[113]=7;[114]=7;[115]=7;[116]=7;[117]=7;[118]=7;[119]=7;[120]=15;[121]=15;[122]=15;[123]=15;[124]=15;[125]=15;[126]=15;[127]=15;[128]=8;[129]=9;[130]=10;[131]=11;[132]=12;[133]=13;[134]=14;[135]=15;[136]=8;[137]=9;[138]=10;[139]=11;[140]=12;[141]=13;[142]=14;[143]=15;[144]=9;[145]=9;[146]=11;[147]=11;[148]=13;[149]=13;[150]=15;[151]=15;[152]=9;[153]=9;[154]=11;[155]=11;[156]=13;[157]=13;[158]=15;[159]=15;[160]=10;[161]=11;[162]=10;[163]=11;[164]=14;[165]=15;[166]=14;[167]=15;[168]=10;[169]=11;[170]=10;[171]=11;[172]=14;[173]=15;[174]=14;[175]=15;[176]=11;[177]=11;[178]=11;[179]=11;[180]=15;[181]=15;[182]=15;[183]=15;[184]=11;[185]=11;[186]=11;[187]=11;[188]=15;[189]=15;[190]=15;[191]=15;[192]=12;[193]=13;[194]=14;[195]=15;[196]=12;[197]=13;[198]=14;[199]=15;[200]=12;[201]=13;[202]=14;[203]=15;[204]=12;[205]=13;[206]=14;[207]=15;[208]=13;[209]=13;[210]=15;[211]=15;[212]=13;[213]=13;[214]=15;[215]=15;[216]=13;[217]=13;[218]=15;[219]=15;[220]=13;[221]=13;[222]=15;[223]=15;[224]=14;[225]=15;[226]=14;[227]=15;[228]=14;[229]=15;[230]=14;[231]=15;[232]=14;[233]=15;[234]=14;[235]=15;[236]=14;[237]=15;[238]=14;[239]=15;[240]=15;[241]=15;[242]=15;[243]=15;[244]=15;[245]=15;[246]=15;[247]=15;[248]=15;[249]=15;[250]=15;[251]=15;[252]=15;[253]=15;[254]=15;[255]=15;}; +local and_map = {[0]=0;[1]=0;[2]=0;[3]=0;[4]=0;[5]=0;[6]=0;[7]=0;[8]=0;[9]=0;[10]=0;[11]=0;[12]=0;[13]=0;[14]=0;[15]=0;[16]=0;[17]=1;[18]=0;[19]=1;[20]=0;[21]=1;[22]=0;[23]=1;[24]=0;[25]=1;[26]=0;[27]=1;[28]=0;[29]=1;[30]=0;[31]=1;[32]=0;[33]=0;[34]=2;[35]=2;[36]=0;[37]=0;[38]=2;[39]=2;[40]=0;[41]=0;[42]=2;[43]=2;[44]=0;[45]=0;[46]=2;[47]=2;[48]=0;[49]=1;[50]=2;[51]=3;[52]=0;[53]=1;[54]=2;[55]=3;[56]=0;[57]=1;[58]=2;[59]=3;[60]=0;[61]=1;[62]=2;[63]=3;[64]=0;[65]=0;[66]=0;[67]=0;[68]=4;[69]=4;[70]=4;[71]=4;[72]=0;[73]=0;[74]=0;[75]=0;[76]=4;[77]=4;[78]=4;[79]=4;[80]=0;[81]=1;[82]=0;[83]=1;[84]=4;[85]=5;[86]=4;[87]=5;[88]=0;[89]=1;[90]=0;[91]=1;[92]=4;[93]=5;[94]=4;[95]=5;[96]=0;[97]=0;[98]=2;[99]=2;[100]=4;[101]=4;[102]=6;[103]=6;[104]=0;[105]=0;[106]=2;[107]=2;[108]=4;[109]=4;[110]=6;[111]=6;[112]=0;[113]=1;[114]=2;[115]=3;[116]=4;[117]=5;[118]=6;[119]=7;[120]=0;[121]=1;[122]=2;[123]=3;[124]=4;[125]=5;[126]=6;[127]=7;[128]=0;[129]=0;[130]=0;[131]=0;[132]=0;[133]=0;[134]=0;[135]=0;[136]=8;[137]=8;[138]=8;[139]=8;[140]=8;[141]=8;[142]=8;[143]=8;[144]=0;[145]=1;[146]=0;[147]=1;[148]=0;[149]=1;[150]=0;[151]=1;[152]=8;[153]=9;[154]=8;[155]=9;[156]=8;[157]=9;[158]=8;[159]=9;[160]=0;[161]=0;[162]=2;[163]=2;[164]=0;[165]=0;[166]=2;[167]=2;[168]=8;[169]=8;[170]=10;[171]=10;[172]=8;[173]=8;[174]=10;[175]=10;[176]=0;[177]=1;[178]=2;[179]=3;[180]=0;[181]=1;[182]=2;[183]=3;[184]=8;[185]=9;[186]=10;[187]=11;[188]=8;[189]=9;[190]=10;[191]=11;[192]=0;[193]=0;[194]=0;[195]=0;[196]=4;[197]=4;[198]=4;[199]=4;[200]=8;[201]=8;[202]=8;[203]=8;[204]=12;[205]=12;[206]=12;[207]=12;[208]=0;[209]=1;[210]=0;[211]=1;[212]=4;[213]=5;[214]=4;[215]=5;[216]=8;[217]=9;[218]=8;[219]=9;[220]=12;[221]=13;[222]=12;[223]=13;[224]=0;[225]=0;[226]=2;[227]=2;[228]=4;[229]=4;[230]=6;[231]=6;[232]=8;[233]=8;[234]=10;[235]=10;[236]=12;[237]=12;[238]=14;[239]=14;[240]=0;[241]=1;[242]=2;[243]=3;[244]=4;[245]=5;[246]=6;[247]=7;[248]=8;[249]=9;[250]=10;[251]=11;[252]=12;[253]=13;[254]=14;[255]=15;} + +local not_map = {[0]=15;[1]=14;[2]=13;[3]=12;[4]=11;[5]=10;[6]=9;[7]=8;[8]=7;[9]=6;[10]=5;[11]=4;[12]=3;[13]=2;[14]=1;[15]=0;}; +local rshift1_map = {[0]=0;[1]=0;[2]=1;[3]=1;[4]=2;[5]=2;[6]=3;[7]=3;[8]=4;[9]=4;[10]=5;[11]=5;[12]=6;[13]=6;[14]=7;[15]=7;}; +local rshift1carry_map = {[0]=0;[1]=8;[2]=0;[3]=8;[4]=0;[5]=8;[6]=0;[7]=8;[8]=0;[9]=8;[10]=0;[11]=8;[12]=0;[13]=8;[14]=0;[15]=8;}; +local lshift1_map = {[0]=0;[1]=2;[2]=4;[3]=6;[4]=8;[5]=10;[6]=12;[7]=14;[8]=0;[9]=2;[10]=4;[11]=6;[12]=8;[13]=10;[14]=12;[15]=14;}; +local lshift1carry_map = {[0]=0;[1]=0;[2]=0;[3]=0;[4]=0;[5]=0;[6]=0;[7]=0;[8]=1;[9]=1;[10]=1;[11]=1;[12]=1;[13]=1;[14]=1;[15]=1;}; +local arshift1carry_map = {[0]=0;[1]=0;[2]=0;[3]=0;[4]=0;[5]=0;[6]=0;[7]=0;[8]=8;[9]=8;[10]=8;[11]=8;[12]=8;[13]=8;[14]=8;[15]=8;}; + +module "bit" + +local bit_mt = {__tostring = function(t) return ("%x%x%x%x%x%x%x%x"):format(t[1],t[2],t[3],t[4],t[5],t[6],t[7],t[8]); end}; +local function do_bop(a, b, op) + return setmetatable({ + op[a[1]*16+b[1]]; + op[a[2]*16+b[2]]; + op[a[3]*16+b[3]]; + op[a[4]*16+b[4]]; + op[a[5]*16+b[5]]; + op[a[6]*16+b[6]]; + op[a[7]*16+b[7]]; + op[a[8]*16+b[8]]; + }, bit_mt); +end +local function do_uop(a, op) + return setmetatable({ + op[a[1]]; + op[a[2]]; + op[a[3]]; + op[a[4]]; + op[a[5]]; + op[a[6]]; + op[a[7]]; + op[a[8]]; + }, bit_mt); +end + +function bxor(a, b) return do_bop(a, b, xor_map); end +function bor(a, b) return do_bop(a, b, or_map); end +function band(a, b) return do_bop(a, b, and_map); end + +function bnot(a) return do_uop(a, not_map); end +local function _rshift1(t) + local carry = 0; + for i=1,8 do + local t_i = rshift1_map[t[i]] + carry; + carry = rshift1carry_map[t[i]]; + t[i] = t_i; + end +end +function rshift(a, i) + local t = {a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]}; + for n = 1,i do _rshift1(t); end + return setmetatable(t, bit_mt); +end +local function _arshift1(t) + local carry = arshift1carry_map[t[1]]; + for i=1,8 do + local t_i = rshift1_map[t[i]] + carry; + carry = rshift1carry_map[t[i]]; + t[i] = t_i; + end +end +function arshift(a, i) + local t = {a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]}; + for n = 1,i do _arshift1(t); end + return setmetatable(t, bit_mt); +end +local function _lshift1(t) + local carry = 0; + for i=8,1,-1 do + local t_i = lshift1_map[t[i]] + carry; + carry = lshift1carry_map[t[i]]; + t[i] = t_i; + end +end +function lshift(a, i) + local t = {a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]}; + for n = 1,i do _lshift1(t); end + return setmetatable(t, bit_mt); +end + +local function _cast(a) + if type(a) == "number" then a = ("%x"):format(a); + elseif type(a) == "table" then return a; + elseif type(a) ~= "string" then error("string expected, got "..type(a), 2); end + local t = {0,0,0,0,0,0,0,0}; + a = "00000000"..a; + a = a:sub(-8); + for i = 1,8 do + t[i] = tonumber(a:sub(i,i), 16) or error("Number format error", 2); + end + return setmetatable(t, bit_mt); +end + +local function wrap1(f) + return function(a, ...) + if type(a) ~= "table" then a = _cast(a); end + a = f(a, ...); + a = tonumber(tostring(a), 16); + if a > 0x7fffffff then a = a - 1 - 0xffffffff; end + return a; + end; +end +local function wrap2(f) + return function(a, b, ...) + if type(a) ~= "table" then a = _cast(a); end + if type(b) ~= "table" then b = _cast(b); end + a = f(a, b, ...); + a = tonumber(tostring(a), 16); + if a > 0x7fffffff then a = a - 1 - 0xffffffff; end + return a; + end; +end + +bxor = wrap2(bxor); +bor = wrap2(bor); +band = wrap2(band); +bnot = wrap1(bnot); +lshift = wrap1(lshift); +rshift = wrap1(rshift); +arshift = wrap1(arshift); +cast = wrap1(_cast); + +bits = 32; + +return _M;
--- a/net/http.lua Wed May 13 16:54:46 2009 +0100 +++ b/net/http.lua Wed May 13 16:55:20 2009 +0100 @@ -9,8 +9,8 @@ local listener = connlisteners_get("httpclient") or error("No httpclient listener!"); local t_insert, t_concat = table.insert, table.concat; -local tonumber, tostring, pairs, xpcall, select, debug_traceback = - tonumber, tostring, pairs, xpcall, select, debug.traceback; +local tonumber, tostring, pairs, xpcall, select, debug_traceback, char = + tonumber, tostring, pairs, xpcall, select, debug.traceback, string.char; local log = require "util.logger".init("http"); local print = function () end
--- a/net/server.lua Wed May 13 16:54:46 2009 +0100 +++ b/net/server.lua Wed May 13 16:55:20 2009 +0100 @@ -791,7 +791,7 @@ end local addclient = function( address, port, listeners, pattern, sslctx, startssl ) - local client, err = socket.tcp( ) + local client, err = luasocket.tcp( ) if err then return nil, err end @@ -800,7 +800,7 @@ if err then -- try again local handler = wrapclient( client, address, port, listeners ) else - wrapconnection( server, listeners, socket, address, port, "clientport", pattern, sslctx, startssl ) + wrapconnection( nil, listeners, client, address, port, "clientport", pattern, sslctx, startssl ) end end
--- a/net/xmppclient_listener.lua Wed May 13 16:54:46 2009 +0100 +++ b/net/xmppclient_listener.lua Wed May 13 16:55:20 2009 +0100 @@ -9,6 +9,7 @@ local logger = require "logger"; +local log = logger.init("xmppclient_listener"); local lxp = require "lxp" local init_xmlhandlers = require "core.xmlhandlers" local sm_new_session = require "core.sessionmanager".new_session; @@ -20,10 +21,11 @@ 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 local m_random = math.random; local format = string.format; -local sm_new_session, sm_destroy_session = sessionmanager.new_session, sessionmanager.destroy_session; --import("core.sessionmanager", "new_session", "destroy_session"); +local sessionmanager = require "core.sessionmanager"; +local sm_new_session, sm_destroy_session = sessionmanager.new_session, sessionmanager.destroy_session; local sm_streamopened = sessionmanager.streamopened; local sm_streamclosed = sessionmanager.streamclosed; -local st = stanza; +local st = require "util.stanza"; local stream_callbacks = { stream_tag = "http://etherx.jabber.org/streams|stream", default_ns = "jabber:client",
--- a/net/xmppserver_listener.lua Wed May 13 16:54:46 2009 +0100 +++ b/net/xmppserver_listener.lua Wed May 13 16:55:20 2009 +0100 @@ -9,9 +9,9 @@ local logger = require "logger"; +local log = logger.init("xmppserver_listener"); local lxp = require "lxp" local init_xmlhandlers = require "core.xmlhandlers" -local sm_new_session = require "core.sessionmanager".new_session; local s2s_new_incoming = require "core.s2smanager".new_incoming; local s2s_streamopened = require "core.s2smanager".streamopened; local s2s_streamclosed = require "core.s2smanager".streamclosed; @@ -42,8 +42,9 @@ 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 local m_random = math.random; local format = string.format; -local sm_new_session, sm_destroy_session = sessionmanager.new_session, sessionmanager.destroy_session; --import("core.sessionmanager", "new_session", "destroy_session"); -local st = stanza; +local sessionmanager = require "core.sessionmanager"; +local sm_new_session, sm_destroy_session = sessionmanager.new_session, sessionmanager.destroy_session; +local st = require "util.stanza"; local sessions = {}; local xmppserver = { default_port = 5269, default_mode = "*a" };
--- a/plugins/mod_bosh.lua Wed May 13 16:54:46 2009 +0100 +++ b/plugins/mod_bosh.lua Wed May 13 16:55:20 2009 +0100 @@ -1,6 +1,7 @@ module.host = "*" -- Global module +local hosts = _G.hosts; local lxp = require "lxp"; local init_xmlhandlers = require "core.xmlhandlers" local server = require "net.server";
--- a/plugins/mod_muc.lua Wed May 13 16:54:46 2009 +0100 +++ b/plugins/mod_muc.lua Wed May 13 16:55:20 2009 +0100 @@ -205,6 +205,34 @@ end end end +function send_history(room, to) + local history = rooms_info:get(room, 'history'); -- send discussion history + if history then + for _, msg in ipairs(history) do + msg = st.deserialize(msg); + msg.attr.to=to; + core_route_stanza(component, msg); + end + end + if rooms_info:get(room, 'subject') then + core_route_stanza(component, st.message({type='groupchat', from=room, to=to}):tag("subject"):text(rooms_info:get(room, 'subject'))); + end +end +function send_occupant_list(room, to) + local r = rooms:get(room); + if r then + local current_nick = jid_nick:get(to, room); + for occupant, o_data in pairs(r) do + if occupant ~= current_nick then + local pres = get_filtered_presence(o_data.sessions[o_data.jid]); + pres.attr.to, pres.attr.from = to, occupant; + pres:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) + :tag("item", {affiliation=o_data.affiliation, role=o_data.role}):up(); + core_route_stanza(component, pres); + end + end + end +end function handle_to_occupant(origin, stanza) -- PM, vCards, etc local from, to = stanza.attr.from, stanza.attr.to; @@ -232,7 +260,7 @@ end elseif not type then -- available if current_nick then - if #pr == #stanza or current_nick ~= to then + --if #pr == #stanza or current_nick ~= to then -- commented because google keeps resending directed presence if current_nick == to then -- simple presence log("debug", "%s broadcasted presence", current_nick); rooms:get(room, current_nick).sessions[from] = pr; @@ -259,11 +287,11 @@ end end end - else -- possible rejoin - log("debug", "%s had connection replaced", current_nick); - handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('Replaced by new connection'):up()); -- send unavailable - handle_to_occupant(origin, stanza); -- resend available - end + --else -- possible rejoin + -- log("debug", "%s had connection replaced", current_nick); + -- handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('Replaced by new connection'):up()); -- send unavailable + -- handle_to_occupant(origin, stanza); -- resend available + --end else -- enter room local new_nick = to; if rooms:get(room, to) then @@ -284,31 +312,10 @@ end rooms:set(room, to, data); jid_nick:set(from, room, to); - local r = rooms:get(room); - if r then - for occupant, o_data in pairs(r) do - if occupant ~= to then - local pres = get_filtered_presence(o_data.sessions[o_data.jid]); - pres.attr.to, pres.attr.from = from, occupant; - pres:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) - :tag("item", {affiliation=o_data.affiliation, role=o_data.role}):up(); - core_route_stanza(component, pres); - end - end - end + send_occupant_list(room, from); pr.attr.from = to; broadcast_presence_stanza(room, pr); - local history = rooms_info:get(room, 'history'); -- send discussion history - if history then - for _, msg in ipairs(history) do - msg = st.deserialize(msg); - msg.attr.to=from; - core_route_stanza(component, msg); - end - end - if rooms_info:get(room, 'subject') then - core_route_stanza(component, st.message({type='groupchat', from=room, to=from}):tag("subject"):text(rooms_info:get(room, 'subject'))); - end + send_history(room, from); end end elseif type ~= 'result' then -- bad type
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/mod_pep.lua Wed May 13 16:55:20 2009 +0100 @@ -0,0 +1,48 @@ + +local jid_bare = require "util.jid".bare; +local jid_split = require "util.jid".split; +local st = require "util.stanza"; +local hosts = hosts; +local user_exists = require "core.usermanager".user_exists; +local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed; +local pairs, ipairs = pairs, ipairs; + +local function publish(session, node, item) + local stanza = st.message({from=session.full_jid, type='headline'}) + :tag('event', {xmlns='http://jabber.org/protocol/pubsub#event'}) + :tag('items', {node=node}) + :add_child(item) + :up() + :up(); + + -- broadcast to resources + stanza.attr.to = session.username..'@'..session.host; + core_route_stanza(session, stanza); + + -- broadcast to contacts + for jid, item in pairs(session.roster) do + if jid and jid ~= "pending" and (item.subscription == 'from' or item.subscription == 'both') then + stanza.attr.to = jid; + core_route_stanza(session, stanza); + end + end +end + +module:add_iq_handler("c2s", "http://jabber.org/protocol/pubsub", function (session, stanza) + if stanza.attr.type == 'set' and (not stanza.attr.to or jid_bare(stanza.attr.from) == stanza.attr.to) then + local payload = stanza.tags[1]; + if payload.name == 'pubsub' then + payload = payload.tags[1]; + if payload and payload.name == 'publish' and payload.attr.node then + local node = payload.attr.node; + payload = payload.tags[1]; + if payload then + publish(session, node, payload); + return true; + end -- TODO else error + end -- TODO else error + end + end + origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); +end); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/mod_presence.lua Wed May 13 16:55:20 2009 +0100 @@ -0,0 +1,279 @@ +-- Prosody IM v0.4 +-- Copyright (C) 2008-2009 Matthew Wild +-- Copyright (C) 2008-2009 Waqas Hussain +-- +-- This project is MIT/X11 licensed. Please see the +-- COPYING file in the source package for more information. +-- + + + +local log = require "util.logger".init("mod_presence") + +local require = require; +local pairs, ipairs = pairs, ipairs; +local t_concat = table.concat; +local s_find = string.find; +local tonumber = tonumber; + +local st = require "util.stanza"; +local jid_split = require "util.jid".split; +local jid_bare = require "util.jid".bare; +local hosts = hosts; + +local rostermanager = require "core.rostermanager"; +local sessionmanager = require "core.sessionmanager"; +local offlinemanager = require "core.offlinemanager"; + +local _core_route_stanza = core_route_stanza; +local core_route_stanza; +function core_route_stanza(origin, stanza) + if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then + local node, host = jid_split(stanza.attr.to); + host = hosts[host]; + if host and host.type == "local" then + handle_inbound_presence_subscriptions_and_probes(origin, stanza, jid_bare(stanza.attr.from), jid_bare(stanza.attr.to), core_route_stanza); + return; + end + end + _core_route_stanza(origin, stanza); +end + +function handle_presence(origin, stanza, from_bare, to_bare, core_route_stanza, inbound) + local type = stanza.attr.type; + if type and type ~= "unavailable" and type ~= "error" then + if inbound then + handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza); + else + handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza); + end + elseif not inbound and not stanza.attr.to then + handle_normal_presence(origin, stanza, core_route_stanza); + else + core_route_stanza(origin, stanza); + end +end + +function handle_normal_presence(origin, stanza, core_route_stanza) + if origin.roster then + for jid in pairs(origin.roster) do -- broadcast to all interested contacts + local subscription = origin.roster[jid].subscription; + if subscription == "both" or subscription == "from" then + stanza.attr.to = jid; + core_route_stanza(origin, stanza); + end + end + local node, host = jid_split(stanza.attr.from); + for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast to all resources + if res ~= origin and res.presence then -- to resource + stanza.attr.to = res.full_jid; + core_route_stanza(origin, stanza); + end + end + if stanza.attr.type == nil and not origin.presence then -- initial presence + local probe = st.presence({from = origin.full_jid, type = "probe"}); + for jid in pairs(origin.roster) do -- probe all contacts we are subscribed to + local subscription = origin.roster[jid].subscription; + if subscription == "both" or subscription == "to" then + probe.attr.to = jid; + core_route_stanza(origin, probe); + end + end + for _, res in pairs(hosts[host].sessions[node].sessions) do -- broadcast from all available resources + if res ~= origin and res.presence then + res.presence.attr.to = origin.full_jid; + core_route_stanza(res, res.presence); + res.presence.attr.to = nil; + end + end + if origin.roster.pending then -- resend incoming subscription requests + for jid in pairs(origin.roster.pending) do + origin.send(st.presence({type="subscribe", from=jid})); -- TODO add to attribute? Use original? + end + end + local request = st.presence({type="subscribe", from=origin.username.."@"..origin.host}); + for jid, item in pairs(origin.roster) do -- resend outgoing subscription requests + if item.ask then + request.attr.to = jid; + core_route_stanza(origin, request); + end + end + local offline = offlinemanager.load(node, host); + if offline then + for _, msg in ipairs(offline) do + origin.send(msg); -- FIXME do we need to modify to/from in any way? + end + offlinemanager.deleteAll(node, host); + end + end + origin.priority = 0; + if stanza.attr.type == "unavailable" then + origin.presence = nil; + if origin.directed then + local old_from = stanza.attr.from; + stanza.attr.from = origin.full_jid; + for jid in pairs(origin.directed) do + stanza.attr.to = jid; + core_route_stanza(origin, stanza); + end + stanza.attr.from = old_from; + origin.directed = nil; + end + else + origin.presence = stanza; + local priority = stanza:child_with_name("priority"); + if priority and #priority > 0 then + priority = t_concat(priority); + if s_find(priority, "^[+-]?[0-9]+$") then + priority = tonumber(priority); + if priority < -128 then priority = -128 end + if priority > 127 then priority = 127 end + origin.priority = priority; + end + end + end + stanza.attr.to = nil; -- reset it + else + log("error", "presence recieved from client with no roster"); + end +end + +function send_presence_of_available_resources(user, host, jid, recipient_session, core_route_stanza) + local h = hosts[host]; + local count = 0; + if h and h.type == "local" then + local u = h.sessions[user]; + if u then + for k, session in pairs(u.sessions) do + local pres = session.presence; + if pres then + pres.attr.to = jid; + pres.attr.from = session.full_jid; + core_route_stanza(session, pres); + pres.attr.to = nil; + pres.attr.from = nil; + count = count + 1; + end + end + end + end + log("info", "broadcasted presence of "..count.." resources from "..user.."@"..host.." to "..jid); + return count; +end + +function handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza) + local node, host = jid_split(from_bare); + local st_from, st_to = stanza.attr.from, stanza.attr.to; + stanza.attr.from, stanza.attr.to = from_bare, to_bare; + log("debug", "outbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare); + if stanza.attr.type == "subscribe" then + -- 1. route stanza + -- 2. roster push (subscription = none, ask = subscribe) + if rostermanager.set_contact_pending_out(node, host, to_bare) then + rostermanager.roster_push(node, host, to_bare); + end -- else file error + core_route_stanza(origin, stanza); + elseif stanza.attr.type == "unsubscribe" then + -- 1. route stanza + -- 2. roster push (subscription = none or from) + if rostermanager.unsubscribe(node, host, to_bare) then + rostermanager.roster_push(node, host, to_bare); -- FIXME do roster push when roster has in fact not changed? + end -- else file error + core_route_stanza(origin, stanza); + elseif stanza.attr.type == "subscribed" then + -- 1. route stanza + -- 2. roster_push () + -- 3. send_presence_of_available_resources + if rostermanager.subscribed(node, host, to_bare) then + rostermanager.roster_push(node, host, to_bare); + end + core_route_stanza(origin, stanza); + send_presence_of_available_resources(node, host, to_bare, origin, core_route_stanza); + elseif stanza.attr.type == "unsubscribed" then + -- 1. route stanza + -- 2. roster push (subscription = none or to) + if rostermanager.unsubscribed(node, host, to_bare) then + rostermanager.roster_push(node, host, to_bare); + end + core_route_stanza(origin, stanza); + end + stanza.attr.from, stanza.attr.to = st_from, st_to; +end + +function handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza) + local node, host = jid_split(to_bare); + local st_from, st_to = stanza.attr.from, stanza.attr.to; + stanza.attr.from, stanza.attr.to = from_bare, to_bare; + log("debug", "inbound presence "..stanza.attr.type.." from "..from_bare.." for "..to_bare); + if stanza.attr.type == "probe" then + if rostermanager.is_contact_subscribed(node, host, from_bare) then + if 0 == send_presence_of_available_resources(node, host, from_bare, origin, core_route_stanza) then + -- TODO send last recieved unavailable presence (or we MAY do nothing, which is fine too) + end + else + core_route_stanza(origin, st.presence({from=to_bare, to=from_bare, type="unsubscribed"})); + end + elseif stanza.attr.type == "subscribe" then + if rostermanager.is_contact_subscribed(node, host, from_bare) then + core_route_stanza(origin, st.presence({from=to_bare, to=from_bare, type="subscribed"})); -- already subscribed + -- Sending presence is not clearly stated in the RFC, but it seems appropriate + if 0 == send_presence_of_available_resources(node, host, from_bare, origin, core_route_stanza) then + -- TODO send last recieved unavailable presence (or we MAY do nothing, which is fine too) + end + else + if not rostermanager.is_contact_pending_in(node, host, from_bare) then + if rostermanager.set_contact_pending_in(node, host, from_bare) then + sessionmanager.send_to_available_resources(node, host, stanza); + end -- TODO else return error, unable to save + end + end + elseif stanza.attr.type == "unsubscribe" then + if rostermanager.process_inbound_unsubscribe(node, host, from_bare) then + rostermanager.roster_push(node, host, from_bare); + end + elseif stanza.attr.type == "subscribed" then + if rostermanager.process_inbound_subscription_approval(node, host, from_bare) then + rostermanager.roster_push(node, host, from_bare); + end + elseif stanza.attr.type == "unsubscribed" then + if rostermanager.process_inbound_subscription_cancellation(node, host, from_bare) then + rostermanager.roster_push(node, host, from_bare); + end + end -- discard any other type + stanza.attr.from, stanza.attr.to = st_from, st_to; +end + +local function presence_handler(data) + local origin, stanza = data.origin, data.stanza; + local to = stanza.attr.to; + local node, host = jid_split(to); + local to_bare = jid_bare(to); + local from_bare = jid_bare(stanza.attr.from); + if origin.type == "c2s" then + if to ~= nil and not(origin.roster[to_bare] and (origin.roster[to_bare].subscription == "both" or origin.roster[to_bare].subscription == "from")) then -- directed presence + origin.directed = origin.directed or {}; + origin.directed[to] = true; + end + if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then + handle_outbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza); + elseif not to then + handle_normal_presence(origin, stanza, core_route_stanza); + else + core_route_stanza(origin, stanza); + end + elseif (origin.type == "s2sin" or origin.type == "component") and hosts[host] then + if stanza.attr.type ~= nil and stanza.attr.type ~= "unavailable" and stanza.attr.type ~= "error" then + handle_inbound_presence_subscriptions_and_probes(origin, stanza, from_bare, to_bare, core_route_stanza); + else + core_route_stanza(origin, stanza); + end + end +end + +local add_handler = require "core.eventmanager2".add_handler; +local remove_handler = require "core.eventmanager2".remove_handler; + +add_handler(module:get_host().."/presence", presence_handler); +module.unload = function() + remove_handler(module:get_host().."/presence", presence_handler); +end
--- a/plugins/mod_roster.lua Wed May 13 16:54:46 2009 +0100 +++ b/plugins/mod_roster.lua Wed May 13 16:55:20 2009 +0100 @@ -23,6 +23,14 @@ module:add_feature("jabber:iq:roster"); +local rosterver_stream_feature = st.stanza("ver", {xmlns="urn:xmpp:features:rosterver"}):tag("optional"):up(); +module:add_event_hook("stream-features", + function (session, features) + if session.username then + features:add_child(rosterver_stream_feature); + end + end); + module:add_iq_handler("c2s", "jabber:iq:roster", function (session, stanza) if stanza.tags[1].name == "query" then
--- a/prosody.cfg.lua.dist Wed May 13 16:54:46 2009 +0100 +++ b/prosody.cfg.lua.dist Wed May 13 16:55:20 2009 +0100 @@ -38,6 +38,7 @@ modules_enabled = { -- Generally required "roster"; -- Allow users to have a roster. Recommended ;) + "presence"; -- See and broadcast status changes to/from contacts "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. "tls"; -- Add support for secure TLS on c2s/s2s connections "dialback"; -- s2s dialback support
--- a/util/sasl.lua Wed May 13 16:54:46 2009 +0100 +++ b/util/sasl.lua Wed May 13 16:55:20 2009 +0100 @@ -26,8 +26,6 @@ local type = type local error = error local print = print -local idna_ascii = require "util.encodings".idna.to_ascii -local idna_unicode = require "util.encodings".idna.to_unicode module "sasl"