@@ -2,6 +2,11 @@
|
||||
name = "music-dht"
|
||||
version = "0.1.0"
|
||||
description = "Distributed music library search: a Kademlia-style DHT on top of federation-net"
|
||||
readme = "README.md"
|
||||
documentation = "https://docs.rs/music-dht"
|
||||
repository.workspace = true
|
||||
keywords = ["p2p", "dht", "music", "kademlia", "iroh"]
|
||||
categories = ["network-programming", "multimedia::audio"]
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
@@ -7,9 +7,8 @@ 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`](../artist-dht) example: same DHT machinery, richer records and
|
||||
an application-oriented API.
|
||||
It combines the original DHT proof of concept with the richer record model and
|
||||
application-oriented API used by Furumi.
|
||||
|
||||
## Records
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
//! 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 bootstrap, index or
|
||||
//! search servers. This crate is the grown-up sibling of the minimal
|
||||
//! `artist-dht` example.
|
||||
//! search servers.
|
||||
//!
|
||||
//! ## How it works
|
||||
//!
|
||||
|
||||
@@ -835,10 +835,13 @@ impl Node {
|
||||
}
|
||||
|
||||
for index in targets.iter() {
|
||||
per_peer.entry(*index).or_default().push(StoreRecordRequest {
|
||||
key,
|
||||
record: record.clone(),
|
||||
});
|
||||
per_peer
|
||||
.entry(*index)
|
||||
.or_default()
|
||||
.push(StoreRecordRequest {
|
||||
key,
|
||||
record: record.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1043,7 +1046,9 @@ mod tests {
|
||||
|
||||
// Byte limit: huge entries split well before the count limit.
|
||||
let huge = "x".repeat(crate::record::MAX_ITEM_NAME_BYTES);
|
||||
let entries: Vec<_> = (0..MAX_RECORDS_PER_BATCH).map(|_| store_entry(&huge)).collect();
|
||||
let entries: Vec<_> = (0..MAX_RECORDS_PER_BATCH)
|
||||
.map(|_| store_entry(&huge))
|
||||
.collect();
|
||||
for batch in chunk_store_batches(entries) {
|
||||
assert!(!batch.is_empty());
|
||||
let bytes: usize = batch
|
||||
|
||||
@@ -236,9 +236,9 @@ impl LibraryItem {
|
||||
pub struct StoredRecord {
|
||||
/// The item record itself.
|
||||
pub item: LibraryItem,
|
||||
/// Peer that pushed this replica. Not cryptographically verified in the
|
||||
/// PoC: the connection authenticates the direct sender, not the origin
|
||||
/// of a replicated record.
|
||||
/// Peer that pushed this replica. The connection authenticates the direct
|
||||
/// sender, not the origin embedded in a forwarded record. Revision
|
||||
/// ordering provides convergence, not end-to-end origin authentication.
|
||||
pub publisher: PeerId,
|
||||
/// Unix timestamp (milliseconds) after which the replica must be dropped.
|
||||
pub expires_at_ms: u64,
|
||||
|
||||
@@ -120,8 +120,9 @@ impl RoutingTable {
|
||||
/// Inserts or refreshes a contact. Returns `true` if the contact was not
|
||||
/// known before.
|
||||
///
|
||||
/// A full bucket evicts its least recently seen contact; the PoC skips
|
||||
/// the classic ping-before-evict procedure.
|
||||
/// A full bucket evicts its least recently seen contact. Active liveness
|
||||
/// handling stays in the node layer so routing-table updates remain
|
||||
/// deterministic.
|
||||
pub fn upsert(&mut self, contact: NodeContact) -> bool {
|
||||
let Some(index) =
|
||||
distance(self.own_id.as_bytes(), contact.node_id.as_bytes()).bucket_index()
|
||||
|
||||
@@ -23,8 +23,11 @@ use crate::record::{
|
||||
};
|
||||
use crate::routing::{NodeContact, NodeId};
|
||||
|
||||
/// Fixed schema of the music-dht protocol; peers with a different schema are
|
||||
/// rejected by `federation-net` during the handshake.
|
||||
/// Fixed compatibility identifier of the music-dht protocol; peers with a
|
||||
/// different schema are rejected by `federation-net` during the handshake.
|
||||
///
|
||||
/// The historical value is retained because changing it would partition
|
||||
/// existing deployments.
|
||||
pub const SCHEMA_NAME: &str = "music-dht-poc-v3";
|
||||
|
||||
/// Capacity of the application event channel.
|
||||
|
||||
Reference in New Issue
Block a user