Software /
code /
prosody
Comparison
core/moduleapi.lua @ 10411:db2a06b9ff98
Merge 0.11->trunk
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 16 Nov 2019 16:52:31 +0100 |
parent | 10214:f864e685e618 |
child | 10575:5cf8e96575b3 |
comparison
equal
deleted
inserted
replaced
10410:659b577f280c | 10411:db2a06b9ff98 |
---|---|
12 local logger = require "util.logger"; | 12 local logger = require "util.logger"; |
13 local pluginloader = require "util.pluginloader"; | 13 local pluginloader = require "util.pluginloader"; |
14 local timer = require "util.timer"; | 14 local timer = require "util.timer"; |
15 local resolve_relative_path = require"util.paths".resolve_relative_path; | 15 local resolve_relative_path = require"util.paths".resolve_relative_path; |
16 local st = require "util.stanza"; | 16 local st = require "util.stanza"; |
17 local cache = require "util.cache"; | |
18 local errutil = require "util.error"; | |
19 local promise = require "util.promise"; | |
20 local time_now = require "util.time".now; | |
21 local format = require "util.format".format; | |
17 | 22 |
18 local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; | 23 local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat; |
19 local error, setmetatable, type = error, setmetatable, type; | 24 local error, setmetatable, type = error, setmetatable, type; |
20 local ipairs, pairs, select = ipairs, pairs, select; | 25 local ipairs, pairs, select = ipairs, pairs, select; |
21 local tonumber, tostring = tonumber, tostring; | 26 local tonumber, tostring = tonumber, tostring; |
22 local require = require; | 27 local require = require; |
23 local pack = table.pack or function(...) return {n=select("#",...), ...}; end -- table.pack is only in 5.2 | 28 local pack = table.pack or require "util.table".pack; -- table.pack is only in 5.2 |
24 local unpack = table.unpack or unpack; --luacheck: ignore 113 -- renamed in 5.2 | 29 local unpack = table.unpack or unpack; --luacheck: ignore 113 -- renamed in 5.2 |
25 | 30 |
26 local prosody = prosody; | 31 local prosody = prosody; |
27 local hosts = prosody.hosts; | 32 local hosts = prosody.hosts; |
28 | 33 |
359 | 364 |
360 function api:send(stanza, origin) | 365 function api:send(stanza, origin) |
361 return core_post_stanza(origin or hosts[self.host], stanza); | 366 return core_post_stanza(origin or hosts[self.host], stanza); |
362 end | 367 end |
363 | 368 |
369 function api:send_iq(stanza, origin, timeout) | |
370 local iq_cache = self._iq_cache; | |
371 if not iq_cache then | |
372 iq_cache = cache.new(256, function (_, iq) | |
373 iq.reject(errutil.new({ | |
374 type = "wait", condition = "resource-constraint", | |
375 text = "evicted from iq tracking cache" | |
376 })); | |
377 end); | |
378 self._iq_cache = iq_cache; | |
379 end | |
380 | |
381 local event_type; | |
382 if stanza.attr.from == self.host then | |
383 event_type = "host"; | |
384 else -- assume bare since we can't hook full jids | |
385 event_type = "bare"; | |
386 end | |
387 local result_event = "iq-result/"..event_type.."/"..stanza.attr.id; | |
388 local error_event = "iq-error/"..event_type.."/"..stanza.attr.id; | |
389 local cache_key = event_type.."/"..stanza.attr.id; | |
390 | |
391 local p = promise.new(function (resolve, reject) | |
392 local function result_handler(event) | |
393 if event.stanza.attr.from == stanza.attr.to then | |
394 resolve(event); | |
395 return true; | |
396 end | |
397 end | |
398 | |
399 local function error_handler(event) | |
400 if event.stanza.attr.from == stanza.attr.to then | |
401 reject(errutil.from_stanza(event.stanza), event); | |
402 return true; | |
403 end | |
404 end | |
405 | |
406 if iq_cache:get(cache_key) then | |
407 reject(errutil.new({ | |
408 type = "modify", condition = "conflict", | |
409 text = "IQ stanza id attribute already used", | |
410 })); | |
411 return; | |
412 end | |
413 | |
414 self:hook(result_event, result_handler); | |
415 self:hook(error_event, error_handler); | |
416 | |
417 local timeout_handle = self:add_timer(timeout or 120, function () | |
418 reject(errutil.new({ | |
419 type = "wait", condition = "remote-server-timeout", | |
420 text = "IQ stanza timed out", | |
421 })); | |
422 end); | |
423 | |
424 local ok = iq_cache:set(cache_key, { | |
425 reject = reject, resolve = resolve, | |
426 timeout_handle = timeout_handle, | |
427 result_handler = result_handler, error_handler = error_handler; | |
428 }); | |
429 | |
430 if not ok then | |
431 reject(errutil.new({ | |
432 type = "wait", condition = "internal-server-error", | |
433 text = "Could not store IQ tracking data" | |
434 })); | |
435 return; | |
436 end | |
437 | |
438 self:send(stanza, origin); | |
439 end); | |
440 | |
441 p:finally(function () | |
442 local iq = iq_cache:get(cache_key); | |
443 if iq then | |
444 self:unhook(result_event, iq.result_handler); | |
445 self:unhook(error_event, iq.error_handler); | |
446 iq.timeout_handle:stop(); | |
447 iq_cache:set(cache_key, nil); | |
448 end | |
449 end); | |
450 | |
451 return p; | |
452 end | |
453 | |
364 function api:broadcast(jids, stanza, iter) | 454 function api:broadcast(jids, stanza, iter) |
365 for jid in (iter or it.values)(jids) do | 455 for jid in (iter or it.values)(jids) do |
366 local new_stanza = st.clone(stanza); | 456 local new_stanza = st.clone(stanza); |
367 new_stanza.attr.to = jid; | 457 new_stanza.attr.to = jid; |
368 self:send(new_stanza); | 458 self:send(new_stanza); |
430 | 520 |
431 function api:measure_global_event(event_name, stat_name) | 521 function api:measure_global_event(event_name, stat_name) |
432 return self:measure_object_event(prosody.events.wrappers, event_name, stat_name); | 522 return self:measure_object_event(prosody.events.wrappers, event_name, stat_name); |
433 end | 523 end |
434 | 524 |
525 local status_priorities = { error = 3, warn = 2, info = 1, core = 0 }; | |
526 | |
527 function api:set_status(status_type, status_message, override) | |
528 local priority = status_priorities[status_type]; | |
529 if not priority then | |
530 self:log("error", "set_status: Invalid status type '%s', assuming 'info'"); | |
531 status_type, priority = "info", status_priorities.info; | |
532 end | |
533 local current_priority = status_priorities[self.status_type] or 0; | |
534 -- By default an 'error' status can only be overwritten by another 'error' status | |
535 if (current_priority >= status_priorities.error and priority < current_priority and override ~= true) | |
536 or (override == false and current_priority > priority) then | |
537 self:log("debug", "moduleapi: ignoring status [prio %d override %s]: %s", priority, override, status_message); | |
538 return; | |
539 end | |
540 self.status_type, self.status_message, self.status_time = status_type, status_message, time_now(); | |
541 self:fire_event("module-status/updated", { name = self.name }); | |
542 end | |
543 | |
544 function api:log_status(level, msg, ...) | |
545 self:set_status(level, format(msg, ...)); | |
546 return self:log(level, msg, ...); | |
547 end | |
548 | |
549 function api:get_status() | |
550 return self.status_type, self.status_message, self.status_time; | |
551 end | |
552 | |
435 return api; | 553 return api; |