comparison mod_delegation/mod_delegation.lua @ 1709:59ba224bf145

mod_delegation: XEP-0355 implementation, first draft (configuration management + delegations advertising)
author Goffi <goffi@goffi.org>
date Fri, 17 Apr 2015 21:02:22 +0200
parents
children b68eed25b880
comparison
equal deleted inserted replaced
1708:ad7afcf86131 1709:59ba224bf145
1 -- XEP-0355 (Namespace Delegation)
2 -- Copyright (C) 2015 Jérôme Poisson
3 --
4 -- This module is MIT/X11 licensed. Please see the
5 -- COPYING file in the source package for more information.
6
7
8 local jid = require("util/jid")
9 local st = require("util/stanza")
10 local set = require("util/set")
11
12 local delegation_session = module:shared("/*/delegation/session")
13
14 if delegation_session.connected_cb == nil then
15 -- set used to have connected event listeners
16 -- which allow a host to react on events from
17 -- other hosts
18 delegation_session.connected_cb = set.new()
19 end
20 local connected_cb = delegation_session.connected_cb
21
22 local _DELEGATION_NS = 'urn:xmpp:delegation:1'
23 -- local _FORWARDED_NS = 'urn:xmpp:forward:0'
24
25
26 module:log("debug", "Loading namespace delegation module ");
27
28
29 --> Configuration management <--
30
31 local ns_delegations = module:get_option("delegations", {})
32
33 local jid2ns = {}
34 for namespace, config in pairs(ns_delegations) do
35 -- "connected" contain the full jid of connected managing entity
36 config.connected = nil
37 if config.jid then
38 if jid2ns[config.jid] == nil then
39 jid2ns[config.jid] = {}
40 end
41 jid2ns[config.jid][namespace] = config
42 else
43 module:log("warn", "Ignoring delegation for %s: no jid specified", tostring(namespace))
44 ns_delegations[namespace] = nil
45 end
46 end
47
48
49 local function advertise_delegations(session, to_jid)
50 -- send <message/> stanza to advertise delegations
51 -- as expained in § 4.2
52 local message = st.message({from=module.host, to=to_jid})
53 :tag("delegation", {xmlns=_DELEGATION_NS})
54
55 -- we need to check if a delegation is granted because the configuration
56 -- can be complicated if some delegations are granted to bare jid
57 -- and other to full jids, and several resources are connected.
58 local have_delegation = false
59
60 for namespace, config in pairs(jid2ns[to_jid]) do
61 if config.connected == to_jid then
62 have_delegation = true
63 message:tag("delegated", {namespace=namespace})
64 if type(config.filtering) == "table" then
65 for _, attribute in pairs(config.filtering) do
66 message:tag("attribute", {name=attribute}):up()
67 end
68 message:up()
69 end
70 end
71 end
72
73 if have_delegation then
74 session.send(message)
75 end
76 end
77
78 local function set_connected(entity_jid)
79 -- set the "connected" key for all namespace managed by entity_jid
80 -- if the namespace has already a connected entity, ignore the new one
81 local function set_config(jid_)
82 for _, config in pairs(jid2ns[jid_]) do
83 if config.connected == nil then
84 config.connected = entity_jid
85 end
86 end
87 end
88 local bare_jid = jid.bare(entity_jid)
89 set_config(bare_jid)
90 -- We can have a bare jid of a full jid specified in configuration
91 -- so we try our luck with both (first connected resource will
92 -- manage the namespaces in case of bare jid)
93 if bare_jid ~= entity_jid then
94 set_config(entity_jid)
95 jid2ns[entity_jid] = jid2ns[bare_jid]
96 end
97 end
98
99 local function on_presence(event)
100 local session = event.origin
101 local bare_jid = jid.bare(session.full_jid)
102
103 if jid2ns[bare_jid] or jid2ns[session.full_jid] then
104 set_connected(session.full_jid)
105 advertise_delegations(session, session.full_jid)
106 end
107 end
108
109 local function on_component_connected(event)
110 -- method called by the module loaded by the component
111 -- /!\ the event come from the component host,
112 -- not from the host of this module
113 local session = event.session
114 local bare_jid = jid.join(session.username, session.host)
115
116 local jid_delegations = jid2ns[bare_jid]
117 if jid_delegations ~= nil then
118 set_connected(bare_jid)
119 advertise_delegations(session, bare_jid)
120 end
121 end
122
123 local function on_component_auth(event)
124 -- react to component-authenticated event from this host
125 -- and call the on_connected methods from all other hosts
126 -- needed for the component to get delegations advertising
127 for callback in connected_cb:items() do
128 callback(event)
129 end
130 end
131
132 connected_cb:add(on_component_connected)
133 module:hook('component-authenticated', on_component_auth)
134 module:hook('presence/initial', on_presence)