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

67 lines
2.3 KiB
Markdown

# 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