Skip to content

Batch autojoin channels into comma-separated JOIN commands#283

Open
kofany wants to merge 1 commit intoaatxe:developfrom
kofany:fix/develop/batch-autojoin-channels
Open

Batch autojoin channels into comma-separated JOIN commands#283
kofany wants to merge 1 commit intoaatxe:developfrom
kofany:fix/develop/batch-autojoin-channels

Conversation

@kofany
Copy link
Copy Markdown

@kofany kofany commented Mar 8, 2026

Problem

When connecting to a server with multiple autojoin channels configured, the client sends individual JOIN commands for each channel:

JOIN #channel1
JOIN #channel2
JOIN #channel3
...

For a typical configuration with 20 channels, this generates 20 separate messages. With any form of server-side or client-side flood protection, this introduces significant delay — each JOIN carries a penalty (~2s per command on most IRCd implementations following RFC 2813 §5.8), resulting in ~34 seconds to complete autojoin for 20 channels.

Solution

Batch autojoin channels into comma-separated JOIN commands per RFC 2812 §3.2.1:

JOIN #channel1,#channel2,#channel3,...,#channelN

Key design decisions

  1. Keyed channels placed first — RFC 2812 specifies positional key matching (JOIN #a,#b,#c key1,key2 maps key1→#a, key2→#b, #c has no key). Channels with keys must precede keyless channels within each batch to maintain correct alignment.

  2. Respects 512-byte IRC line limit — The batching algorithm splits into multiple JOIN commands when adding another channel would exceed 512 bytes (including JOIN , commas, the space-separated keylist, and \r\n). This is the only real constraint — RFC 2812 does not impose a limit on the number of channels per JOIN.

  3. Preserves config order within groups — Keyed and keyless channels each maintain their original configuration order.

  4. Re-joined channels also batched — Previously joined channels (tracked in chanlists) that aren't in the config are also batched when re-joining after reconnect.

Example

Config with channels [#public, #secret, #general] where #secret has key mypass:

Before: JOIN #public\r\n + JOIN #secret mypass\r\n + JOIN #general\r\n (3 messages)
After: JOIN #secret,#public,#general mypass\r\n (1 message)

Testing

  • All 73 existing tests updated and passing
  • 6 new unit tests for build_batched_joins:
    • All keyless channels → single batch
    • Keyed channels placed first with correct key ordering
    • Multiple keyed channels with positional key alignment
    • Empty channel list → no batches
    • Long channel names exceeding 512-byte limit → correct splitting
    • Keyed channels with keys exceeding limit → correct splitting with keys preserved
  • cargo test --no-default-features
  • cargo clippy --all-targets --all-features — no new warnings
  • cargo fmt --check
  • git diff --check — no whitespace issues

Instead of sending individual JOIN per channel on connect, batch channels
into comma-separated JOIN commands (RFC 2812 §3.2.1). Keyed channels are
placed first in each batch so positional key matching works correctly.
Commands are split into multiple JOINs when they would exceed the 512-byte
IRC line length limit.

This reduces the number of messages sent during autojoin, which matters
especially with flood protection enabled — 20 individual JOINs would incur
~34s of penalty delay vs ~2s for a single batched JOIN.
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