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;