Mercurial > prosody-modules
comparison mod_pubsub_serverinfo/mod_pubsub_serverinfo.lua @ 5808:2465d5191ae9
mod_pubsub_serverinfo: Consider sibling vhosts 'connected'
Prosody does not have s2s connections between vhosts. Multiple domains will therefor not show up as each-other 'remote domains'.
With this commit, the module considers vhosts permanently s2s-connected.
Additional debug logging has been added.
author | Guus der Kinderen <guus.der.kinderen@gmail.com> |
---|---|
date | Thu, 04 Jan 2024 15:14:19 +0100 |
parents | 55b99f593c3a |
children | a8cae8322b7c |
comparison
equal
deleted
inserted
replaced
5807:f08818b8b87d | 5808:2465d5191ae9 |
---|---|
120 -- mapped to a collection of remote domain names. De-duplicate all remote domain names by using | 120 -- mapped to a collection of remote domain names. De-duplicate all remote domain names by using |
121 -- them as an index in a table. | 121 -- them as an index in a table. |
122 local domains_by_host = {} | 122 local domains_by_host = {} |
123 for session, _ in pairs(prosody.incoming_s2s) do | 123 for session, _ in pairs(prosody.incoming_s2s) do |
124 if session ~= nil and session.from_host ~= nil and local_domain == session.to_host then | 124 if session ~= nil and session.from_host ~= nil and local_domain == session.to_host then |
125 module:log("debug", "Local host '%s' has remote '%s' (inbound)", session.to_host, session.from_host); | |
125 local sessions = domains_by_host[session.to_host] | 126 local sessions = domains_by_host[session.to_host] |
126 if sessions == nil then sessions = {} end; -- instantiate a new entry if none existed | 127 if sessions == nil then sessions = {} end; -- instantiate a new entry if none existed |
127 sessions[session.from_host] = true | 128 sessions[session.from_host] = true |
128 domains_by_host[session.to_host] = sessions | 129 domains_by_host[session.to_host] = sessions |
129 end | 130 end |
130 end | 131 end |
131 | 132 |
132 -- At an earlier stage, the code iterated voer all prosody.hosts - but that turned out to be to noisy. | 133 -- At an earlier stage, the code iterated over all prosody.hosts, trying to generate one pubsub item for all local hosts. That turned out to be |
134 -- to noisy. Instead, this code now creates an item that includes the local vhost only. It is assumed that this module will also be loaded for | |
135 -- other vhosts. Their data should then be published to distinct pub/sub services and nodes. | |
136 | |
133 -- for host, data in pairs(prosody.hosts) do | 137 -- for host, data in pairs(prosody.hosts) do |
134 local host = local_domain | 138 local host = local_domain |
135 local data = prosody.hosts[host] | 139 local data = prosody.hosts[host] |
136 if data ~= nil then | 140 if data ~= nil then |
137 local sessions = domains_by_host[host] | 141 local sessions = domains_by_host[host] |
138 if sessions == nil then sessions = {} end; -- instantiate a new entry if none existed | 142 if sessions == nil then sessions = {} end; -- instantiate a new entry if none existed |
139 if data.s2sout ~= nil then | 143 if data.s2sout ~= nil then |
140 for _, session in pairs(data.s2sout) do | 144 for _, session in pairs(data.s2sout) do |
141 if session.to_host ~= nil then | 145 if session.to_host ~= nil then |
146 module:log("debug", "Local host '%s' has remote '%s' (outbound)", host, session.to_host); | |
142 sessions[session.to_host] = true | 147 sessions[session.to_host] = true |
143 domains_by_host[host] = sessions | 148 domains_by_host[host] = sessions |
144 end | 149 end |
150 end | |
151 end | |
152 | |
153 -- When the instance of Prosody hosts more than one host, the other hosts can be thought of as having a 'permanent' s2s connection. | |
154 for host_name, host_info in pairs(prosody.hosts) do | |
155 if host ~= host_name and host_info.type ~= "component" then | |
156 module:log("debug", "Local host '%s' has remote '%s' (vhost)", host, host_name); | |
157 sessions[host_name] = true; | |
158 domains_by_host[host] = sessions | |
145 end | 159 end |
146 end | 160 end |
147 end | 161 end |
148 | 162 |
149 -- Build the publication stanza. | 163 -- Build the publication stanza. |
194 function does_opt_in(remoteDomain) | 208 function does_opt_in(remoteDomain) |
195 | 209 |
196 -- try to read answer from cache. | 210 -- try to read answer from cache. |
197 local cached_value = opt_in_cache[remoteDomain] | 211 local cached_value = opt_in_cache[remoteDomain] |
198 if cached_value ~= nil and os.difftime(cached_value.expires, os.time()) > 0 then | 212 if cached_value ~= nil and os.difftime(cached_value.expires, os.time()) > 0 then |
213 module:log("debug", "Opt-in status (from cache) for '%s': %s", remoteDomain, cached_value.opt_in) | |
199 return cached_value.opt_in; | 214 return cached_value.opt_in; |
200 end | 215 end |
201 | 216 |
202 -- TODO worry about not having multiple requests in flight to the same domain.cached_value | 217 -- TODO worry about not having multiple requests in flight to the same domain.cached_value |
203 | 218 |
204 -- Cache could not provide an answer. Perform service discovery. | 219 -- Cache could not provide an answer. Perform service discovery. |
220 module:log("debug", "No cached opt-in status for '%s': performing disco/info to determine opt-in.", remoteDomain) | |
205 local discoRequest = st.iq({ type = "get", to = remoteDomain, from = actor, id = new_id() }) | 221 local discoRequest = st.iq({ type = "get", to = remoteDomain, from = actor, id = new_id() }) |
206 :tag("query", { xmlns = "http://jabber.org/protocol/disco#info" }) | 222 :tag("query", { xmlns = "http://jabber.org/protocol/disco#info" }) |
207 | 223 |
208 module:send_iq(discoRequest):next( | 224 module:send_iq(discoRequest):next( |
209 function(response) | 225 function(response) |
210 if response.stanza ~= nil and response.stanza.attr.type == "result" then | 226 if response.stanza ~= nil and response.stanza.attr.type == "result" then |
211 local query = response.stanza:get_child("query", "http://jabber.org/protocol/disco#info") | 227 local query = response.stanza:get_child("query", "http://jabber.org/protocol/disco#info") |
212 if query ~= nil then | 228 if query ~= nil then |
213 for feature in query:childtags("feature", "http://jabber.org/protocol/disco#info") do | 229 for feature in query:childtags("feature", "http://jabber.org/protocol/disco#info") do |
230 module:log("debug", "Disco/info feature for '%s': %s", remoteDomain, feature) | |
214 if feature.attr.var == 'urn:xmpp:serverinfo:0' then | 231 if feature.attr.var == 'urn:xmpp:serverinfo:0' then |
232 module:log("debug", "Disco/info response included opt-in for '%s'", remoteDomain) | |
215 opt_in_cache[remoteDomain] = { | 233 opt_in_cache[remoteDomain] = { |
216 opt_in = true; | 234 opt_in = true; |
217 expires = os.time() + cache_ttl; | 235 expires = os.time() + cache_ttl; |
218 } | 236 } |
219 return; -- prevent 'false' to be cached, down below. | 237 return; -- prevent 'false' to be cached, down below. |
220 end | 238 end |
221 end | 239 end |
222 end | 240 end |
223 end | 241 end |
242 module:log("debug", "Disco/info response did not include opt-in for '%s'", remoteDomain) | |
224 opt_in_cache[remoteDomain] = { | 243 opt_in_cache[remoteDomain] = { |
225 opt_in = false; | 244 opt_in = false; |
226 expires = os.time() + cache_ttl; | 245 expires = os.time() + cache_ttl; |
227 } | 246 } |
228 end, | 247 end, |
229 function(response) | 248 function(response) |
249 module:log("debug", "An error occurred while performing a disco/info request to determine opt-in for '%s'", remoteDomain, response) | |
230 opt_in_cache[remoteDomain] = { | 250 opt_in_cache[remoteDomain] = { |
231 opt_in = false; | 251 opt_in = false; |
232 expires = os.time() + cache_ttl; | 252 expires = os.time() + cache_ttl; |
233 } | 253 } |
234 end | 254 end |