# HG changeset patch # User Goffi # Date 1429297625 -7200 # Node ID 3d83f5337a73df78320ab5a363041790c1ec19e6 # Parent 01e9465f8f8054d5060128ec4fc7c2c13ee61f1d mod_delegation: disco info request on bare jid is now managed diff -r 01e9465f8f80 -r 3d83f5337a73 mod_delegation/mod_delegation.lua --- a/mod_delegation/mod_delegation.lua Fri Apr 17 21:06:51 2015 +0200 +++ b/mod_delegation/mod_delegation.lua Fri Apr 17 21:07:05 2015 +0200 @@ -7,7 +7,7 @@ -- This module manage namespace delegation, a way to delegate server features -- to an external entity/component. Only the admin mode is implemented so far --- TODO: client mode, managing entity error handling +-- TODO: client mode, managing entity error handling, disco extensions (XEP-0128) local jid = require("util/jid") local st = require("util/stanza") @@ -29,13 +29,15 @@ local _ORI_ID_PREFIX = "IQ_RESULT_" local _MAIN_SEP = '::' ---local _BARE_SEP = ':bare:' +local _BARE_SEP = ':bare:' +local _MAIN_PREFIX = _DELEGATION_NS.._MAIN_SEP +local _BARE_PREFIX = _DELEGATION_NS.._BARE_SEP +local _PREFIXES = {_MAIN_PREFIX, _BARE_PREFIX} local disco_nest module:log("debug", "Loading namespace delegation module "); - --> Configuration management <-- local ns_delegations = module:get_option("delegations", {}) @@ -297,60 +299,95 @@ -- managing entity features/identities collection -local disco_main_error +local disco_error +local bare_features = set.new() +local bare_identities = {} -local function disco_main_result(event) +local function disco_result(event) + -- parse result from disco nesting request + -- and fill module features/identities and bare_features/bare_identities accordingly local session, stanza = event.origin, event.stanza if stanza.attr.to ~= module.host then module:log("warn", 'Stanza result has "to" attribute not addressed to current host, id conflict ?') return end - module:unhook("iq-result/host/"..stanza.attr.id, disco_main_result) - module:unhook("iq-error/host/"..stanza.attr.id, disco_main_error) + module:unhook("iq-result/host/"..stanza.attr.id, disco_result) + module:unhook("iq-error/host/"..stanza.attr.id, disco_error) local query = stanza:get_child("query", _DISCO_NS) if not query or not query.attr.node then session.send(st.error_reply(stanza, 'modify', 'not-acceptable')) return true end - -- local node = query.attr.node + + local node = query.attr.node + local main + + if string.sub(node, 1, #_MAIN_PREFIX) == _MAIN_PREFIX then + main=true + elseif string.sub(node, 1, #_BARE_PREFIX) == _BARE_PREFIX then + main=false + else + module:log("warn", "Unexpected node: "..node) + session.send(st.error_reply(stanza, 'modify', 'not-acceptable')) + return true + end + for feature in query:childtags("feature") do local namespace = feature.attr.var - if not module:has_feature(namespace) then -- we avoid doubling features in case of disconnection/reconnexion - module:add_feature(namespace) + if main then + if not module:has_feature(namespace) then -- we avoid doubling features in case of disconnection/reconnexion + module:add_feature(namespace) + end + else + bare_features:add(namespace) end end for identity in query:childtags("identity") do local category, type_, name = identity.attr.category, identity.attr.type, identity.attr.name - if not module:has_identity(category, type_, name) then - module:add_identity(category, type_, name) + if main then + if not module:has_identity(category, type_, name) then + module:add_identity(category, type_, name) + end + else + local found=false + for _, item in ipairs(bare_identities) do + if item.category == category and item.type == type_ and item.name == name then + found=true + break + end + end + if not found then + table.insert(bare_identities, {category=category, type=type_, name=name}) + end end end end -function disco_main_error(event) +function disco_error(event) local stanza = event.stanza if stanza.attr.to ~= module.host then module:log("warn", 'Stanza result has "to" attribute not addressed to current host, id conflict ?') return end - module:unhook("iq-result/host/"..stanza.attr.id, disco_main_result) - module:unhook("iq-error/host/"..stanza.attr.id, disco_main_error) + module:unhook("iq-result/host/"..stanza.attr.id, disco_result) + module:unhook("iq-error/host/"..stanza.attr.id, disco_error) module:log("warn", "Got an error while requesting disco for nesting to "..stanza.attr.from) module:log("warn", "Ignoring disco nesting") end function disco_nest(namespace, entity_jid) - local main_node = _DELEGATION_NS.._MAIN_SEP..namespace - -- local bare_node = _DELEGATION_NS.._BARE_SEP..namespace + for _, prefix in ipairs(_PREFIXES) do + local node = prefix..namespace - local iq = st.iq({from=module.host, to=entity_jid, type='get'}) - :tag('query', {xmlns=_DISCO_NS, node=main_node}) + local iq = st.iq({from=module.host, to=entity_jid, type='get'}) + :tag('query', {xmlns=_DISCO_NS, node=node}) - local iq_id = iq.attr.id + local iq_id = iq.attr.id - module:hook("iq-result/host/"..iq_id, disco_main_result) - module:hook("iq-error/host/"..iq_id, disco_main_error) - module:send(iq) + module:hook("iq-result/host/"..iq_id, disco_result) + module:hook("iq-error/host/"..iq_id, disco_error) + module:send(iq) + end end -- disco to bare jids special case @@ -382,4 +419,11 @@ end return child end) + for feature in bare_features:items() do + reply:tag('feature', {var=feature}):up(); + end + for _, item in ipairs(bare_identities) do + reply:tag('identity', {category=item.category, type=item.type, name=item.name}):up(); + end + end, -2^32);