Skip to content

Implement penalty-based IRC flood protection (RFC 2813 §5.8)#284

Open
kofany wants to merge 4 commits intoaatxe:developfrom
kofany:feature/flood-penalty-throttle
Open

Implement penalty-based IRC flood protection (RFC 2813 §5.8)#284
kofany wants to merge 4 commits intoaatxe:developfrom
kofany:feature/flood-penalty-throttle

Conversation

@kofany
Copy link
Copy Markdown

@kofany kofany commented Mar 9, 2026

Summary

Adds penalty-based outgoing message throttling modeled after the IRCd flood detection formula (RFC 2813 §5.8), replacing the unimplemented burst_window_length / max_messages_in_burst config fields.

  • Penalty model: Each outgoing message incurs (1 + message_bytes / 100) * 1000ms + command_penalty_ms, matching the server-side calculation. Penalty drains in real-time at 1ms/1ms elapsed.
  • Configurable threshold: New flood_penalty_threshold config field (default 10,000ms / 10s). When accumulated penalty exceeds the threshold, messages are delayed. Set to 0 to disable.
  • Per-command costs: PONG/QUIT/PASS/CAP exempt (0ms), NICK (3s), PART (4s), WHO/LIST/NAMES without args (10s), WHOIS/WHOWAS (3s), INFO/MOTD/USERS (5s), PRIVMSG/NOTICE and others (2s).
  • Critical fix: Each message is flushed to TCP individually after its penalty delay. Without this, start_send only buffers into the codec — messages accumulate across delay cycles and burst on idle, causing Excess Flood disconnects.
  • Deprecation: burst_window_length and max_messages_in_burst marked #[deprecated] with guidance to use flood_penalty_threshold.
  • Tests: 12 unit tests covering command_penalty(), length_penalty(), and config defaults.
  • Example updated: repeater.rs migrated from deprecated fields to flood_penalty_threshold.

Commits

  1. 9257dff — Implement penalty-based IRC flood protection
  2. b02e137 — Improve flood penalty to match IRCd formula (RFC 2813 §5.8)
  3. 2d996b1 — Fix Excess Flood: flush each message to TCP after penalty delay
  4. fee0838 — Add unit tests for flood penalty and update deprecated example

Test plan

  • cargo test --lib — 79 tests pass (67 existing + 12 new)
  • cargo fmt --check — clean
  • cargo clippy --all-targets --all-features — no new warnings
  • Tested on live IRC network (20+ channels, WHO/MODE queries) — no Excess Flood

kofany and others added 4 commits March 8, 2026 12:06
Add command-aware flood throttling modeled after irssi and IRCd (RFC 2813
penalty model). Each outgoing command incurs a penalty cost that mirrors
the server's own flood detection: PRIVMSG/JOIN/NICK = 2000ms, WHO/WHOIS/
LIST = 4000ms, PONG/QUIT/CAP = 0ms. When accumulated penalty exceeds a
configurable threshold (default 10s), outgoing messages are delayed until
the penalty drains below the threshold at real-time rate.

New config field: flood_penalty_threshold (milliseconds, default 10000,
set to 0 to disable). Deprecates the unimplemented burst_window_length
and max_messages_in_burst fields.

Closes aatxe#190
Add message-length base cost: (1 + bytes/100) * 1000ms per message,
matching the server's own flood calculation. Fix per-command penalties
to closely mirror irc2.11 reference implementation:

- WHO/NAMES/LIST without args: 10s (was 4s)
- WHO/NAMES/LIST with args: 2s (was 4s)
- NICK: 3s (was 2s)
- PART: 4s (was 2s)
- WHOIS/WHOWAS: 3s (was 4s)
- INFO/MOTD/USERS: 5s (was 4s)
- PRIVMSG/NOTICE: 2s (unchanged)
- PONG/QUIT/CAP: 0s (unchanged, client-side exemption)

Without the length factor, rapid sends of long messages would trigger
the server's Excess Flood detection despite client-side throttling.
start_send only buffers into the codec — without poll_flush the data
never reaches the TCP socket. When many messages are delayed by the
penalty system, they accumulate in the codec buffer and burst all at
once when the stream goes idle, triggering Excess Flood on the IRCd.

Add poll_flush in two places:
1. After sending a delayed-buffered message — ensures it hits TCP
   before we loop back for more.
2. Before returning Pending for a new delay — ensures any messages
   start_send'd earlier in this poll cycle are flushed before sleeping.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 12 unit tests covering command_penalty(), length_penalty(), and
flood_penalty_threshold config defaults. Update repeater example to
use flood_penalty_threshold instead of deprecated burst fields.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant