Protocol Handlers
How Risuko handles different download protocols.
Risuko's engine includes specialized handlers for each supported protocol. Each handler is a separate module within risuko-engine.
HTTP/HTTPS
Module: engine/http.rs
The HTTP handler supports multi-threaded range-based downloads:
- Sends a
GETrequest withRange: bytes=0-0to probe file size and range support - Divides the file into 1 MiB pieces when at least
min-split-sizebytes; spawns N worker tasks (configurable viasplit, like aria2's-s/-x) that pull pieces from a shared lock-free queue - Work-stealing is inherent: any idle worker claims the next free piece, so a slow connection never holds back the rest of the download
- Resume granularity is per-piece (≤1 MiB lost on
SIGKILL): each piece tracks anAtomicU32byte counter that the writer increments per flushedBytes, and a sidecar JSON snapshot is persisted every 2 s - Downloads use HTTP
Rangeheaders; workers are pinned to HTTP/1.1 to keep each piece on its own TCP connection - Each piece streams
bytes::Bytesdirectly into a dedicated writer task that issues positioned writes (pwriteon Unix,seek_writeon Windows) against a shared file handle, so workers never contend on a seek lock - Calls
fsynconce on completion before renaming the.partfile into place - Validates the
Content-Rangeheader on every 206 response and aborts on mismatch; sendsIf-Matchwhen anETagwas recorded for resume - Falls back to a single-connection download when the file is below
min-split-sizeor the server doesn't support ranges - Handles redirects, cookies, and custom headers
- Supports proxy connections via the
all-proxyoption
Key Options
| Option | Default | Description |
|---|---|---|
split | 16 | Number of parallel worker tasks (one TCP connection each) |
min-split-size | 1M | Skip splitting for files smaller than this |
user-agent | Chrome UA string | Custom user agent |
header | — | Custom HTTP headers |
all-proxy | — | Proxy URL |
referer | — | HTTP referer |
max-download-limit | 0 | Per-task speed limit (bytes/s, 0 = unlimited) |
remote-time | false | Set the local file mtime from the server's Last-Modified header |
BitTorrent
Module: engine/torrent.rs
Built on risuko-bt:
- Magnet link resolution (session fast-path for already-managed torrents, then tracker + DHT)
.torrentfile parsing via the bundled bencode decoder- BEP-5 DHT for peer discovery, dual-stack (IPv4 + IPv6 via BEP-32) when an IPv6 socket can be bound
- BEP-14 Local Service Discovery (LSD) for peers on the same LAN
- BEP-10 extension protocol with
ut_metadata(BEP-9); theut_pexextension id is advertised but BEP-11 peer ingest is not yet wired - BEP-8 Message Stream Encryption (MSE/PE) with selectable
plaintext/prefer/requirepolicy - UPnP IGD port forwarding for the listener (TCP + UDP)
- Rarest-first piece selection with endgame mode and SHA-1 verification off the async runtime
- HTTP/HTTPS (BEP-23 compact) and UDP (BEP-15) trackers
- Configurable seeding (ratio, time, or keep-seeding), upload speed limiting
- Tunable per-peer request pipeline and per-torrent peer cap
Key Options
| Option | Description |
|---|---|
seed-ratio | Stop seeding after this upload/download ratio |
seed-time | Stop seeding after this many minutes |
keep-seeding | Seed until manually stopped (overrides seed-time / seed-ratio) |
max-upload-limit | Upload speed limit (bytes/s) |
bt-tracker | Additional tracker URLs |
bt-max-peers-per-torrent | Max concurrent peer connections per torrent (default 100) |
bt-max-outstanding-per-peer | Max pipelined chunk requests per peer (default 128) |
bt-enable-upnp | UPnP IGD port forwarding (default true) |
bt-upnp-lease | UPnP mapping lease in seconds (default 300) |
bt-enable-lsd | BEP-14 Local Service Discovery (default true) |
bt-encryption-policy | MSE/PE policy: plaintext, prefer, require (default prefer) |
bt-listen-v6 | Also bind an IPv6 TCP listener (default false) |
Seeding Behavior
After a torrent download completes, seeding behavior depends on the seed options:
onBtDownloadCompletefires when the download finishes- If
keep-seedingis true, orseed-time > 0, orseed-ratio > 0, the task stays active and seeding continues - When
keep-seedingis true,seed-time/seed-ratiolimits are ignored; seeding runs until the task is stopped manually - Otherwise seeding stops when
seed-timeelapses orseed-ratiois reached (whichever comes first) onDownloadCompletefires when seeding is done (or immediately if no seeding was requested)
ED2K
Module: engine/ed2k/
Supports the eDonkey2000 protocol for downloading files using ed2k:// links.
M3U8/HLS
Module: engine/m3u8/
Downloads HTTP Live Streaming content:
- Parses M3U8 playlist files
- Downloads all segments in parallel
- Concatenates segments into the final file
- Supports both live and VOD playlists
FTP/SFTP
Module: engine/ftp/
File Transfer Protocol handler:
- FTP with optional TLS encryption
- SFTP (SSH File Transfer Protocol)
- Passive mode support
- Directory listing and file download
RSS
Module: engine/rss/
Automatic feed subscription and download:
- Add RSS/Atom feed URLs
- Periodic polling for new items (configurable interval)
- Automatic download of new items matching configured rules
- Persistent feed state via
StorageBackend
The RSS manager uses tokio::spawn for async polling and requires a tokio runtime context.
Protocol Routing
The engine does not auto-detect protocols from URLs. Each protocol has a dedicated RPC method or API function:
| Protocol | RPC Method | Node.js Function | CLI |
|---|---|---|---|
| HTTP/HTTPS | risuko.addUri | addUri | risuko download <url> |
| BitTorrent (.torrent) | risuko.addTorrent | addTorrent | risuko download <file.torrent> (auto-detected) |
| BitTorrent (magnet) | — | addMagnet | Passed to addUri |
| ED2K | risuko.addEd2k | addEd2k | — |
| M3U8/HLS | — | addM3u8 | — |
| FTP/SFTP | — | addFtp | — |
The CLI's download command only distinguishes .torrent files (by checking if the path ends with .torrent and exists on disk). All other inputs are passed to addUri. The Node.js API provides protocol-specific functions (addTorrent, addMagnet, addEd2k, addM3u8, addFtp) that call the engine directly.