Diff

mod_delegation/mod_delegation.lua @ 1714:3d83f5337a73

mod_delegation: disco info request on bare jid is now managed
author Goffi <goffi@goffi.org>
date Fri, 17 Apr 2015 21:07:05 +0200
parent 1713:01e9465f8f80
child 1715:241c061bb953
line wrap: on
line diff
--- 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);