Mercurial > prosody-modules
view mod_muc_limits/mod_muc_limits.lua @ 4895:2542fd80cd15
mod_turn_external: Fix type of config option (thanks mirux)
There was a separate boolean option to enable TLS before, but it was
merged with the port number option and it seems the typed API interface
got confused.
Backport of trunk rev aa7a8aa64d3f
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 15 Feb 2022 21:51:52 +0100 |
parents | 2b10e51d85a6 |
children | 731ba9400c10 |
line wrap: on
line source
local mod_muc = module:depends"muc"; local rooms = rawget(mod_muc, "rooms"); -- Old MUC API local jid_split, jid_bare = require "util.jid".split, require "util.jid".bare; local st = require "util.stanza"; local new_throttle = require "util.throttle".create; local t_insert, t_concat = table.insert, table.concat; local xmlns_muc = "http://jabber.org/protocol/muc"; local period = math.max(module:get_option_number("muc_event_rate", 0.5), 0); local burst = math.max(module:get_option_number("muc_burst_factor", 6), 1); local max_nick_length = module:get_option_number("muc_max_nick_length", 23); -- Default chosen through scientific methods local join_only = module:get_option_boolean("muc_limit_joins_only", false); local dropped_count = 0; local dropped_jids; local function log_dropped() module:log("warn", "Dropped %d stanzas from %d JIDs: %s", dropped_count, #dropped_jids, t_concat(dropped_jids, ", ")); dropped_count = 0; dropped_jids = nil; end local function handle_stanza(event) local origin, stanza = event.origin, event.stanza; if stanza.name == "presence" and stanza.attr.type == "unavailable" then -- Don't limit room leaving return; end local dest_room, dest_host, dest_nick = jid_split(stanza.attr.to); local room = event.room or rooms[dest_room.."@"..dest_host]; if not room then return; end local from_jid = stanza.attr.from; if room:get_affiliation(jid_bare(from_jid)) then module:log("debug", "Skipping stanza from affiliated user..."); return; elseif dest_nick and max_nick_length and stanza.name == "presence" and not room._occupants[stanza.attr.to] and #dest_nick > max_nick_length then module:log("debug", "Forbidding long (%d bytes) nick in %s", #dest_nick, dest_room) origin.send(st.error_reply(stanza, "modify", "policy-violation", "Your nick name is too long, please use a shorter one") :up():tag("x", { xmlns = xmlns_muc })); return true; end local throttle = room.throttle; if not room.throttle then throttle = new_throttle(period*burst, burst); room.throttle = throttle; end if not throttle:poll(1) then module:log("debug", "Dropping stanza for %s@%s from %s, over rate limit", dest_room, dest_host, from_jid); if not dropped_jids then dropped_jids = { [from_jid] = true, from_jid }; module:add_timer(5, log_dropped); elseif not dropped_jids[from_jid] then dropped_jids[from_jid] = true; t_insert(dropped_jids, from_jid); end dropped_count = dropped_count + 1; if stanza.attr.type == "error" then -- We don't want to bounce errors return true; end local reply = st.error_reply(stanza, "wait", "policy-violation", "The room is currently overactive, please try again later"); local body = stanza:get_child_text("body"); if body then reply:up():tag("body"):text(body):up(); end local x = stanza:get_child("x", xmlns_muc); if x then reply:add_child(st.clone(x)); end origin.send(reply); return true; end end if rooms then function module.unload() for room_jid, room in pairs(rooms) do --luacheck: ignore 213/room_jid room.throttle = nil; end end module:hook("presence/full", handle_stanza, 501); if not join_only then module:hook("message/bare", handle_stanza, 501); module:hook("message/full", handle_stanza, 501); module:hook("presence/bare", handle_stanza, 501); end else module:hook("muc-occupant-pre-join", handle_stanza); if not join_only then module:hook("muc-occupant-pre-change", handle_stanza); module:hook("muc-occupant-groupchat", handle_stanza); end end