Replace the one-intermediate-peer relay with protocol-scoped connectivity graphs and precomputed shortest-path/ECMP forwarding snapshots. Independent transport readers forward opaque transit frames without a plugin or TUN round trip. Carry source, destination, a bounded hop limit and stable flow tags; preserve end-to-end WireGuard links across topology changes. Classify IP flows before encryption and preserve their tags through the WireGuard pending queue. Add offline four-agent path-change coverage, loop and isolation tests, and an opt-in release forwarding microbenchmark. Bump control/data ALPNs while preserving persistent network identities and state. Also include the pending Windows Mainline idle-timeout fix and its regression test, using a reproducible vendored dependency patch. Validation: fmt, workspace Clippy with warnings denied, and 307 release tests passed. Two pre-existing Windows SQLite wipe failures were excluded; public DHT and the manual benchmark remain ignored by default. The forwarding microbenchmark measured 103 ns (64 B) and 202 ns (1280 B) per transit packet, excluding encryption and socket I/O.
Mainline
Simple, robust, BitTorrent's Mainline DHT implementation.
This library is focused on being the best and simplest Rust client for Mainline, especially focused on reliable and fast time-to-first-response.
It should work as a routing / storing node (server mode) as well, and has been running in production for many months without an issue. However if you are concerned about spam or DoS, you should consider implementing rate limiting.
Getting started
Check the Examples.
Features
Client
Running as a client, means you can store and query for values on the DHT, but not accept any incoming requests.
use mainline::Dht;
let dht = Dht::client().unwrap();
Supported BEPs:
- BEP_0005 DHT Protocol
- BEP_0042 DHT Security extension
- BEP_0043 Read-only DHT Nodes
- BEP_0044 Storing arbitrary data in the DHT
This implementation also includes measures against Vertical Sybil Attacks.
Server
Running as a server is the same as a client, but you also respond to incoming requests and serve as a routing and storing node, supporting the general routing of the DHT, and contributing to the storage capacity of the DHT.
use mainline::Dht;
let dht = Dht::server().unwrap(); // or `Dht::builder::server_mode().build();`
Supported BEPs:
- BEP_0005 DHT Protocol
- BEP_0042 DHT Security extension
- BEP_0043 Read-only DHT Nodes
- BEP_0044 Storing arbitrary data in the DHT
Rate limiting
The server implementation has no rate-limiting, you can run your own request filter and apply your custom rate-limiting. However, that limit/block will only apply after parsing incoming messages, and it won't affect handling incoming responses.
Adaptive mode
The default Adaptive mode will start the node in client mode, and after 15 minutes of running with a publicly accessible address, it will switch to server mode. This way nodes that can serve as routing nodes (accessible and less likely to churn), serve as such.
If you want to explicitly start in Server mode, because you know you are not running behind firewall,
you can call Dht::builder().server_mode().build(), and you can optionally add your known public ip so the node doesn't have to depend on,
votes from responding nodes: Dht::builder().server_mode().public_ip().build().
Acknowledgment
This implementation was possible thanks to Webtorrent's Bittorrent-dht as a reference, and Rustydht-lib that saved me a lot of time, especially at the serialization and deserialization of Bencode messages.