readme: mio reactor + scaling, reverse-dns on connect, callerid/accept, reload-safe rehash, openssl+mio deps

This commit is contained in:
Jean Chevronnet 2026-08-08 01:18:38 +00:00
parent 2d9c482496
commit 296d87726a

View file

@ -3,12 +3,13 @@
A from-scratch IRC daemon written in **native Rust**. The architecture is A from-scratch IRC daemon written in **native Rust**. The architecture is
*inspired by* InspIRCd's shape — commands as objects, modes as handler objects, *inspired by* InspIRCd's shape — commands as objects, modes as handler objects,
modules with lifecycle hooks — but every line is original Rust, not a port or a modules with lifecycle hooks — but every line is original Rust, not a port or a
translation. Design goals: `#![forbid(unsafe_code)]`, dependency-light (the only translation. Design goals: `#![forbid(unsafe_code)]`, dependency-light (just two
external crate is `openssl`, for TLS), and lock-free (a single core thread owns small crates — `openssl` for TLS and `mio` for the epoll socket engine), and
all state). lock-free (a single core thread owns all state).
> Status: early but capable. It boots, registers clients, and speaks a large > Status: early but capable. It boots, registers clients, speaks a large chunk of
> chunk of the IRC + IRCv3 protocol (see **What works**). Not battle-tested yet. > the IRC + IRCv3 protocol (see **What works**), and one reactor thread has served
> 5,000 concurrent connections in testing. Not battle-tested yet.
## Run it ## Run it
@ -27,10 +28,19 @@ key, link password) — never commit it. For TLS, generate a cert/key into `tls/
A single **core thread** owns every `User` and `Channel`, so command and module A single **core thread** owns every `User` and `Channel`, so command and module
code is plain single-threaded logic over `&mut Server` — no `Arc<Mutex<…>>` code is plain single-threaded logic over `&mut Server` — no `Arc<Mutex<…>>`
anywhere. I/O lives on cheap per-connection threads that talk to the core over anywhere. The I/O edge feeds it events over mpsc channels:
mpsc channels (a reader turns wire → events, a writer turns lines → wire). TLS
connections use one polling thread each (an `openssl` session can't be split - **Client connections run on one `mio` epoll reactor thread.** The daemon drives
across reader+writer threads). tens of thousands of sockets without a thread per connection — measured at 5,000
concurrent clients on **4 threads total**, and it scales toward ~50k (use a
release build and a high `LimitNOFILE`). This is the readiness layer Tokio is
built on, but without pulling in an async runtime, so the single-threaded core
is untouched.
- **TLS and server links** keep a thread per connection — there are few of them,
and a TLS session can't be split across reader/writer threads.
Both models hand the core the same `OutSink`, so it never knows or cares which one
a connection uses.
Where this improves on the C++ original it's inspired by: `Uid` handles instead Where this improves on the C++ original it's inspired by: `Uid` handles instead
of raw `User*` (no use-after-free, no cull list), an `Extensible` typemap instead of raw `User*` (no use-after-free, no cull list), an `Extensible` typemap instead
@ -57,14 +67,21 @@ of `void*` module data (freed automatically on drop), `&str` slices instead of
- **Full mode set** as handler objects: prefixes `+qaohv`, lists `+beI`, and - **Full mode set** as handler objects: prefixes `+qaohv`, lists `+beI`, and
`+klmntispzONCTcSRMGu` plus flood/rate modes `+f/+j/+F`, redirect `+L`, word `+klmntispzONCTcSRMGu` plus flood/rate modes `+f/+j/+F`, redirect `+L`, word
filter `+g`, and acting **extbans** `m:`/`c:`/`n:`. filter `+g`, and acting **extbans** `m:`/`c:`/`n:`.
- **IRC operators**: `OPER`/`KILL`/`WALLOPS`/`REHASH`/`GLOBOPS`, `SAJOIN`/`SAPART`/ - **IRC operators**: `OPER`/`KILL`/`WALLOPS`/`GLOBOPS`, `SAJOIN`/`SAPART`/`SANICK`/
`SANICK`/`SAMODE`/`SATOPIC`/`SAKICK`, `CHGHOST`/`CHGIDENT`/`SETHOST`/`SETIDENT`, `SAMODE`/`SATOPIC`/`SAKICK`, `CHGHOST`/`CHGIDENT`/`SETHOST`/`SETIDENT`,
`KLINE`/`GLINE`/`ZLINE` + `STATS`, snomasks (`+s`), `DIE`/`RESTART`. `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`**, - **IRCv3**: `CAP` negotiation, `server-time`, `message-tags` + **`msgid`**,
`multi-prefix`, `away-notify`, `account-notify`, `extended-join`, `chghost`, `multi-prefix`, `away-notify`, `account-notify`, `extended-join`, `chghost`,
`userhost-in-names`, `echo-message`, `invite-notify`, `setname`, `userhost-in-names`, `echo-message`, `invite-notify`, `setname`,
`extended-monitor`, `SASL` (PLAIN, relayed to services), `WATCH`/`MONITOR`, `extended-monitor`, `SASL` (PLAIN, relayed to services), `WATCH`/`MONITOR`,
`SILENCE`. `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`); - **TLS** (openssl) with `sslinfo`; keyed-SHA-256 host **cloaking** (`+x`);
**services-ready accounts** (`SVSLOGIN`/`SVSLOGOUT`, account-gated `+r/+R/+M`) **services-ready accounts** (`SVSLOGIN`/`SVSLOGOUT`, account-gated `+r/+R/+M`)
— the ircd is *ready* for an external services package, it is not one itself. — the ircd is *ready* for an external services package, it is not one itself.
@ -76,7 +93,8 @@ of `void*` module data (freed automatically on drop), `&str` slices instead of
echoIRCd is original Rust. InspIRCd is a reference for *behaviour and API shape* echoIRCd is original Rust. InspIRCd is a reference for *behaviour and API shape*
only — no code is copied or translated. `scripts/native-rust-guard.sh` enforces only — no code is copied or translated. `scripts/native-rust-guard.sh` enforces
this (no `unsafe`, no C/FFI, openssl-only deps, no copy/translation wording). this (no `unsafe`, no C/FFI, dependencies limited to `openssl` + `mio`, and no
copy/translation wording in comments); it runs on every edit.
## License ## License