docs: add a full docs/ manual (architecture, configuration, modes, operators, linking, ircv3, anti-abuse, deployment, building) and refresh the README for the reactor pool + TLS-in-reactor + resilience
This commit is contained in:
parent
d8a963d0f9
commit
bd054f7721
11 changed files with 1182 additions and 11 deletions
39
README.md
39
README.md
|
|
@ -16,9 +16,10 @@
|
|||
|
||||
echoIRCd is a full IRC + IRCv3 server built from the ground up in safe Rust
|
||||
(`#![forbid(unsafe_code)]`) with just two dependencies — `openssl` for TLS and
|
||||
`mio` for the socket engine. A single lock-free core thread owns all state while
|
||||
one epoll reactor drives tens of thousands of connections without an async
|
||||
runtime. It ships **100+ commands**, the **complete channel & user mode set**,
|
||||
`mio` for the socket engine. A single lock-free core thread owns all state; a
|
||||
**pool of epoll reactor threads** (one per core) drives the connections around it
|
||||
— TLS crypto and all — without an async runtime. It ships **100+ commands**, the
|
||||
**complete channel & user mode set**,
|
||||
**28 IRCv3 capabilities**, server-to-server linking, a services interface, TLS,
|
||||
WebSocket, GeoIP, layered anti-spam, and a JSON-RPC control plane — with every
|
||||
operational limit configurable and nothing hardcoded.
|
||||
|
|
@ -66,6 +67,14 @@ cargo run --release # reads ./echoircd.conf
|
|||
Then point a client at it: `/server 127.0.0.1 6667` (or `6697` for TLS once a
|
||||
certificate is configured).
|
||||
|
||||
## Documentation
|
||||
|
||||
The full manual lives in [`docs/`](docs/):
|
||||
|
||||
- [Building & running](docs/building.md) · [Configuration](docs/configuration.md) · [Architecture](docs/architecture.md)
|
||||
- [Channel & user modes](docs/modes.md) · [Operators](docs/operators.md) · [Server linking & services](docs/linking.md)
|
||||
- [IRCv3](docs/ircv3.md) · [Anti-abuse & flood protection](docs/anti-abuse.md) · [Deployment](docs/deployment.md)
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration is a plain `key = value` file; see
|
||||
|
|
@ -80,11 +89,16 @@ A single **core thread** owns every `User` and `Channel`, so command and module
|
|||
code is ordinary single-threaded logic over `&mut Server` — no `Arc<Mutex<…>>`
|
||||
anywhere. The I/O edge feeds it events over channels:
|
||||
|
||||
- **One `mio` epoll reactor** drives all client sockets — measured at 5,000
|
||||
concurrent clients on 4 threads total, scaling toward ~50k with a release build
|
||||
and a high `LimitNOFILE`.
|
||||
- **TLS sessions and server links** run a thread each; both hand the core the same
|
||||
`OutSink`, so it never knows which transport a connection uses.
|
||||
- **A pool of `mio` epoll reactors** drives client sockets — an acceptor
|
||||
round-robins each connection onto a worker (one per core by default), and each
|
||||
worker frames lines and runs **TLS handshakes and record crypto non-blocking**
|
||||
in-thread. So the socket work and the crypto spread across cores while the state
|
||||
core stays single-threaded and lock-free. (Proxied TLS and server links keep a
|
||||
thread each; there are few of them.)
|
||||
- **Resilience is built in.** Slow work (KDF hashing, DNS, disk snapshots) runs
|
||||
off the core so a flood can't freeze it; each event and each connection's I/O is
|
||||
panic-isolated so one bad client can't crash the server; a watchdog flags a
|
||||
stuck core; and half-open/stalled connections are reaped on a timer.
|
||||
|
||||
**Why a raw reactor and not async?** IRC is one large shared mutable graph, and
|
||||
almost every command mutates it and then broadcasts. With one thread owning all of
|
||||
|
|
@ -92,12 +106,14 @@ it, handlers are plain synchronous code — no locks, no `.await`, no `Send + 's
|
|||
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 for
|
||||
parallelism the workload can't use. `mio` is the same readiness layer async runtimes
|
||||
build on, so you keep the scaling without the runtime; blocking work (DNS, TLS,
|
||||
HTTP) is offloaded to its own threads.
|
||||
build on, so you keep the scaling without the runtime. What *does* parallelize —
|
||||
the socket syscalls and TLS crypto — runs in the reactor pool; scaling past one
|
||||
machine is done by linking servers, not threading one harder.
|
||||
|
||||
Memory safety is structural: `Uid` handles instead of raw pointers, an `Extensible`
|
||||
typemap instead of `void*` module data (freed on drop), and compiled-in trait
|
||||
objects instead of a fragile plugin ABI.
|
||||
objects instead of a fragile plugin ABI. **Full design notes:**
|
||||
[`docs/architecture.md`](docs/architecture.md).
|
||||
|
||||
## Extending
|
||||
|
||||
|
|
@ -114,6 +130,7 @@ Three small extension points, each one file + one table line:
|
|||
|
||||
- **Repository** — <https://git.devtronic.pro/fedserv/echoIRCd>
|
||||
- **Issues** — <https://git.devtronic.pro/fedserv/echoIRCd/issues>
|
||||
- **Documentation** — [`docs/`](docs/)
|
||||
- **Config reference** — [`echoircd.conf.example`](echoircd.conf.example)
|
||||
|
||||
## License
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue