Files
bouncer/PROJECT.md
user 8cc57a7af4 feat: multi-network namespace multiplexing
Multiplex all networks onto a single client connection using /network
suffixes on channels and nicks. PASS is now just the password (no
network prefix). Channels appear as #channel/network, foreign nicks as
nick/network, own nicks stay bare.

New namespace.py module with pure encode/decode functions. Router
tracks clients globally (not per-network), namespaces messages before
delivery. Client attaches to all networks on connect, sends synthetic
JOIN/TOPIC/NAMES for every channel across all networks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:03:58 +01:00

2.3 KiB

Project: bouncer

Purpose

IRC bouncer that maintains persistent connections to IRC servers through a SOCKS5 proxy, allowing IRC clients to connect/disconnect while keeping the session alive and replaying missed messages.

Architecture

IRC Client(s) --> [bouncer:6667] --> Router --> [SOCKS5:1080] --> IRC Server(s)
                                       |
                                    Backlog
                                   (SQLite)

Connection State Machine

DISCONNECTED -> CONNECTING -> REGISTERING -> PROBATION (15s) -> READY
                    |              |              |
                    '--------------+--------------'
                         (failure = backoff + retry)
  • CONNECTING: SOCKS5 + optional TLS handshake
  • REGISTERING: Random nick/user/realname sent to server
  • PROBATION: 15s window to detect K-lines before exposing real identity
  • READY: Configured nick set, channels joined, clients served

Components

Module Responsibility
irc.py IRC protocol parser/formatter (RFC 2812 subset)
config.py TOML configuration loading and validation
namespace.py /network suffix encode/decode for multi-network multiplexing
proxy.py SOCKS5 async connector with local DNS + multi-IP failover
network.py Server connection state machine, stealth registration
server.py TCP listener accepting IRC client connections
client.py Per-client session, PASS/NICK/USER handshake, multi-network attach
router.py Namespaced message routing between clients and networks
backlog.py SQLite message storage and replay

Key Decisions

  • asyncio: single-threaded async for all I/O
  • python-socks: async SOCKS5 proxy support
  • aiosqlite: non-blocking SQLite for backlog
  • No IRC library: manual protocol handling (IRC is line-based)
  • Markov nicks: English bigram frequencies for pronounceable random nicks
  • Local DNS: resolve before SOCKS5 to handle proxies without DNS support
  • Multi-IP: try all resolved addresses, skip unreachable exit IPs

Dependencies

Package Version Purpose
python-socks[asyncio] >=2.4 SOCKS5 proxy
aiosqlite >=0.19 Async SQLite

Requirements

  • Python 3.10+
  • SOCKS5 proxy on 127.0.0.1:1080