diff --git a/README.md b/README.md index d9aacff..b631983 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,11 @@ handler objects, and modules hook lifecycle events. Design goals: for TLS and `mio` for the epoll socket engine), and lock-free (a single core thread owns all state). -> Status: early but capable. It boots, registers clients, speaks a large chunk of -> the IRC + IRCv3 protocol (see **What works**), and one reactor thread has served -> 5,000 concurrent connections in testing. Not battle-tested yet. +> Status: capable and broad. It speaks a large slice of the IRC + IRCv3 protocol +> — **100+ commands**, the full channel/user mode set, **28 IRCv3 capabilities**, +> and **~55 pluggable modules** — with server-to-server linking, a services +> interface, TLS, WebSocket, GeoIP and a JSON-RPC control plane. One reactor thread +> has served 5,000 concurrent connections in testing. Not battle-tested yet. ## Run it @@ -46,6 +48,19 @@ no cull list), an `Extensible` typemap instead of `void*` module data (freed automatically on drop), `&str` slices, and compiled-in trait objects instead of a fragile `.so` ABI. +### Why a raw reactor, not async? + +IRC is one big shared mutable graph (users, channels, the nick index), and almost +every command mutates it and then broadcasts. With one thread owning all of it, +handlers are plain `&mut Server` code — no locks, no `.await`, no `Send + 'static` +bounds. A multi-threaded async runtime would force that shared state behind +mutexes or an actor mailbox, and a channel broadcast is serialized anyway, so +you'd pay locking cost for parallelism the workload can't use. `mio` is the same +readiness layer async runtimes are built on, so you keep the C50k scaling without +the runtime. CPU-heavy or blocking work (DNS, TLS, outbound HTTP) is pushed to its +own threads; the network scales out by **linking servers**, not by adding cores to +one process. + ### The two extension points - **Commands** (`src/command.rs`, `src/coremods/`) — a handler declares `name`, @@ -59,34 +74,109 @@ fragile `.so` ABI. ## What works -- Registration (`CAP`/`NICK`/`USER`), `PING`/`PONG` with idle + registration - timeouts, welcome burst (001–005) + ISUPPORT. -- `JOIN`/`PART`/`NAMES`/`TOPIC`/`KICK`/`INVITE`, `PRIVMSG`/`NOTICE`/`TAGMSG`, - `NICK`, `WHO`/`WHOIS`/`WHOWAS`, `LIST`, `AWAY`, `QUIT`, `MOTD`/`LUSERS`. -- **Full mode set** as handler objects: prefixes `+qaohv`, lists `+beI`, and - `+klmntispzONCTcSRMGu` plus flood/rate modes `+f/+j/+F`, redirect `+L`, word - filter `+g`, and acting **extbans** `m:`/`c:`/`n:`. -- **IRC operators**: `OPER`/`KILL`/`WALLOPS`/`GLOBOPS`, `SAJOIN`/`SAPART`/`SANICK`/ - `SAMODE`/`SATOPIC`/`SAKICK`, `CHGHOST`/`CHGIDENT`/`SETHOST`/`SETIDENT`, - `KLINE`/`GLINE`/`ZLINE` + `STATS`, snomasks (`+s`), `DIE`/`RESTART`, and a - reload-safe **`REHASH`** (keeps the running config if the file can't be read, - and announces the reload to every connected user). -- **IRCv3**: `CAP` negotiation, `server-time`, `message-tags` + **`msgid`**, - `multi-prefix`, `away-notify`, `account-notify`, `extended-join`, `chghost`, - `userhost-in-names`, `echo-message`, `invite-notify`, `setname`, - `extended-monitor`, `SASL` (PLAIN, relayed to services), `WATCH`/`MONITOR`, - `SILENCE`, and `ACCEPT` + user `+g` **callerid** (only accepted users may PM you). -- **Reverse-DNS on connect**: the classic `*** Looking up your hostname...` - connection notices, backed by a *real* forward-confirmed PTR resolver written - from scratch over UDP (no DNS crate) — resolves clients to hostnames, off the - core thread, fail-safe to the IP. Configurable (`resolve_hosts`, - `use_resolved_host`). -- **TLS** (openssl) with `sslinfo`; keyed-SHA-256 host **cloaking** (`+x`); - **services-ready accounts** (`SVSLOGIN`/`SVSLOGOUT`, account-gated `+r/+R/+M`) - — the ircd is *ready* for an external services package, it is not one itself. -- **Server-to-server linking**: handshake, UID/FJOIN netburst, cross-server - users and channels, nick-collision handling, netsplit. -- An **antimixedutf8** anti-spam module (blocks mixed-script look-alike spam). +### Registration & session +- `CAP` negotiation, `NICK`/`USER`, `PING`/`PONG` with configurable idle + + registration timeouts, welcome burst (001–005) + ISUPPORT (optionally batched). +- `WEBIRC` (real client IP from a trusted web gateway), `conn_waitpong` (require a + PONG cookie before registering — filters bots), `autodrop` (silently drop + pre-registration HTTP scanners), configurable nick/channel length limits. + +### Channels +- `JOIN`/`PART`/`NAMES`/`TOPIC`/`KICK`/`INVITE`, plus `KNOCK`, `CYCLE`, `REMOVE`, + `UNINVITE`. +- Bans / excepts / invex, ban **redirect** (`+b mask$#chan`), and matching + + acting **extbans** (below). + +### Messaging +- `PRIVMSG`/`NOTICE`/`TAGMSG`, CTCP handling, `echo-message`, per-message `msgid`, + `server-time`, `account-tag`. +- **CHATHISTORY** (`draft/chathistory`: `LATEST`/`BEFORE`/`AFTER`/`AROUND`/`BETWEEN` + /`TARGETS`) with the `+H` join backlog, **REDACT** (`draft/message-redaction`), + **MARKREAD** (`draft/read-marker`), and **multiline** (`draft/multiline`). +- **RELAYMSG** (`draft/relaymsg`) — bridge messages under a spoofed relay nick. + +### The full mode set +- **Prefixes** `+qaohv` (`~&@%+`), plus an optional network-staff prefix `+y` (`!`) + above owner (`operprefix` / `OJOIN`). +- **List modes** `+b` ban, `+e` except, `+I` invex, `+g` word filter, `+X` + exemptchanops, `+w` auto-status. +- **Parametered** `+k` key, `+l` limit, `+f` message-flood, `+j` join-flood, `+F` + nick-flood, `+L` redirect-when-full, `+H` history, `+B` anticaps, `+J` + kick-no-rejoin, `+d` delay-msg, `+K` no-repeat. +- **Flags** `+imnpstz`, `+O` oper-only, `+N` no-nick, `+C` no-CTCP, `+T` no-notice, + `+c` no-colour, `+S` strip-colour, `+R` reg-only, `+M` reg-moderated, `+G` censor, + `+u` auditorium, `+Q` no-kicks, `+A` allow-invite, `+P` permanent, `+U` + op-moderated, `+D` delay-join. +- **User modes** `+i w o x s g` plus `+B` bot, `+D` deaf, `+I` hide-chans, `+H` + hide-oper, `+r` logged-in, `+R` reg-only-PM, `+z` TLS-only-PM, `+W` show-whois, + `+h` helpop, `+c` common-chans-only. +- **Extbans** — matching `g:` security-group, `y:` reputation, `r:` realname, + `j:` in-channel, `s:` server, `G:` country, `b:` other-channel's ban list; acting + `m:` mute, `c:` no-colour, `n:` no-nick. + +### Operators +- `OPER`/`KILL`/`WALLOPS`/`GLOBOPS`, snomasks (`+s`) with an optional `chanlog`. +- Overrides: `SAJOIN`/`SAPART`/`SANICK`/`SAMODE`/`SATOPIC`/`SAKICK`/`SAQUIT`, + `CHGHOST`/`CHGIDENT`/`CHGNAME`/`SETHOST`/`SETIDENT`/`SETIDLE`, `NICKLOCK`/ + `NICKUNLOCK`, `SWHOIS`, `CHECK`, `CLEARCHAN`, `ALLTIME`, `OPERMOTD`, `VHOST`, + `TITLE`, oper-override-with-accountability, `operprefix`/`OJOIN`, `hidelist`/ + `hidemode`. +- **X-lines** `KLINE`/`GLINE`/`ZLINE`/`ELINE`/`SHUN`/`QLINE`/`CBAN`, persisted to + disk and restored on boot; `STATS`; on-demand `CONNECT`; `DIE`/`RESTART`; and a + reload-safe **`REHASH`** (keeps the running config if the file can't be read). + +### IRCv3 capabilities +`sasl`, `server-time`, `message-tags` (+ `msgid`), `multi-prefix`, `away-notify`, +`account-notify`, `extended-join`, `chghost`, `userhost-in-names`, `echo-message`, +`invite-notify`, `setname`, `extended-monitor`, `account-tag`, `standard-replies`, +`labeled-response`, `batch`, `cap-notify`, and drafts `chathistory`, +`message-redaction`, `pre-away`, `metadata-2`, `multiline`, `account-registration`, +`json-log`, `extended-isupport`, `relaymsg` — plus `WATCH`/`MONITOR`/`SILENCE` and +`ACCEPT` (+ `+g` callerid). + +### Services interface & accounts +- **SASL** PLAIN + EXTERNAL (TLS client-cert), relayed to an external services + server over S2S. +- `SVSNICK`/`SVSJOIN`/`SVSPART`/`SVSMODE`/`SVSLOGIN`/`SVSLOGOUT`, `ENCAP`, + `METADATA`; account-gated modes (`+r`/`+R`/`+M`). The ircd is *ready* for an + external services package — it is not one itself. +- Optional ircd-side account **registration** (`REGISTER`/`VERIFY` over an HTTP + API), CAPTCHA gating, and `EXTJWT` / file-host tokens. + +### Server-to-server linking +Handshake, `UID`/`FJOIN` netburst, cross-server users and channels, multi-hop +routing, nick-collision handling, and clean netsplit. + +### Anti-abuse +`antimixedutf8` (look-alike script spam), `antirandom` (gibberish nicks), message +flood (`+f`) + global rate limits, `connflood`/`connectban` (connection floods), +`blockamsg`, `securelist`, `dnsbl`, CAPTCHA / challenge gating, `solvemsg` +(arithmetic gate), `dccallow` (DCC filtering), `conn_waitpong`, `autodrop`. + +### GeoIP +A **native MaxMind `.mmdb` reader** (no crate): the `G:` geoban extban, a +`GEOIP` oper command, and a country line in WHOIS. + +### TLS, cloaking, transports +- **TLS** (openssl) with `SSLINFO`, cert fingerprints, and `+z` secure-only. +- Keyed-SHA-256 host **cloaking** (`+x`). +- A **native WebSocket transport** (`ws://` and `wss://`) with real-IP / scheme + behind a trusted proxy. +- Reverse-DNS on connect via a from-scratch forward-confirmed PTR resolver over + UDP (no DNS crate), off the core thread, fail-safe to the IP. + +### JSON-RPC control plane +A native inbound HTTP server + JSON-RPC interface (no `serde`, no `hyper`) with +token auth and ~30 methods across core/user/channel/server/stats/ban/message. + +### Native building blocks +Everything is hand-rolled to stay dependency-light and `unsafe`-free: the DNS +resolver, JWT (HS256), JSON scan/build, the mmdb reader, an HTTP client, and +password hashing (`md5`/`sha1`/`sha256`/`sha512`/`pbkdf2`). + +### Everything is configurable +Limits, thresholds, durations, timeouts and list sizes are all config keys — the +literal in code is only the default; nothing operational is hardcoded. ## Originality