From 264ed76508ef6a0bf83f28f55e53ff9ae906b7cd Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Tue, 17 Feb 2009 02:48:06 +0500 Subject: MUC: Fixed: Presence for user joining the roomi was sent twice to the user --- plugins/mod_muc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index 9a559f2d..a306c699 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -298,7 +298,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc local r = rooms:get(room); if r then for occupant, o_data in pairs(r) do - if occupant ~= from then + if occupant ~= to then local pres = get_filtered_presence(o_data.sessions[o_data.jid]); pres.attr.to, pres.attr.from = from, occupant; pres -- cgit v1.2.3 From b964df3b328d3b83dc5e466dcb666c40198a19cc Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Wed, 18 Feb 2009 23:30:33 +0500 Subject: MUC: Various fixes --- plugins/mod_muc.lua | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index a306c699..7c18b9c4 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -116,7 +116,7 @@ function set_subject(current_nick, room, subject) if subject == "" then subject = nil; end rooms_info:set(room, 'subject', subject); save_room(); - local msg = st.message({type='groupchat', from=from}) + local msg = st.message({type='groupchat', from=current_nick}) :tag('subject'):text(subject):up(); broadcast_message_stanza(room, msg, false); --broadcast_message(current_nick, room, subject or "", nil); @@ -231,30 +231,35 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc pr.attr.from = to; if type == "error" then -- error, kick em out! if current_nick then - local data = rooms:get(room, to); + local data = rooms:get(room, current_nick); data.role = 'none'; local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error presence'):up() - :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) - :tag("item", {affiliation=data.affiliation, role=data.role}):up(); + --:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) + --:tag("item", {affiliation=data.affiliation, role=data.role}):up(); broadcast_presence_stanza(room, pr); - --broadcast_presence('unavailable', to, room); -- TODO also add This participant is kicked from the room because he sent an error presence: badformed error stanza - rooms:remove(room, to); + --broadcast_presence('unavailable', current_nick, room); -- TODO also add This participant is kicked from the room because he sent an error presence: badformed error stanza + rooms:remove(room, current_nick); jid_nick:remove(from, room); end elseif type == "unavailable" then -- unavailable if current_nick then - local data = rooms:get(room, to); + local data = rooms:get(room, current_nick); data.role = 'none'; broadcast_presence_stanza(room, pr); - --broadcast_presence('unavailable', to, room); - rooms:remove(room, to); + --broadcast_presence('unavailable', current_nick, room); + rooms:remove(room, current_nick); jid_nick:remove(from, room); end elseif not type then -- available if current_nick then if current_nick == to then -- simple presence - broadcast_presence_stanza(room, pr); - -- FIXME check if something was filtered. if it was, then user may be rejoining + if #pr == #stanza then + broadcast_presence_stanza(room, pr); + else -- possible rejoin + local pr_ = st.presence({type='unavailable', from=from, to=current_nick}):tag('status'):text('Replaced by new connection'); + handle_to_occupant(origin, pr_); -- send unavailable + handle_to_occupant(origin, pr); -- resend available + end else -- change nick if rooms:get(room, to) then origin.send(st.error_reply(stanza, "cancel", "conflict")); -- cgit v1.2.3 From 81287473fc3b61e9ba74216e84ddf1c6d8215b31 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 18 Feb 2009 19:23:29 +0000 Subject: net.server: Fix some more potential nil handler accesses --- net/server.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/server.lua b/net/server.lua index a5c8e24c..cea2ada3 100644 --- a/net/server.lua +++ b/net/server.lua @@ -369,7 +369,9 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport end bufferqueuelen = bufferqueuelen + 1 bufferqueue[ bufferqueuelen ] = data - _writetimes[ handler ] = _writetimes[ handler ] or _currenttime + if handler then + _writetimes[ handler ] = _writetimes[ handler ] or _currenttime + end return true end handler.write = write @@ -470,7 +472,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport out_put( "server.lua: client ", ip, ":", clientport, " error: ", err ) fatalerror = true disconnect( handler, err ) - handler.close( ) + _ = handler and handler.close( ) return false end end -- cgit v1.2.3 From 8433494e21252423c4395f7e920c16923e44ce0a Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Wed, 18 Feb 2009 19:33:57 +0000 Subject: mod_bosh: Possible fix for invalid key to next crash --- plugins/mod_bosh.lua | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/plugins/mod_bosh.lua b/plugins/mod_bosh.lua index df89f88e..4d0f5cd9 100644 --- a/plugins/mod_bosh.lua +++ b/plugins/mod_bosh.lua @@ -32,6 +32,19 @@ local inactive_sessions = {}; -- Sessions which have no open requests local waiting_requests = {}; function on_destroy_request(request) waiting_requests[request] = nil; + local session = request.session; + if session then + local requests = session.requests; + for i,r in pairs(requests) do + if r == request then requests[i] = nil; break; end + end + + -- If this session now has no requests open, mark it as inactive + if #requests == 0 and session.bosh_max_inactive and not inactive_sessions[session] then + inactive_sessions[session] = os_time(); + (session.log or log)("debug", "BOSH session marked as inactive at %d", inactive_sessions[session]); + end + end end function handle_request(method, body, request) @@ -151,10 +164,6 @@ function stream_callbacks.streamopened(request, attr) end elseif s ~= "" then log("debug", "Saved to send buffer because there are %d open requests", #r); - if session.bosh_max_inactive and not inactive_sessions[session] then - inactive_sessions[session] = os_time(); - (session.log or log)("debug", "BOSH session marked as inactive at %d", inactive_sessions[session]); - end -- Hmm, no requests are open :( t_insert(session.send_buffer, tostring(s)); log("debug", "There are now %d things in the send_buffer", #session.send_buffer); @@ -243,7 +252,6 @@ function on_timer() (session.log or log)("debug", "BOSH client inactive too long, destroying session at %d", now); sessions[session.sid] = nil; inactive_sessions[session] = nil; - session.bosh_max_inactive = nil; -- Stop us marking this session as active during destroy sm_destroy_session(session, "BOSH client silent for over "..session.bosh_max_inactive.." seconds"); end else -- cgit v1.2.3 From ac2f11fb5fbbe8111ce741e4509a73a71442f400 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Thu, 19 Feb 2009 02:01:31 +0500 Subject: MUC: Added logging --- plugins/mod_muc.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index 7c18b9c4..38e93a45 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -226,11 +226,13 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc local room = jid_bare(to); local current_nick = jid_nick:get(from, room); local type = stanza.attr.type; + log("debug", "room: %s, current_nick: %s, stanza: %s", room, current_nick, stanza:top_tag()); if stanza.name == "presence" then local pr = get_filtered_presence(stanza); pr.attr.from = to; if type == "error" then -- error, kick em out! if current_nick then + log("debug", "kicking %s from %s", current_nick, room); local data = rooms:get(room, current_nick); data.role = 'none'; local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error presence'):up() @@ -243,6 +245,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc end elseif type == "unavailable" then -- unavailable if current_nick then + log("debug", "%s leaving %s", current_nick, room); local data = rooms:get(room, current_nick); data.role = 'none'; broadcast_presence_stanza(room, pr); @@ -254,19 +257,23 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc if current_nick then if current_nick == to then -- simple presence if #pr == #stanza then + log("debug", "%s broadcasted presence", current_nick); broadcast_presence_stanza(room, pr); else -- possible rejoin + log("debug", "%s had connection replaced", current_nick); local pr_ = st.presence({type='unavailable', from=from, to=current_nick}):tag('status'):text('Replaced by new connection'); handle_to_occupant(origin, pr_); -- send unavailable handle_to_occupant(origin, pr); -- resend available end else -- change nick if rooms:get(room, to) then + log("debug", "%s couldn't change nick", current_nick); origin.send(st.error_reply(stanza, "cancel", "conflict")); else local data = rooms:get(room, current_nick); local to_nick = select(3, jid_split(to)); if to_nick then + log("debug", "%s changing nick to %s", current_nick, to_nick); local p = st.presence({type='unavailable', from=current_nick}); --[[:tag('x', {xmlns='http://jabber.org/protocol/muc#user'}) :tag('item', {affiliation=data.affiliation, role=data.role, nick=to_nick}):up() @@ -289,8 +296,10 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc new_nick = nil; end if not new_nick then + log("debug", "%s couldn't join due to nick conflict: %s", from, to); origin.send(st.error_reply(stanza, "cancel", "conflict")); else + log("debug", "%s joining as %s", from, to); local data; if not rooms:get(room) and not rooms_info:get(room) then -- new room data = {affiliation='owner', role='moderator', jid=from, sessions={[from]=get_filtered_presence(stanza)}}; @@ -338,6 +347,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc origin.send(st.error_reply(stanza, "modify", "bad-request")); elseif stanza.name == "message" and type == "error" then if current_nick then + log("debug", "%s kicked from %s for sending an error message", current_nick, room); local data = rooms:get(room, to); data.role = 'none'; local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant'):up() @@ -350,6 +360,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc else -- private stanza local o_data = rooms:get(room, to); if o_data then + log("debug", "%s sent private stanza to %s (%s)", from, to, o_data.jid); local jid = o_data.jid; if stanza.name=='iq' and type=='get' and stanza.tags[1].attr.xmlns == 'vcard-temp' then jid = jid_bare(jid); end stanza.attr.to, stanza.attr.from = jid, current_nick; -- cgit v1.2.3 From 3b253992f156d8c91a1d9be6141349e032fa49bf Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Thu, 19 Feb 2009 14:10:26 +0500 Subject: MUC: Logging - logger doesn't like nils --- plugins/mod_muc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index 38e93a45..51a6c3b5 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -226,7 +226,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc local room = jid_bare(to); local current_nick = jid_nick:get(from, room); local type = stanza.attr.type; - log("debug", "room: %s, current_nick: %s, stanza: %s", room, current_nick, stanza:top_tag()); + log("debug", "room: %s, current_nick: %s, stanza: %s", room or "nil", current_nick or "nil", stanza:top_tag()); if stanza.name == "presence" then local pr = get_filtered_presence(stanza); pr.attr.from = to; -- cgit v1.2.3 From 3af91c3bf28a042b5ba08d085b3b4f1aefabb377 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Thu, 19 Feb 2009 20:17:07 +0500 Subject: MUC: Bug fixes and workarounds --- plugins/mod_muc.lua | 70 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index 51a6c3b5..5fa52726 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -229,7 +229,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc log("debug", "room: %s, current_nick: %s, stanza: %s", room or "nil", current_nick or "nil", stanza:top_tag()); if stanza.name == "presence" then local pr = get_filtered_presence(stanza); - pr.attr.from = to; + pr.attr.from = current_nick; if type == "error" then -- error, kick em out! if current_nick then log("debug", "kicking %s from %s", current_nick, room); @@ -246,6 +246,8 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc elseif type == "unavailable" then -- unavailable if current_nick then log("debug", "%s leaving %s", current_nick, room); +-- log("debug", "rooms: %s", require "util.serialization".serialize(rooms.data)); +-- log("debug", "jid_nick: %s", require "util.serialization".serialize(jid_nick.data)); local data = rooms:get(room, current_nick); data.role = 'none'; broadcast_presence_stanza(room, pr); @@ -255,40 +257,47 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc end elseif not type then -- available if current_nick then - if current_nick == to then -- simple presence - if #pr == #stanza then + if #pr == #stanza then + if current_nick == to then -- simple presence log("debug", "%s broadcasted presence", current_nick); + rooms:get(room, current_nick).sessions[from] = pr; broadcast_presence_stanza(room, pr); - else -- possible rejoin - log("debug", "%s had connection replaced", current_nick); - local pr_ = st.presence({type='unavailable', from=from, to=current_nick}):tag('status'):text('Replaced by new connection'); - handle_to_occupant(origin, pr_); -- send unavailable - handle_to_occupant(origin, pr); -- resend available - end - else -- change nick - if rooms:get(room, to) then - log("debug", "%s couldn't change nick", current_nick); - origin.send(st.error_reply(stanza, "cancel", "conflict")); - else - local data = rooms:get(room, current_nick); - local to_nick = select(3, jid_split(to)); - if to_nick then - log("debug", "%s changing nick to %s", current_nick, to_nick); - local p = st.presence({type='unavailable', from=current_nick}); - --[[:tag('x', {xmlns='http://jabber.org/protocol/muc#user'}) - :tag('item', {affiliation=data.affiliation, role=data.role, nick=to_nick}):up() - :tag('status', {code='303'});]] - broadcast_presence_stanza(room, p, '303', to_nick); - --broadcast_presence('unavailable', current_nick, room, '303', to_nick); - rooms:remove(room, current_nick); - rooms:set(room, to, data); - jid_nick:set(from, room, to); - broadcast_presence_stanza(room, pr); - --broadcast_presence(nil, to, room, nil); + else -- change nick + if rooms:get(room, to) then + log("debug", "%s couldn't change nick", current_nick); + origin.send(st.error_reply(stanza, "cancel", "conflict")); else - --TODO malformed-jid + local data = rooms:get(room, current_nick); + local to_nick = select(3, jid_split(to)); + if to_nick then + log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to); +-- log("debug", "rooms: %s", require "util.serialization".serialize(rooms.data)); +-- log("debug", "jid_nick: %s", require "util.serialization".serialize(jid_nick.data)); + local p = st.presence({type='unavailable', from=current_nick}); + --[[:tag('x', {xmlns='http://jabber.org/protocol/muc#user'}) + :tag('item', {affiliation=data.affiliation, role=data.role, nick=to_nick}):up() + :tag('status', {code='303'});]] + broadcast_presence_stanza(room, p, '303', to_nick); + --broadcast_presence('unavailable', current_nick, room, '303', to_nick); + rooms:remove(room, current_nick); + rooms:set(room, to, data); + jid_nick:set(from, room, to); + pr.attr.from = to; + rooms:get(room, to).sessions[from] = pr; + broadcast_presence_stanza(room, pr); +-- log("debug", "rooms: %s", require "util.serialization".serialize(rooms.data)); +-- log("debug", "jid_nick: %s", require "util.serialization".serialize(jid_nick.data)); + --broadcast_presence(nil, to, room, nil); + else + --TODO malformed-jid + end end end + else -- possible rejoin + log("debug", "%s had connection replaced", current_nick); + local pr_ = st.presence({type='unavailable', from=from, to=current_nick}):tag('status'):text('Replaced by new connection'); + handle_to_occupant(origin, pr_); -- send unavailable + handle_to_occupant(origin, stanza); -- resend available end else -- enter room local new_nick = to; @@ -323,6 +332,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc end end end + pr.attr.from = to; broadcast_presence_stanza(room, pr); --broadcast_presence(nil, to, room); local history = rooms_info:get(room, 'history'); -- send discussion history -- cgit v1.2.3 From 412368f62ac29b4880f14c26372806a32b2bb4ae Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 19 Feb 2009 19:00:18 +0000 Subject: core.presencemanager: Set 'from' attribute on outgoing unavailable directed presences --- core/presencemanager.lua | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/core/presencemanager.lua b/core/presencemanager.lua index 8fdf3612..f94ffd55 100644 --- a/core/presencemanager.lua +++ b/core/presencemanager.lua @@ -95,13 +95,16 @@ function handle_normal_presence(origin, stanza, core_route_stanza) end origin.priority = 0; if stanza.attr.type == "unavailable" then - origin.presence = nil; - if origin.directed then - for jid in pairs(origin.directed) do - stanza.attr.to = jid; - core_route_stanza(origin, stanza); - end - origin.directed = nil; + 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; -- cgit v1.2.3 From 1113fbdedd06e496c037a9449fd9136c0cbf58bb Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Fri, 20 Feb 2009 00:51:33 +0500 Subject: MUC: Throw an error if we try talking to ourselves --- plugins/mod_muc.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index 5fa52726..e02ab00e 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -227,6 +227,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc local current_nick = jid_nick:get(from, room); local type = stanza.attr.type; log("debug", "room: %s, current_nick: %s, stanza: %s", room or "nil", current_nick or "nil", stanza:top_tag()); + if (select(2, jid_split(from)) == muc_domain) error("Presence from the MUC itself!!!"); if stanza.name == "presence" then local pr = get_filtered_presence(stanza); pr.attr.from = current_nick; -- cgit v1.2.3 From 4c696b7d8acaed5e4e324cae6f27d28d21a101d5 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Fri, 20 Feb 2009 00:56:14 +0500 Subject: MUC: Syntax error in last commit - this is lua :) --- plugins/mod_muc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index e02ab00e..b82ea37f 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -227,7 +227,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc local current_nick = jid_nick:get(from, room); local type = stanza.attr.type; log("debug", "room: %s, current_nick: %s, stanza: %s", room or "nil", current_nick or "nil", stanza:top_tag()); - if (select(2, jid_split(from)) == muc_domain) error("Presence from the MUC itself!!!"); + if (select(2, jid_split(from)) == muc_domain) then error("Presence from the MUC itself!!!"); end if stanza.name == "presence" then local pr = get_filtered_presence(stanza); pr.attr.from = current_nick; -- cgit v1.2.3 From 0fe02618e58fb93ebdf11ff38efcf71015a0ca81 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Fri, 20 Feb 2009 02:18:07 +0500 Subject: util/stanza: Added clone function --- util/stanza.lua | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/util/stanza.lua b/util/stanza.lua index 1c1cab0e..5bc15609 100644 --- a/util/stanza.lua +++ b/util/stanza.lua @@ -12,9 +12,10 @@ local t_concat = table.concat; local t_remove = table.remove; local t_concat = table.concat; local s_format = string.format; -local s_match = string.match; +local s_match = string.match; local tostring = tostring; local setmetatable = setmetatable; +local getmetatable = getmetatable; local pairs = pairs; local ipairs = ipairs; local type = type; @@ -215,6 +216,24 @@ function deserialize(stanza) return stanza; end +function clone(stanza) + local lookup_table = {}; + local function _copy(object) + if type(object) ~= "table" then + return object; + elseif lookup_table[object] then + return lookup_table[object]; + end + local new_table = {}; + lookup_table[object] = new_table; + for index, value in pairs(object) do + new_table[_copy(index)] = _copy(value); + end + return setmetatable(new_table, getmetatable(object)); + end + return _copy(stanza) +end + function message(attr, body) if not body then return stanza("message", attr); -- cgit v1.2.3 From b561d477830c46fbf4bda0b8145788c4c45ec30f Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Fri, 20 Feb 2009 02:23:21 +0500 Subject: MUC: Use util.stanza.clone instead of pre/deserialize for cloning stanzas --- plugins/mod_muc.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index b82ea37f..bae3d476 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -62,7 +62,7 @@ function filter_xmlns_from_stanza(stanza, filters) end local presence_filters = {["http://jabber.org/protocol/muc"]=true;["http://jabber.org/protocol/muc#user"]=true}; function get_filtered_presence(stanza) - return filter_xmlns_from_stanza(st.deserialize(st.preserialize(stanza)), presence_filters); + return filter_xmlns_from_stanza(st.clone(stanza), presence_filters); end function getUsingPath(stanza, path, getText) local tag = stanza; @@ -162,10 +162,10 @@ function broadcast_message(from, room, subject, body) if not subject and body then -- add to history local history = rooms_info:get(room, 'history'); if not history then history = {}; rooms_info:set(room, 'history', history); end - -- stanza = st.deserialize(st.preserialize(stanza)); + -- stanza = st.clone(stanza); stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = muc_domain, stamp = datetime.datetime()}):up(); -- XEP-0203 stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated) - t_insert(history, st.preserialize(stanza)); + t_insert(history, st.clone(st.preserialize(stanza))); while #history > history_length do t_remove(history, 1) end end end @@ -182,10 +182,10 @@ function broadcast_message_stanza(room, stanza, historic) if historic then -- add to history local history = rooms_info:get(room, 'history'); if not history then history = {}; rooms_info:set(room, 'history', history); end - -- stanza = st.deserialize(st.preserialize(stanza)); + -- stanza = st.clone(stanza); stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = muc_domain, stamp = datetime.datetime()}):up(); -- XEP-0203 stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated) - t_insert(history, st.preserialize(stanza)); + t_insert(history, st.clone(st.preserialize(stanza))); while #history > history_length do t_remove(history, 1) end end end -- cgit v1.2.3 From 8f0b93e738a6df64a7eb70766ff31873c880d436 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Fri, 20 Feb 2009 03:52:04 +0500 Subject: MUC: Workaround for a Gajim bug (it includes in nick change presences) --- plugins/mod_muc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index bae3d476..a0252dfc 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -258,7 +258,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc end elseif not type then -- available if current_nick then - if #pr == #stanza then + if #pr == #stanza or current_nick ~= to then if current_nick == to then -- simple presence log("debug", "%s broadcasted presence", current_nick); rooms:get(room, current_nick).sessions[from] = pr; -- cgit v1.2.3 From 97ea70c7d325fcdd6342a84464e9b7b26d9da177 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 21 Feb 2009 01:13:53 +0500 Subject: Added util/timer.lua - a timer API --- util/timer.lua | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 util/timer.lua diff --git a/util/timer.lua b/util/timer.lua new file mode 100644 index 00000000..889a8c4c --- /dev/null +++ b/util/timer.lua @@ -0,0 +1,47 @@ +-- Prosody IM v0.3 +-- 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 ns_addtimer = require "net.server".addtimer; +local get_time = os.time; +local t_insert = table.insert; +local ipairs = ipairs; +local type = type; + +local data = {}; +local new_data = {}; + +module "timer" + +local function _add_task(delay, func) + local current_time = get_time(); + delay = delay + current_time; + if delay >= current_time then + t_insert(new_data, {delay, func}); + else func(); end +end + +add_task = _add_task; + +ns_addtimer(function() + local current_time = get_time(); + for _, d in ipairs(new_data) do + t_insert(data, d); + end + new_data = {}; + for i = #data,1 do + local t, func = data[i][1], data[i][2]; + if t <= current_time then + data[i] = nil; + local r = func(); + if type(r) == "number" then _add_task(r, func); end + end + end +end); + +return _M; -- cgit v1.2.3 From 656e45305cbbfbb55ebefdb4c51ef7bffaf07ece Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 21 Feb 2009 01:24:23 +0500 Subject: MUC: Removed commented and unused code --- plugins/mod_muc.lua | 69 +---------------------------------------------------- 1 file changed, 1 insertion(+), 68 deletions(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index a0252dfc..4b10a907 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -119,57 +119,9 @@ function set_subject(current_nick, room, subject) local msg = st.message({type='groupchat', from=current_nick}) :tag('subject'):text(subject):up(); broadcast_message_stanza(room, msg, false); - --broadcast_message(current_nick, room, subject or "", nil); return true; end -function broadcast_presence(type, from, room, code, newnick) - local data = rooms:get(room, from); - local stanza = st.presence({type=type, from=from}) - :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) - :tag("item", {affiliation=data.affiliation, role=data.role, nick = newnick}):up(); - if code then - stanza:tag("status", {code=code}):up(); - end - local me; - local r = rooms:get(room); - if r then - for occupant, o_data in pairs(r) do - if occupant ~= from then - stanza.attr.to = o_data.jid; - core_route_stanza(component, stanza); - else - me = o_data.jid; - end - end - end - if me then - stanza:tag("status", {code='110'}); - stanza.attr.to = me; - core_route_stanza(component, stanza); - end -end -function broadcast_message(from, room, subject, body) - local stanza = st.message({type='groupchat', from=from}); - if subject then stanza:tag('subject'):text(subject):up(); end - if body then stanza:tag('body'):text(body):up(); end - local r = rooms:get(room); - if r then - for occupant, o_data in pairs(r) do - stanza.attr.to = o_data.jid; - core_route_stanza(component, stanza); - end - if not subject and body then -- add to history - local history = rooms_info:get(room, 'history'); - if not history then history = {}; rooms_info:set(room, 'history', history); end - -- stanza = st.clone(stanza); - stanza:tag("delay", {xmlns = "urn:xmpp:delay", from = muc_domain, stamp = datetime.datetime()}):up(); -- XEP-0203 - stanza:tag("x", {xmlns = "jabber:x:delay", from = muc_domain, stamp = datetime.legacy()}):up(); -- XEP-0091 (deprecated) - t_insert(history, st.clone(st.preserialize(stanza))); - while #history > history_length do t_remove(history, 1) end - end - end -end function broadcast_message_stanza(room, stanza, historic) local r = rooms:get(room); if r then @@ -237,22 +189,16 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc local data = rooms:get(room, current_nick); data.role = 'none'; local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error presence'):up() - --:tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) - --:tag("item", {affiliation=data.affiliation, role=data.role}):up(); broadcast_presence_stanza(room, pr); - --broadcast_presence('unavailable', current_nick, room); -- TODO also add This participant is kicked from the room because he sent an error presence: badformed error stanza rooms:remove(room, current_nick); jid_nick:remove(from, room); end elseif type == "unavailable" then -- unavailable if current_nick then log("debug", "%s leaving %s", current_nick, room); --- log("debug", "rooms: %s", require "util.serialization".serialize(rooms.data)); --- log("debug", "jid_nick: %s", require "util.serialization".serialize(jid_nick.data)); local data = rooms:get(room, current_nick); data.role = 'none'; broadcast_presence_stanza(room, pr); - --broadcast_presence('unavailable', current_nick, room); rooms:remove(room, current_nick); jid_nick:remove(from, room); end @@ -272,23 +218,14 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc local to_nick = select(3, jid_split(to)); if to_nick then log("debug", "%s (%s) changing nick to %s", current_nick, data.jid, to); --- log("debug", "rooms: %s", require "util.serialization".serialize(rooms.data)); --- log("debug", "jid_nick: %s", require "util.serialization".serialize(jid_nick.data)); local p = st.presence({type='unavailable', from=current_nick}); - --[[:tag('x', {xmlns='http://jabber.org/protocol/muc#user'}) - :tag('item', {affiliation=data.affiliation, role=data.role, nick=to_nick}):up() - :tag('status', {code='303'});]] broadcast_presence_stanza(room, p, '303', to_nick); - --broadcast_presence('unavailable', current_nick, room, '303', to_nick); rooms:remove(room, current_nick); rooms:set(room, to, data); jid_nick:set(from, room, to); pr.attr.from = to; rooms:get(room, to).sessions[from] = pr; broadcast_presence_stanza(room, pr); --- log("debug", "rooms: %s", require "util.serialization".serialize(rooms.data)); --- log("debug", "jid_nick: %s", require "util.serialization".serialize(jid_nick.data)); - --broadcast_presence(nil, to, room, nil); else --TODO malformed-jid end @@ -325,9 +262,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc if occupant ~= to then local pres = get_filtered_presence(o_data.sessions[o_data.jid]); pres.attr.to, pres.attr.from = from, occupant; - pres - --local pres = st.presence({to=from, from=occupant}) - :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) + 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 @@ -335,7 +270,6 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc end pr.attr.from = to; broadcast_presence_stanza(room, pr); - --broadcast_presence(nil, to, room); local history = rooms_info:get(room, 'history'); -- send discussion history if history then for _, msg in ipairs(history) do @@ -406,7 +340,6 @@ function handle_to_room(origin, stanza) -- presence changes and groupchat messag if subject then set_subject(current_nick, room, subject); -- TODO use broadcast_message_stanza else - --broadcast_message(current_nick, room, nil, getText(stanza, {"body"})); broadcast_message_stanza(room, stanza, true); end end -- cgit v1.2.3 From 56b621a54d64a8ed13d785ac5d39616f18aa8ffb Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 21 Feb 2009 01:49:09 +0500 Subject: MUC: Replaced some duplicate code --- plugins/mod_muc.lua | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index 4b10a907..a2bc683b 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -186,12 +186,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc if type == "error" then -- error, kick em out! if current_nick then log("debug", "kicking %s from %s", current_nick, room); - local data = rooms:get(room, current_nick); - data.role = 'none'; - local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error presence'):up() - broadcast_presence_stanza(room, pr); - rooms:remove(room, current_nick); - jid_nick:remove(from, room); + handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('This participant is kicked from the room because he sent an error presence')); -- send unavailable end elseif type == "unavailable" then -- unavailable if current_nick then @@ -233,8 +228,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc end else -- possible rejoin log("debug", "%s had connection replaced", current_nick); - local pr_ = st.presence({type='unavailable', from=from, to=current_nick}):tag('status'):text('Replaced by new connection'); - handle_to_occupant(origin, pr_); -- send unavailable + handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('Replaced by new connection')); -- send unavailable handle_to_occupant(origin, stanza); -- resend available end else -- enter room @@ -291,17 +285,8 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc elseif stanza.name == "message" and type == "groupchat" then -- groupchat messages not allowed in PM origin.send(st.error_reply(stanza, "modify", "bad-request")); elseif stanza.name == "message" and type == "error" then - if current_nick then - log("debug", "%s kicked from %s for sending an error message", current_nick, room); - local data = rooms:get(room, to); - data.role = 'none'; - local pr = st.presence({type='unavailable', from=current_nick}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant'):up() - :tag("x", {xmlns='http://jabber.org/protocol/muc#user'}) - :tag("item", {affiliation=data.affiliation, role=data.role}):up(); - broadcast_presence_stanza(room, pr); - rooms:remove(room, to); - jid_nick:remove(from, room); - end + log("debug", "%s kicked from %s for sending an error message", current_nick, room); + handle_to_occupant(origin, st.presence({type='unavailable', from=from, to=to}):tag('status'):text('This participant is kicked from the room because he sent an error message to another occupant')); -- send unavailable else -- private stanza local o_data = rooms:get(room, to); if o_data then -- cgit v1.2.3 From 4c2d9d14bc190e9c17d51a1eae47cf9a7a34b861 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Sat, 21 Feb 2009 01:57:13 +0500 Subject: MUC: Added copyright notice --- plugins/mod_muc.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index a2bc683b..83c35563 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -1,3 +1,10 @@ +-- Prosody IM v0.3 +-- 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 register_component = require "core.componentmanager".register_component; -- cgit v1.2.3 From e2908c06e1c8340db7c424c7ef158c2b5674c460 Mon Sep 17 00:00:00 2001 From: Waqas Hussain Date: Mon, 23 Feb 2009 01:14:23 +0500 Subject: mod_register: Fixed an error happening during account deletion --- plugins/mod_register.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_register.lua b/plugins/mod_register.lua index ba5bcf36..c1487228 100644 --- a/plugins/mod_register.lua +++ b/plugins/mod_register.lua @@ -44,7 +44,7 @@ module:add_iq_handler("c2s", "jabber:iq:register", function (session, stanza) datamanager.store(session.username, session.host, "vcard", nil); datamanager.store(session.username, session.host, "private", nil); datamanager.store(session.username, session.host, "offline", nil); - local bare = session.username.."@"..session.host; + --local bare = session.username.."@"..session.host; for jid, item in pairs(roster) do if jid ~= "pending" then if item.subscription == "both" or item.subscription == "to" then -- cgit v1.2.3 From d0072c9cfab3365c0fe5f8f3bfda87be899c8e13 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Feb 2009 02:24:12 +0000 Subject: net/xmppclient_listener: Add some logging and handle unestablished sessions error'ing --- net/xmppclient_listener.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/xmppclient_listener.lua b/net/xmppclient_listener.lua index ad1fd948..e7a87c1e 100644 --- a/net/xmppclient_listener.lua +++ b/net/xmppclient_listener.lua @@ -29,9 +29,10 @@ local stream_callbacks = { stream_tag = "http://etherx.jabber.org/streams|stream function stream_callbacks.error(session, error, data) if error == "no-stream" then + session.log("debug", "Invalid opening stream header"); session:close("invalid-namespace"); - else - session.log("debug", "Client XML parse error: %s", tostring(error)); + elseif session.close then + (session.log or log)("debug", "Client XML parse error: %s", tostring(error)); session:close("xml-not-well-formed"); end end -- cgit v1.2.3 From 2aa35ba40d4868d6e65f07b743b269c89d6b0e46 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Feb 2009 02:26:30 +0000 Subject: core.xmlhandlers: Optimise completed stanza logic --- core/xmlhandlers.lua | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/core/xmlhandlers.lua b/core/xmlhandlers.lua index 020e08db..56115917 100644 --- a/core/xmlhandlers.lua +++ b/core/xmlhandlers.lua @@ -121,17 +121,19 @@ function init_xmlhandlers(session, stream_callbacks) cb_error(session, "parse-error", "unexpected-element-close", name); end end - if stanza and #chardata > 0 then - -- We have some character data in the buffer - stanza:text(t_concat(chardata)); - chardata = {}; - end - -- Complete stanza - if #stanza.last_add == 0 then - cb_handlestanza(session, stanza); - stanza = nil; - else - stanza:up(); + if stanza then + if stanza and #chardata > 0 then + -- We have some character data in the buffer + stanza:text(t_concat(chardata)); + chardata = {}; + end + -- Complete stanza + if #stanza.last_add == 0 then + cb_handlestanza(session, stanza); + stanza = nil; + else + stanza:up(); + end end end return xml_handlers; -- cgit v1.2.3 From 073db87d448354024c663a695be2e4c62e8f506d Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Feb 2009 02:42:47 +0000 Subject: Better handling of found, but unloadable, core libraries (eg. undefined symbols) --- util/dependencies.lua | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/util/dependencies.lua b/util/dependencies.lua index 09b7b018..6ba5f670 100644 --- a/util/dependencies.lua +++ b/util/dependencies.lua @@ -9,7 +9,7 @@ local fatal; -local function softreq(...) local ok, lib = pcall(require, ...); if ok then return lib; else return nil; end end +local function softreq(...) local ok, lib = pcall(require, ...); if ok then return lib; else return nil, lib; end end local function missingdep(name, sources, msg) print(""); @@ -51,19 +51,37 @@ if not ssl then end end -local encodings = softreq "util.encodings" +local encodings, err = softreq "util.encodings" if not encodings then - missingdep("util.encodings", { ["Windows"] = "Make sure you have encodings.dll from the Prosody distribution in util/"; + if err:match("not found") then + missingdep("util.encodings", { ["Windows"] = "Make sure you have encodings.dll from the Prosody distribution in util/"; ["GNU/Linux"] = "Run './configure' and 'make' in the Prosody source directory to build util/encodings.so"; }); + else + print "***********************************" + print("util/encodings couldn't be loaded. Check that you have a recent version of libidn"); + print "" + print("The full error was:"); + print(err) + print "***********************************" + end fatal = true; end -local encodings = softreq "util.hashes" -if not encodings then - missingdep("util.hashes", { ["Windows"] = "Make sure you have hashes.dll from the Prosody distribution in util/"; +local hashes, err = softreq "util.hashes" +if not hashes then + if err:match("not found") then + missingdep("util.hashes", { ["Windows"] = "Make sure you have hashes.dll from the Prosody distribution in util/"; ["GNU/Linux"] = "Run './configure' and 'make' in the Prosody source directory to build util/hashes.so"; }); + else + print "***********************************" + print("util/hashes couldn't be loaded. Check that you have a recent version of OpenSSL (libcrypto in particular)"); + print "" + print("The full error was:"); + print(err) + print "***********************************" + end fatal = true; end -- cgit v1.2.3 From b9636951c1d64ec398a18a40b55ff92d83f50009 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Feb 2009 16:55:46 +0000 Subject: util.multitable: Add mt:search(), use nil for wildcard keys --- util/multitable.lua | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/util/multitable.lua b/util/multitable.lua index e5e87521..397f9ebe 100644 --- a/util/multitable.lua +++ b/util/multitable.lua @@ -82,6 +82,53 @@ local function remove(self, ...) end +local function s(t, n, results, _end, ...) + if t == nil then return; end + local k = select(n, ...); + if n == _end then + if k == nil then + for _, v in pairs(t) do + t_insert(results, v); + end + else + t_insert(results, t[k]); + end + return; + end + if k then + v = t[k]; + if v then + s(v, n+1, results, _end, ...); + end + else + for _,b in pairs(t) do + s(b, n+1, results, _end, ...); + end + end +end + +-- Search for keys, nil == wildcard +local function search(self, ...) + local _end = select('#', ...); + for n = _end,1 do + if select(n, ...) then _end = n; break; end + end + local results = {}; + s(self.data, 1, results, _end, ...); + return results; +end + +-- Append results to an existing list +local function search_add(self, results, ...) + if not results then results = {}; end + local _end = select('#', ...); + for n = _end,1 do + if select(n, ...) then _end = n; break; end + end + s(self.data, 1, results, _end, ...); + return results; +end + function new() return { data = {}; @@ -89,6 +136,8 @@ function new() add = add; set = set; remove = remove; + search = search; + search_add = search_add; }; end -- cgit v1.2.3 From d2631d39ca278c6823ffc6e19a670954507c981b Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Feb 2009 21:00:42 +0000 Subject: util.timer: Fix crash when loaded but no tasks set, fix skipping some tasks when multiple set, and one removed --- util/timer.lua | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/util/timer.lua b/util/timer.lua index 889a8c4c..8bb1c115 100644 --- a/util/timer.lua +++ b/util/timer.lua @@ -10,7 +10,8 @@ local ns_addtimer = require "net.server".addtimer; local get_time = os.time; local t_insert = table.insert; -local ipairs = ipairs; +local t_remove = table.remove; +local ipairs, pairs = ipairs, pairs; local type = type; local data = {}; @@ -30,14 +31,19 @@ add_task = _add_task; ns_addtimer(function() local current_time = get_time(); - for _, d in ipairs(new_data) do - t_insert(data, d); + if #new_data > 0 then + for _, d in ipairs(new_data) do + t_insert(data, d); + end + new_data = {}; + elseif #data == 0 then + return; end - new_data = {}; - for i = #data,1 do - local t, func = data[i][1], data[i][2]; + + for i, d in pairs(data) do + local t, func = d[1], d[2]; if t <= current_time then - data[i] = nil; + t_remove(data, i); local r = func(); if type(r) == "number" then _add_task(r, func); end end -- cgit v1.2.3 From 0c8bb8e89f63fe33e7a320e5d8bb308c1ba80192 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Thu, 26 Feb 2009 22:17:55 +0000 Subject: util.timer: More small fixes I forgot to commit --- util/timer.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/util/timer.lua b/util/timer.lua index 8bb1c115..3db66832 100644 --- a/util/timer.lua +++ b/util/timer.lua @@ -32,18 +32,16 @@ add_task = _add_task; ns_addtimer(function() local current_time = get_time(); if #new_data > 0 then - for _, d in ipairs(new_data) do + for _, d in pairs(new_data) do t_insert(data, d); end new_data = {}; - elseif #data == 0 then - return; end for i, d in pairs(data) do local t, func = d[1], d[2]; if t <= current_time then - t_remove(data, i); + data[i] = nil; local r = func(); if type(r) == "number" then _add_task(r, func); end end -- cgit v1.2.3 From 9122c9bfbba618ac47c0c5ae04c0db713ff1ed95 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Feb 2009 04:35:36 +0000 Subject: prosody: Protect main loop. Dare I say crashing finally becomes impossible. --- prosody | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/prosody b/prosody index 197446e6..9a9bb683 100755 --- a/prosody +++ b/prosody @@ -7,14 +7,14 @@ -- COPYING file in the source package for more information. -- --- Config here -- +-- Will be modified by configure script if run -- CFG_SOURCEDIR=nil; CFG_CONFIGDIR=os.getenv("PROSODY_CFGDIR"); CFG_PLUGINDIR=nil; CFG_DATADIR=os.getenv("PROSODY_DATADIR"); --- -- -- -- -- -- +-- -- -- -- -- -- -- ---- -- -- -- -- -- -- -- -- if CFG_SOURCEDIR then package.path = CFG_SOURCEDIR.."/?.lua;"..package.path @@ -84,7 +84,9 @@ require "core.usermanager" require "core.sessionmanager" require "core.stanza_router" ---[[ +-- Commented to protect us from +-- the second kind of people +--[[ pcall(require, "remdebug.engine"); if remdebug then remdebug.engine.start() end ]] @@ -104,6 +106,7 @@ require "util.datamanager".set_data_path(data_path); ----------- End of out-of-place code -------------- + eventmanager.fire_event("server-starting"); @@ -148,4 +151,13 @@ end eventmanager.fire_event("server-started"); -server.loop(); +local quitting; +while not quitting do + xpcall(server.loop, function (err) + if err:match("%d*: interrupted!$") then + quitting = true; + return; + end + eventmanager.fire_event("very-bad-error", "*", err, debug.traceback("", 2)); + end); +end -- cgit v1.2.3 From 219c84da4a2f42938e84ad60b53fbf1ed98954b8 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Feb 2009 04:42:06 +0000 Subject: core.xmlhandlers: Remove redundant check in condition --- core/xmlhandlers.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/xmlhandlers.lua b/core/xmlhandlers.lua index 56115917..ea136c8d 100644 --- a/core/xmlhandlers.lua +++ b/core/xmlhandlers.lua @@ -122,7 +122,7 @@ function init_xmlhandlers(session, stream_callbacks) end end if stanza then - if stanza and #chardata > 0 then + if #chardata > 0 then -- We have some character data in the buffer stanza:text(t_concat(chardata)); chardata = {}; -- cgit v1.2.3 From 2a5e41bed0c75505a5367e87c7c6e48220443434 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Feb 2009 17:56:07 +0000 Subject: util.dataforms: First commit, incomplete --- util/dataforms.lua | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 util/dataforms.lua diff --git a/util/dataforms.lua b/util/dataforms.lua new file mode 100644 index 00000000..ba751f6f --- /dev/null +++ b/util/dataforms.lua @@ -0,0 +1,69 @@ + +module "dataforms" + +local xmlns_forms = 'jabber:x:data'; + +local form_t = {}; +local form_mt = { __index = form_t }; + +function new(layout) + return setmetatable(layout, form_mt); +end + +local form_x_attr = { xmlns = xmlns_forms }; + +function form_t.form(layout, data) + local form = st.tag("x", form_x_attr); + for n, field in ipairs(layout) do + local field_type = field.type; + -- Add field tag + form:tag("field", { type = field_type, var = field.name }); + + local value = data[field.name]; + + -- Add value, depending on type + if field_type == "hidden" then + if type(value) == "table" then + -- Assume an XML snippet + form:add_child(value); + elseif value then + form:text(tostring(value)); + end + elseif field_type == "boolean" then + form:text((value and "1") or "0"); + elseif field_type == "fixed" then + + elseif field_type == "jid-multi" then + for _, jid in ipairs(value) do + form:tag("value"):text(jid):up(); + end + elseif field_type == "jid-single" then + form:tag("value"):text(value):up(); + + end + + -- Jump back up to list of fields + form:up(); + end +end + +function form_t.data(layout, stanza) + +end + + + +--[[ + +Layout: +{ + + title = "MUC Configuration", + instructions = [[Use this form to configure options for this MUC room.]], + + { name = "FORM_TYPE", type = "hidden", required = true }; + { name = "field-name", type = "field-type", required = false }; +} + + +--]] -- cgit v1.2.3 From c2b54ca16026643838440922fa966cea576f42d2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Fri, 27 Feb 2009 18:40:17 +0000 Subject: net.server: Some fixes for SSL/TLS handshake handling --- net/server.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/net/server.lua b/net/server.lua index cea2ada3..aacadacc 100644 --- a/net/server.lua +++ b/net/server.lua @@ -480,16 +480,19 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport if sslctx then -- ssl? ssl = true local wrote + local read local handshake = coroutine_wrap( function( client ) -- create handshake coroutine local err for i = 1, 10 do -- 10 handshake attemps + _sendlistlen = ( wrote and removesocket( _sendlist, socket, _sendlistlen ) ) or _sendlistlen + _readlistlen = ( read and removesocket( _readlist, socket, _readlistlen ) ) or _readlistlen + read, wrote = nil, nil _, err = client:dohandshake( ) if not err then --out_put( "server.lua: ssl handshake done" ) - _sendlistlen = ( wrote and removesocket( _sendlist, socket, _sendlistlen ) ) or _sendlistlen handler.readbuffer = _readbuffer -- when handshake is done, replace the handshake function with regular functions handler.sendbuffer = _sendbuffer - --return dispatch( handler ) + -- return dispatch( handler ) return true else out_put( "server.lua: error during ssl handshake: ", err ) @@ -497,6 +500,10 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport _sendlistlen = _sendlistlen + 1 _sendlist[ _sendlistlen ] = client wrote = true + elseif err == "wantread" and not read then + _readlistlen = _readlistlen + 1 + _readlist [ _readlistlen ] = client + read = true end --coroutine_yield( handler, nil, err ) -- handshake not finished coroutine_yield( ) @@ -558,8 +565,8 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport handler.starttls = nil needtls = nil - handler.receivedata = handler.handshake - handler.dispatchdata = handler.handshake + handler.readbuffer = handshake + handler.sendbuffer = handshake handshake( socket ) -- do handshake end handler.readbuffer = _readbuffer -- cgit v1.2.3 From 8c36520f60140741cde82860a05b39fbe1844535 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Feb 2009 02:05:37 +0000 Subject: core.componentmanager: Refactor a little to make XEP-0114 plugin a little simpler --- core/componentmanager.lua | 76 +++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/core/componentmanager.lua b/core/componentmanager.lua index 04909a07..15931167 100644 --- a/core/componentmanager.lua +++ b/core/componentmanager.lua @@ -7,20 +7,20 @@ -- - - + + local log = require "util.logger".init("componentmanager"); local configmanager = require "core.configmanager"; local eventmanager = require "core.eventmanager"; -local modulemanager = require "core.modulemanager"; -local jid_split = require "util.jid".split; +local modulemanager = require "core.modulemanager"; +local jid_split = require "util.jid".split; local hosts = hosts; -local pairs, type, tostring = pairs, type, tostring; - -local components = {}; - -module "componentmanager" +local pairs, type, tostring = pairs, type, tostring; + +local components = {}; + +module "componentmanager" function load_enabled_components(config) local defined_hosts = config or configmanager.getconfig(); @@ -39,34 +39,40 @@ function load_enabled_components(config) end eventmanager.add_event_hook("server-starting", load_enabled_components); - -function handle_stanza(origin, stanza) - local node, host = jid_split(stanza.attr.to); + +function handle_stanza(origin, stanza) + local node, host = jid_split(stanza.attr.to); local component = nil; if not component then component = components[stanza.attr.to]; end -- hack to allow hooking node@server/resource and server/resource - if not component then component = components[node.."@"..host]; end -- hack to allow hooking node@server + if not component then component = components[node.."@"..host]; end -- hack to allow hooking node@server if not component then component = components[host]; end - if component then - log("debug", "stanza being handled by component: "..host); - component(origin, stanza, hosts[host]); - else - log("error", "Component manager recieved a stanza for a non-existing component: " .. stanza.attr.to); - end -end - -function register_component(host, component) - if not hosts[host] or (hosts[host].type == 'component' and not hosts[host].connected) then - -- TODO check for host well-formedness - components[host] = component; - hosts[host] = { type = "component", host = host, connected = true, s2sout = {} }; + if component then + log("debug", "stanza being handled by component: "..host); + component(origin, stanza, hosts[host]); + else + log("error", "Component manager recieved a stanza for a non-existing component: " .. stanza.attr.to); + end +end + +function create_component(host, component) + -- TODO check for host well-formedness + session = session or { type = "component", host = host, connected = true, s2sout = {}, send = component }; + return session; +end + +function register_component(host, component, session) + if not hosts[host] or (hosts[host].type == 'component' and not hosts[host].connected) then + components[host] = component; + hosts[host] = session or create_component(host, component); + -- FIXME only load for a.b.c if b.c has dialback, and/or check in config - modulemanager.load(host, "dialback"); - log("debug", "component added: "..host); - return hosts[host]; - else - log("error", "Attempt to set component for existing host: "..host); - end -end + modulemanager.load(host, "dialback"); + log("debug", "component added: "..host); + return session or hosts[host]; + else + log("error", "Attempt to set component for existing host: "..host); + end +end function deregister_component(host) if components[host] then @@ -79,5 +85,5 @@ function deregister_component(host) log("error", "Attempt to remove component for non-existing host: "..host); end end - -return _M; + +return _M; -- cgit v1.2.3 From 4a34bb9adef891a5451fdb3648c72c37bf54d744 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Feb 2009 04:58:14 +0000 Subject: core.stanza_router: Reply with error to groupchat messages directed at unavailable resources or offline users --- core/stanza_router.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/stanza_router.lua b/core/stanza_router.lua index 1ebc158d..29a4797b 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -217,6 +217,9 @@ function core_route_stanza(origin, stanza) session.send(stanza); end end + elseif resource and stanza.attr.type == 'groupchat' then + -- Groupchat message sent to offline resource + origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); else local priority = 0; local recipients = {}; @@ -263,6 +266,10 @@ function core_route_stanza(origin, stanza) if stanza.attr.type == "chat" or stanza.attr.type == "normal" or not stanza.attr.type then offlinemanager.store(node, host, stanza); -- FIXME don't store messages with only chat state notifications + elseif stanza.attr.type == "groupchat" then + local reply = st.error_reply(stanza, "cancel", "service-unavailable"); + reply.attr.from = to; + origin.send(reply); end -- TODO allow configuration of offline storage -- TODO send error if not storing offline -- cgit v1.2.3 From 1c998c518c525feb7555f6c493f230f8b5a3ebff Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sat, 28 Feb 2009 23:16:27 +0000 Subject: Adding initial util.pubsub --- util/pubsub.lua | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 util/pubsub.lua diff --git a/util/pubsub.lua b/util/pubsub.lua new file mode 100644 index 00000000..c1e35e3c --- /dev/null +++ b/util/pubsub.lua @@ -0,0 +1,60 @@ + +local ipairs, pairs, setmetatable, type = + ipairs, pairs, setmetatable, type; + +module "pubsub" + +local pubsub_node_mt = { __index = _M }; + +function new_node(name) + return setmetatable({ name = name, subscribers = {} }, pubsub_node_mt); +end + +function set_subscribers(node, subscribers_list, list_type) + local subscribers = node.subscribers; + + if list_type == "array" then + for _, jid in ipairs(subscribers_list) do + if not subscribers[jid] then + node:add_subscriber(jid); + end + end + elseif (not list_type) or list_type == "set" then + for jid in pairs(subscribers_list) do + if type(jid) == "string" then + node:add_subscriber(jid); + end + end + end +end + +function get_subscribers(node) + return node.subscribers; +end + +function publish(node, item, dispatcher, data) + local subscribers = node.subscribers; + for i = 1,#subscribers do + item.attr.to = subscribers[i]; + dispatcher(data, item); + end +end + +function add_subscriber(node, jid) + local subscribers = node.subscribers; + if not subscribers[jid] then + local space = #subscribers; + subscribers[space] = jid; + subscribers[jid] = space; + end +end + +function remove_subscriber(node, subscriber) + local subscribers = node.subscribers; + if subscribers[jid] then + subscribers[subscribers[jid]] = nil; + subscribers[jid] = nil; + end +end + +return _M; -- cgit v1.2.3 From fffdba514a7f52494dbc6943da525171d2fd7104 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 1 Mar 2009 23:33:41 +0000 Subject: net.server: Don't retry if client closes socket during SSL handshaking --- net/server.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/server.lua b/net/server.lua index aacadacc..e895f8aa 100644 --- a/net/server.lua +++ b/net/server.lua @@ -489,7 +489,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport read, wrote = nil, nil _, err = client:dohandshake( ) if not err then - --out_put( "server.lua: ssl handshake done" ) + out_put( "server.lua: ssl handshake done" ) handler.readbuffer = _readbuffer -- when handshake is done, replace the handshake function with regular functions handler.sendbuffer = _sendbuffer -- return dispatch( handler ) @@ -504,12 +504,14 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport _readlistlen = _readlistlen + 1 _readlist [ _readlistlen ] = client read = true + else + break; end --coroutine_yield( handler, nil, err ) -- handshake not finished coroutine_yield( ) end end - disconnect( handler, "max handshake attemps exceeded" ) + disconnect( handler, "ssl handshake failed" ) handler.close( true ) -- forced disconnect return false -- handshake failed end -- cgit v1.2.3 From fbb86043bd4380e25d81a3e15774a1f8d50a94e6 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Sun, 1 Mar 2009 23:34:25 +0000 Subject: util.dataforms: Return the form --- util/dataforms.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/util/dataforms.lua b/util/dataforms.lua index ba751f6f..c10a0244 100644 --- a/util/dataforms.lua +++ b/util/dataforms.lua @@ -45,6 +45,7 @@ function form_t.form(layout, data) -- Jump back up to list of fields form:up(); end + return form; end function form_t.data(layout, stanza) -- cgit v1.2.3 From 1a7a72a9f664b78bbb093a5c59620cfdadb18c93 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 2 Mar 2009 13:52:08 +0000 Subject: core.s2smanager: Remove some old commented code, break a long line in 2 --- core/s2smanager.lua | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/core/s2smanager.lua b/core/s2smanager.lua index 4f205418..db6d2fe5 100644 --- a/core/s2smanager.lua +++ b/core/s2smanager.lua @@ -206,22 +206,19 @@ function streamopened(session, attr) session.version = 0; --tonumber(attr.version) or 0; if session.version >= 1.0 and not (attr.to and attr.from) then - --print("to: "..tostring(attr.to).." from: "..tostring(attr.from)); log("warn", (session.to_host or "(unknown)").." failed to specify 'to' or 'from' hostname as per RFC"); end if session.direction == "incoming" then -- Send a reply stream header - - --for k,v in pairs(attr) do print("", tostring(k), ":::", tostring(v)); end - session.to_host = attr.to; session.from_host = attr.from; session.streamid = uuid_gen(); (session.log or log)("debug", "incoming s2s received "); send(""); - 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()); + 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()); if session.to_host and not hosts[session.to_host] then -- Attempting to connect to a host we don't serve session:close({ condition = "host-unknown"; text = "This host does not serve "..session.to_host }); -- cgit v1.2.3 From 3db74ae200f8766a2bf5588cc20e5c4905e1030a Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 2 Mar 2009 19:44:46 +0000 Subject: prosody: Log top-level errors --- prosody | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/prosody b/prosody index 9a9bb683..15c94c92 100755 --- a/prosody +++ b/prosody @@ -158,6 +158,14 @@ while not quitting do quitting = true; return; end - eventmanager.fire_event("very-bad-error", "*", err, debug.traceback("", 2)); + + log("error", "Top-level error, please report:\n%s", tostring(err)); + + local traceback = debug.traceback("", 2); + if traceback then + log("error", "%s", traceback); + end + + eventmanager.fire_event("very-bad-error", "*", err, traceback); end); end -- cgit v1.2.3 From a6107b2b5e84db104641545bd72c7d871678261f Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 2 Mar 2009 19:45:44 +0000 Subject: core.stanza_router: Don't bounce errors to iq type=result/error --- core/stanza_router.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/stanza_router.lua b/core/stanza_router.lua index 29a4797b..23b7a37d 100644 --- a/core/stanza_router.lua +++ b/core/stanza_router.lua @@ -273,7 +273,7 @@ function core_route_stanza(origin, stanza) end -- TODO allow configuration of offline storage -- TODO send error if not storing offline - elseif stanza.name == "iq" then + elseif stanza.name == "iq" and (stanza.attr.type == "get" or stanza.attr.type == "set") then origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); end else -- user does not exist @@ -284,7 +284,7 @@ function core_route_stanza(origin, stanza) origin.send(st.presence({from = to_bare, to = from_bare, type = "unsubscribed"})); end -- else ignore - else + elseif stanza.attr.type ~= "error" and (stanza.name ~= "iq" or stanza.attr.type ~= "result") then origin.send(st.error_reply(stanza, "cancel", "service-unavailable")); end end -- cgit v1.2.3 From 0a2936fb0fef58e0937a86fa42e213bec51650f2 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 2 Mar 2009 19:49:09 +0000 Subject: net.server: Fix to make sure we send a string to logging function --- net/server.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/server.lua b/net/server.lua index e895f8aa..8d0d3b1a 100644 --- a/net/server.lua +++ b/net/server.lua @@ -438,7 +438,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport --out_put( "server.lua: read data '", buffer, "', error: ", err ) return dispatch( handler, buffer, err ) else -- connections was closed or fatal error - out_put( "server.lua: client ", ip, ":", clientport, " error: ", err ) + out_put( "server.lua: client ", ip, ":", tostring(clientport), " error: ", tostring(err) ) fatalerror = true disconnect( handler, err ) _ = handler and handler.close( ) -- cgit v1.2.3 From b6b9906c3c653935b55ad79ad4a2c41118f0a0e3 Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 2 Mar 2009 19:50:28 +0000 Subject: mod_muc: Don't bounce error replies in response to errors --- plugins/mod_muc.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_muc.lua b/plugins/mod_muc.lua index 83c35563..1f8d04e9 100644 --- a/plugins/mod_muc.lua +++ b/plugins/mod_muc.lua @@ -287,7 +287,7 @@ function handle_to_occupant(origin, stanza) -- PM, vCards, etc elseif type ~= 'result' then -- bad type origin.send(st.error_reply(stanza, "modify", "bad-request")); -- FIXME correct error? end - elseif not current_nick then -- not in room + elseif not current_nick and type ~= "error" then -- not in room origin.send(st.error_reply(stanza, "cancel", "not-acceptable")); elseif stanza.name == "message" and type == "groupchat" then -- groupchat messages not allowed in PM origin.send(st.error_reply(stanza, "modify", "bad-request")); -- cgit v1.2.3