Mercurial > prosody-modules
comparison 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 |
| parents | 01e9465f8f80 |
| children | 241c061bb953 |
comparison
equal
deleted
inserted
replaced
| 1713:01e9465f8f80 | 1714:3d83f5337a73 |
|---|---|
| 5 -- COPYING file in the source package for more information. | 5 -- COPYING file in the source package for more information. |
| 6 | 6 |
| 7 -- This module manage namespace delegation, a way to delegate server features | 7 -- This module manage namespace delegation, a way to delegate server features |
| 8 -- to an external entity/component. Only the admin mode is implemented so far | 8 -- to an external entity/component. Only the admin mode is implemented so far |
| 9 | 9 |
| 10 -- TODO: client mode, managing entity error handling | 10 -- TODO: client mode, managing entity error handling, disco extensions (XEP-0128) |
| 11 | 11 |
| 12 local jid = require("util/jid") | 12 local jid = require("util/jid") |
| 13 local st = require("util/stanza") | 13 local st = require("util/stanza") |
| 14 local set = require("util/set") | 14 local set = require("util/set") |
| 15 | 15 |
| 27 local _FORWARDED_NS = 'urn:xmpp:forward:0' | 27 local _FORWARDED_NS = 'urn:xmpp:forward:0' |
| 28 local _DISCO_NS = 'http://jabber.org/protocol/disco#info' | 28 local _DISCO_NS = 'http://jabber.org/protocol/disco#info' |
| 29 local _ORI_ID_PREFIX = "IQ_RESULT_" | 29 local _ORI_ID_PREFIX = "IQ_RESULT_" |
| 30 | 30 |
| 31 local _MAIN_SEP = '::' | 31 local _MAIN_SEP = '::' |
| 32 --local _BARE_SEP = ':bare:' | 32 local _BARE_SEP = ':bare:' |
| 33 local _MAIN_PREFIX = _DELEGATION_NS.._MAIN_SEP | |
| 34 local _BARE_PREFIX = _DELEGATION_NS.._BARE_SEP | |
| 35 local _PREFIXES = {_MAIN_PREFIX, _BARE_PREFIX} | |
| 33 | 36 |
| 34 local disco_nest | 37 local disco_nest |
| 35 | 38 |
| 36 module:log("debug", "Loading namespace delegation module "); | 39 module:log("debug", "Loading namespace delegation module "); |
| 37 | |
| 38 | 40 |
| 39 --> Configuration management <-- | 41 --> Configuration management <-- |
| 40 | 42 |
| 41 local ns_delegations = module:get_option("delegations", {}) | 43 local ns_delegations = module:get_option("delegations", {}) |
| 42 | 44 |
| 295 module:handle_items("identity", identity_added, function(_) end, false) | 297 module:handle_items("identity", identity_added, function(_) end, false) |
| 296 | 298 |
| 297 | 299 |
| 298 -- managing entity features/identities collection | 300 -- managing entity features/identities collection |
| 299 | 301 |
| 300 local disco_main_error | 302 local disco_error |
| 301 | 303 local bare_features = set.new() |
| 302 local function disco_main_result(event) | 304 local bare_identities = {} |
| 305 | |
| 306 local function disco_result(event) | |
| 307 -- parse result from disco nesting request | |
| 308 -- and fill module features/identities and bare_features/bare_identities accordingly | |
| 303 local session, stanza = event.origin, event.stanza | 309 local session, stanza = event.origin, event.stanza |
| 304 if stanza.attr.to ~= module.host then | 310 if stanza.attr.to ~= module.host then |
| 305 module:log("warn", 'Stanza result has "to" attribute not addressed to current host, id conflict ?') | 311 module:log("warn", 'Stanza result has "to" attribute not addressed to current host, id conflict ?') |
| 306 return | 312 return |
| 307 end | 313 end |
| 308 module:unhook("iq-result/host/"..stanza.attr.id, disco_main_result) | 314 module:unhook("iq-result/host/"..stanza.attr.id, disco_result) |
| 309 module:unhook("iq-error/host/"..stanza.attr.id, disco_main_error) | 315 module:unhook("iq-error/host/"..stanza.attr.id, disco_error) |
| 310 local query = stanza:get_child("query", _DISCO_NS) | 316 local query = stanza:get_child("query", _DISCO_NS) |
| 311 if not query or not query.attr.node then | 317 if not query or not query.attr.node then |
| 312 session.send(st.error_reply(stanza, 'modify', 'not-acceptable')) | 318 session.send(st.error_reply(stanza, 'modify', 'not-acceptable')) |
| 313 return true | 319 return true |
| 314 end | 320 end |
| 315 -- local node = query.attr.node | 321 |
| 322 local node = query.attr.node | |
| 323 local main | |
| 324 | |
| 325 if string.sub(node, 1, #_MAIN_PREFIX) == _MAIN_PREFIX then | |
| 326 main=true | |
| 327 elseif string.sub(node, 1, #_BARE_PREFIX) == _BARE_PREFIX then | |
| 328 main=false | |
| 329 else | |
| 330 module:log("warn", "Unexpected node: "..node) | |
| 331 session.send(st.error_reply(stanza, 'modify', 'not-acceptable')) | |
| 332 return true | |
| 333 end | |
| 334 | |
| 316 for feature in query:childtags("feature") do | 335 for feature in query:childtags("feature") do |
| 317 local namespace = feature.attr.var | 336 local namespace = feature.attr.var |
| 318 if not module:has_feature(namespace) then -- we avoid doubling features in case of disconnection/reconnexion | 337 if main then |
| 319 module:add_feature(namespace) | 338 if not module:has_feature(namespace) then -- we avoid doubling features in case of disconnection/reconnexion |
| 339 module:add_feature(namespace) | |
| 340 end | |
| 341 else | |
| 342 bare_features:add(namespace) | |
| 320 end | 343 end |
| 321 end | 344 end |
| 322 for identity in query:childtags("identity") do | 345 for identity in query:childtags("identity") do |
| 323 local category, type_, name = identity.attr.category, identity.attr.type, identity.attr.name | 346 local category, type_, name = identity.attr.category, identity.attr.type, identity.attr.name |
| 324 if not module:has_identity(category, type_, name) then | 347 if main then |
| 325 module:add_identity(category, type_, name) | 348 if not module:has_identity(category, type_, name) then |
| 326 end | 349 module:add_identity(category, type_, name) |
| 327 end | 350 end |
| 328 end | 351 else |
| 329 | 352 local found=false |
| 330 function disco_main_error(event) | 353 for _, item in ipairs(bare_identities) do |
| 354 if item.category == category and item.type == type_ and item.name == name then | |
| 355 found=true | |
| 356 break | |
| 357 end | |
| 358 end | |
| 359 if not found then | |
| 360 table.insert(bare_identities, {category=category, type=type_, name=name}) | |
| 361 end | |
| 362 end | |
| 363 end | |
| 364 end | |
| 365 | |
| 366 function disco_error(event) | |
| 331 local stanza = event.stanza | 367 local stanza = event.stanza |
| 332 if stanza.attr.to ~= module.host then | 368 if stanza.attr.to ~= module.host then |
| 333 module:log("warn", 'Stanza result has "to" attribute not addressed to current host, id conflict ?') | 369 module:log("warn", 'Stanza result has "to" attribute not addressed to current host, id conflict ?') |
| 334 return | 370 return |
| 335 end | 371 end |
| 336 module:unhook("iq-result/host/"..stanza.attr.id, disco_main_result) | 372 module:unhook("iq-result/host/"..stanza.attr.id, disco_result) |
| 337 module:unhook("iq-error/host/"..stanza.attr.id, disco_main_error) | 373 module:unhook("iq-error/host/"..stanza.attr.id, disco_error) |
| 338 module:log("warn", "Got an error while requesting disco for nesting to "..stanza.attr.from) | 374 module:log("warn", "Got an error while requesting disco for nesting to "..stanza.attr.from) |
| 339 module:log("warn", "Ignoring disco nesting") | 375 module:log("warn", "Ignoring disco nesting") |
| 340 end | 376 end |
| 341 | 377 |
| 342 function disco_nest(namespace, entity_jid) | 378 function disco_nest(namespace, entity_jid) |
| 343 local main_node = _DELEGATION_NS.._MAIN_SEP..namespace | 379 for _, prefix in ipairs(_PREFIXES) do |
| 344 -- local bare_node = _DELEGATION_NS.._BARE_SEP..namespace | 380 local node = prefix..namespace |
| 345 | 381 |
| 346 local iq = st.iq({from=module.host, to=entity_jid, type='get'}) | 382 local iq = st.iq({from=module.host, to=entity_jid, type='get'}) |
| 347 :tag('query', {xmlns=_DISCO_NS, node=main_node}) | 383 :tag('query', {xmlns=_DISCO_NS, node=node}) |
| 348 | 384 |
| 349 local iq_id = iq.attr.id | 385 local iq_id = iq.attr.id |
| 350 | 386 |
| 351 module:hook("iq-result/host/"..iq_id, disco_main_result) | 387 module:hook("iq-result/host/"..iq_id, disco_result) |
| 352 module:hook("iq-error/host/"..iq_id, disco_main_error) | 388 module:hook("iq-error/host/"..iq_id, disco_error) |
| 353 module:send(iq) | 389 module:send(iq) |
| 390 end | |
| 354 end | 391 end |
| 355 | 392 |
| 356 -- disco to bare jids special case | 393 -- disco to bare jids special case |
| 357 | 394 |
| 358 module:hook("account-disco-info", function(event) | 395 module:hook("account-disco-info", function(event) |
| 380 end | 417 end |
| 381 end | 418 end |
| 382 end | 419 end |
| 383 return child | 420 return child |
| 384 end) | 421 end) |
| 422 for feature in bare_features:items() do | |
| 423 reply:tag('feature', {var=feature}):up(); | |
| 424 end | |
| 425 for _, item in ipairs(bare_identities) do | |
| 426 reply:tag('identity', {category=item.category, type=item.type, name=item.name}):up(); | |
| 427 end | |
| 428 | |
| 385 end, -2^32); | 429 end, -2^32); |
