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; |