Comparison

core/moduleapi.lua @ 10061:5c71693c8345

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Mon, 08 Jul 2019 02:44:32 +0200
parent 9930:12a31296d63d
child 10213:ee62754b0233
comparison
equal deleted inserted replaced
10060:7a36b7ac309b 10061:5c71693c8345
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 self:unhook(iq.result_event, iq.result_handler);
378 self:unhook(iq.error_event, iq.error_handler);
379 end);
380 self._iq_cache = iq_cache;
381 end
382 return promise.new(function (resolve, reject)
383 local event_type;
384 if stanza.attr.from == self.host then
385 event_type = "host";
386 else -- assume bare since we can't hook full jids
387 event_type = "bare";
388 end
389 local result_event = "iq-result/"..event_type.."/"..stanza.attr.id;
390 local error_event = "iq-error/"..event_type.."/"..stanza.attr.id;
391 local cache_key = event_type.."/"..stanza.attr.id;
392
393 local function result_handler(event)
394 if event.stanza.attr.from == stanza.attr.to then
395 resolve(event);
396 return true;
397 end
398 end
399
400 local function error_handler(event)
401 if event.stanza.attr.from == stanza.attr.to then
402 reject(errutil.from_stanza(event.stanza), event);
403 return true;
404 end
405 end
406
407 if iq_cache:get(cache_key) then
408 reject(errutil.new({
409 type = "modify", condition = "conflict",
410 text = "iq stanza id attribute already used",
411 }));
412 return;
413 end
414
415 self:hook(result_event, result_handler);
416 self:hook(error_event, error_handler);
417
418 local timeout_handle = self:add_timer(timeout or 120, function ()
419 reject(errutil.new({
420 type = "wait", condition = "remote-server-timeout",
421 text = "IQ stanza timed out",
422 }));
423 self:unhook(result_event, result_handler);
424 self:unhook(error_event, error_handler);
425 iq_cache:set(cache_key, nil);
426 end);
427
428 local ok = iq_cache:set(cache_key, {
429 reject = reject, resolve = resolve,
430 timeout_handle = timeout_handle,
431 result_event = result_event, error_event = error_event,
432 result_handler = result_handler, error_handler = error_handler;
433 });
434
435 if not ok then
436 reject(errutil.new({
437 type = "wait", condition = "internal-server-error",
438 text = "Could not store IQ tracking data"
439 }));
440 return;
441 end
442
443 self:send(stanza, origin);
444 end);
445 end
446
364 function api:broadcast(jids, stanza, iter) 447 function api:broadcast(jids, stanza, iter)
365 for jid in (iter or it.values)(jids) do 448 for jid in (iter or it.values)(jids) do
366 local new_stanza = st.clone(stanza); 449 local new_stanza = st.clone(stanza);
367 new_stanza.attr.to = jid; 450 new_stanza.attr.to = jid;
368 self:send(new_stanza); 451 self:send(new_stanza);
430 513
431 function api:measure_global_event(event_name, stat_name) 514 function api:measure_global_event(event_name, stat_name)
432 return self:measure_object_event(prosody.events.wrappers, event_name, stat_name); 515 return self:measure_object_event(prosody.events.wrappers, event_name, stat_name);
433 end 516 end
434 517
518 local status_priorities = { error = 3, warn = 2, info = 1, core = 0 };
519
520 function api:set_status(status_type, status_message, override)
521 local priority = status_priorities[status_type];
522 if not priority then
523 self:log("error", "set_status: Invalid status type '%s', assuming 'info'");
524 status_type, priority = "info", status_priorities.info;
525 end
526 local current_priority = status_priorities[self.status_type] or 0;
527 -- By default an 'error' status can only be overwritten by another 'error' status
528 if (current_priority >= status_priorities.error and priority < current_priority and override ~= true)
529 or (override == false and current_priority > priority) then
530 self:log("debug", "moduleapi: ignoring status [prio %d override %s]: %s", priority, override, status_message);
531 return;
532 end
533 self.status_type, self.status_message, self.status_time = status_type, status_message, time_now();
534 self:fire_event("module-status/updated", { name = self.name });
535 end
536
537 function api:log_status(level, msg, ...)
538 self:set_status(level, format(msg, ...));
539 return self:log(level, msg, ...);
540 end
541
542 function api:get_status()
543 return self.status_type, self.status_message, self.status_time;
544 end
545
435 return api; 546 return api;