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}