# 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