music-dht
A distributed music library directory built on
federation-net: peers publish their local library
index — artists, releases and tracks (names and small metadata, never
files) — into a Kademlia-style DHT and search each other's libraries.
Every running node is simultaneously a client, a DHT router and a storage
node; there are no dedicated servers of any kind.
This crate is the grown-up sibling of the minimal
artist-dht example: same DHT machinery, richer records and
an application-oriented API.
Records
A [LibraryItem] carries: kind (artist | release | track), name,
artist_names (main artists for releases/tracks), featured_artist_names
(for track guest appearances), year, release_type, release_title,
track_number, disc_number, duration_seconds, plus ownership and
versioning metadata. Records are published under one exact key (the
normalized name) and one token key per word of the name, every main/featured
artist name and the track release title, so searching for an artist also
returns their releases, tracks and guest appearances.
API
The application does not add or delete records one by one — it declares the desired state and the service diffs:
let (service, events) = MusicDhtService::start(config).await?;
// Publish (and later re-publish) the whole library; matched by local_key.
service.sync_library(vec![
ItemSpec {
local_key: "artist:1".into(),
kind: ItemKind::Artist,
name: "Massive Attack".into(),
artist_names: vec![],
featured_artist_names: vec![],
year: None,
release_type: None,
release_title: None,
track_number: None,
disc_number: None,
duration_seconds: None,
},
// ...
]).await?;
let outcome = service.search_network("teardrop").await?;
sync_library is idempotent: item ids are derived from
(owner, kind, local_key), so unchanged items are skipped, changed ones are
republished with a bumped revision and items that disappeared from the input
are tombstoned network-wide.
Peer discovery
With .rendezvous(RendezvousConfig::default()) in the config, peers of a
network find each other knowing only the network id (a shared rendezvous
record in the public BitTorrent Mainline DHT — see the federation-net
README). Tickets (service.ticket() / service.connect(ticket)) remain as a
manual fallback for isolated networks.
The network id is a public rendezvous token: anyone who knows it can join and see the published names. Use a unique, hard-to-guess name for a private network.
Consumers
furumi-fd uses this crate for its
federation feature: every instance publishes its library index and can search
the libraries of all other instances on the same network.
Verification
cargo fmt --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p music-dht
The integration test starts three real nodes in one process (they use Iroh's public relay infrastructure), so it needs network access.