rustydht_lib/dht/
builder.rs

1use crate::common::ipv4_addr_src::{IPV4AddrSource, IPV4Consensus};
2use crate::common::Id;
3use crate::dht::{DHTSettings, DHT};
4use crate::errors::RustyDHTError;
5use crate::shutdown::ShutdownReceiver;
6use crate::storage::node_bucket_storage::{NodeBucketStorage, NodeStorage};
7use std::net::{Ipv4Addr, SocketAddrV4};
8
9/// Helps to configure and create new [DHT](crate::dht::DHT) instances.
10#[derive(Default, Clone)]
11pub struct DHTBuilder {
12    initial_id: Option<Id>,
13    listen_addr: Option<SocketAddrV4>,
14    ip_source: Option<Box<dyn IPV4AddrSource + Send>>,
15    route_table: Option<Box<dyn NodeStorage + Send>>,
16    settings: Option<DHTSettings>,
17}
18
19impl DHTBuilder {
20    /// Creates a new DHTBuilder
21    pub fn new() -> DHTBuilder {
22        Self::default()
23    }
24
25    /// Set the initial Id for your DHT node.
26    ///
27    /// If you don't specify one, DHT will try to generate one based on its
28    /// external IPv4 address (if known). If it doesn't know its external
29    /// IPv4 address, DHT will generate a random Id and change it later
30    /// if it learns that it's not valid for its IPv4 address.
31    pub fn initial_id(mut self, id: Id) -> Self {
32        self.initial_id = Some(id);
33        self
34    }
35
36    /// Sets the IPv4 address and port that the DHT should bind its UDP socket to.
37    ///
38    /// If not specified, it will default to 0.0.0.0:6881
39    pub fn listen_addr(mut self, listen_addr: SocketAddrV4) -> Self {
40        self.listen_addr = Some(listen_addr);
41        self
42    }
43
44    /// Provides an IPV4AddrSource implementation to the DHT.
45    ///
46    /// DHT will use this object to learn its external IPv4 address and keep
47    /// up to date when the IP changes. If unspecified, the default implementation
48    /// is [IPV4Consensus](crate::common::ipv4_addr_src::IPV4Consensus).
49    pub fn ip_source(mut self, ip_source: Box<dyn IPV4AddrSource + Send>) -> Self {
50        self.ip_source = Some(ip_source);
51        self
52    }
53
54    /// Provides a [NodeStorage](crate::storage::node_bucket_storage::NodeStorage)
55    /// implementation to the DHT.
56    ///
57    /// DHT will use this to store its routing tables. If unspecified, the default
58    /// implementation is [NodeBucketStorage](crate::storage::node_bucket_storage::NodeBucketStorage)
59    /// which works roughly the [BEP0005](http://www.bittorrent.org/beps/bep_0005.html)
60    /// describes.
61    pub fn route_table(mut self, route_table: Box<dyn NodeStorage + Send>) -> Self {
62        self.route_table = Some(route_table);
63        self
64    }
65
66    /// Provides a DHTSettings object to the DHT.
67    ///
68    /// DHTSettings can be built with [DHTSettingsBuilder](crate::dht::DHTSettingsBuilder)
69    /// but the defaults should work fine in most cases.
70    pub fn settings(mut self, settings: DHTSettings) -> Self {
71        self.settings = Some(settings);
72        self
73    }
74
75    /// Build a DHT
76    ///
77    /// This must be called from within a tokio Runtime context because it constructs
78    /// a tokio UdpSocket. See [tokio::net::UdpSocket].
79    pub fn build(self, shutdown_rx: ShutdownReceiver) -> Result<DHT, RustyDHTError> {
80        DHT::new(
81            shutdown_rx,
82            self.initial_id,
83            std::net::SocketAddr::V4(
84                self.listen_addr
85                    .unwrap_or_else(|| SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 6881)),
86            ),
87            self.ip_source
88                .unwrap_or_else(|| Box::new(IPV4Consensus::new(2, 10))),
89            self.route_table
90                .unwrap_or_else(|| Box::new(NodeBucketStorage::new(Id::ZERO, 8))),
91            self.settings.unwrap_or_default(),
92        )
93    }
94}