litep2p/protocol/libp2p/kademlia/
config.rs

1// Copyright 2023 litep2p developers
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use crate::{
22    codec::ProtocolCodec,
23    protocol::libp2p::kademlia::handle::{
24        IncomingRecordValidationMode, KademliaCommand, KademliaEvent, KademliaHandle,
25        RoutingTableUpdateMode,
26    },
27    types::protocol::ProtocolName,
28    PeerId, DEFAULT_CHANNEL_SIZE,
29};
30
31use multiaddr::Multiaddr;
32use tokio::sync::mpsc::{channel, Receiver, Sender};
33
34use std::{collections::HashMap, time::Duration};
35
36/// Default TTL for the records.
37const DEFAULT_TTL: Duration = Duration::from_secs(36 * 60 * 60);
38
39/// Default provider record TTL.
40const DEFAULT_PROVIDER_TTL: Duration = Duration::from_secs(48 * 60 * 60);
41
42/// Protocol name.
43const PROTOCOL_NAME: &str = "/ipfs/kad/1.0.0";
44
45/// Kademlia replication factor.
46const REPLICATION_FACTOR: usize = 20usize;
47
48/// Kademlia configuration.
49#[derive(Debug)]
50pub struct Config {
51    // Protocol name.
52    // pub(crate) protocol: ProtocolName,
53    /// Protocol names.
54    pub(crate) protocol_names: Vec<ProtocolName>,
55
56    /// Protocol codec.
57    pub(crate) codec: ProtocolCodec,
58
59    /// Replication factor.
60    pub(super) replication_factor: usize,
61
62    /// Known peers.
63    pub(super) known_peers: HashMap<PeerId, Vec<Multiaddr>>,
64
65    /// Routing table update mode.
66    pub(super) update_mode: RoutingTableUpdateMode,
67
68    /// Incoming records validation mode.
69    pub(super) validation_mode: IncomingRecordValidationMode,
70
71    /// Default record TTL.
72    pub(super) record_ttl: Duration,
73
74    /// Provider record TTL.
75    pub(super) provider_ttl: Duration,
76
77    /// TX channel for sending events to `KademliaHandle`.
78    pub(super) event_tx: Sender<KademliaEvent>,
79
80    /// RX channel for receiving commands from `KademliaHandle`.
81    pub(super) cmd_rx: Receiver<KademliaCommand>,
82}
83
84impl Config {
85    fn new(
86        replication_factor: usize,
87        known_peers: HashMap<PeerId, Vec<Multiaddr>>,
88        mut protocol_names: Vec<ProtocolName>,
89        update_mode: RoutingTableUpdateMode,
90        validation_mode: IncomingRecordValidationMode,
91        record_ttl: Duration,
92        provider_ttl: Duration,
93    ) -> (Self, KademliaHandle) {
94        let (cmd_tx, cmd_rx) = channel(DEFAULT_CHANNEL_SIZE);
95        let (event_tx, event_rx) = channel(DEFAULT_CHANNEL_SIZE);
96
97        // if no protocol names were provided, use the default protocol
98        if protocol_names.is_empty() {
99            protocol_names.push(ProtocolName::from(PROTOCOL_NAME));
100        }
101
102        (
103            Config {
104                protocol_names,
105                update_mode,
106                validation_mode,
107                record_ttl,
108                provider_ttl,
109                codec: ProtocolCodec::UnsignedVarint(None),
110                replication_factor,
111                known_peers,
112                cmd_rx,
113                event_tx,
114            },
115            KademliaHandle::new(cmd_tx, event_rx),
116        )
117    }
118
119    /// Build default Kademlia configuration.
120    pub fn default() -> (Self, KademliaHandle) {
121        Self::new(
122            REPLICATION_FACTOR,
123            HashMap::new(),
124            Vec::new(),
125            RoutingTableUpdateMode::Automatic,
126            IncomingRecordValidationMode::Automatic,
127            DEFAULT_TTL,
128            DEFAULT_PROVIDER_TTL,
129        )
130    }
131}
132
133/// Configuration builder for Kademlia.
134#[derive(Debug)]
135pub struct ConfigBuilder {
136    /// Replication factor.
137    pub(super) replication_factor: usize,
138
139    /// Routing table update mode.
140    pub(super) update_mode: RoutingTableUpdateMode,
141
142    /// Incoming records validation mode.
143    pub(super) validation_mode: IncomingRecordValidationMode,
144
145    /// Known peers.
146    pub(super) known_peers: HashMap<PeerId, Vec<Multiaddr>>,
147
148    /// Protocol names.
149    pub(super) protocol_names: Vec<ProtocolName>,
150
151    /// Default TTL for the records.
152    pub(super) record_ttl: Duration,
153
154    /// Default TTL for the provider records.
155    pub(super) provider_ttl: Duration,
156}
157
158impl Default for ConfigBuilder {
159    fn default() -> Self {
160        Self::new()
161    }
162}
163
164impl ConfigBuilder {
165    /// Create new [`ConfigBuilder`].
166    pub fn new() -> Self {
167        Self {
168            replication_factor: REPLICATION_FACTOR,
169            known_peers: HashMap::new(),
170            protocol_names: Vec::new(),
171            update_mode: RoutingTableUpdateMode::Automatic,
172            validation_mode: IncomingRecordValidationMode::Automatic,
173            record_ttl: DEFAULT_TTL,
174            provider_ttl: DEFAULT_PROVIDER_TTL,
175        }
176    }
177
178    /// Set replication factor.
179    pub fn with_replication_factor(mut self, replication_factor: usize) -> Self {
180        self.replication_factor = replication_factor;
181        self
182    }
183
184    /// Seed Kademlia with one or more known peers.
185    pub fn with_known_peers(mut self, peers: HashMap<PeerId, Vec<Multiaddr>>) -> Self {
186        self.known_peers = peers;
187        self
188    }
189
190    /// Set routing table update mode.
191    pub fn with_routing_table_update_mode(mut self, mode: RoutingTableUpdateMode) -> Self {
192        self.update_mode = mode;
193        self
194    }
195
196    /// Set incoming records validation mode.
197    pub fn with_incoming_records_validation_mode(
198        mut self,
199        mode: IncomingRecordValidationMode,
200    ) -> Self {
201        self.validation_mode = mode;
202        self
203    }
204
205    /// Set Kademlia protocol names, overriding the default protocol name.
206    ///
207    /// The order of the protocol names signifies preference so if, for example, there are two
208    /// protocols:
209    ///  * `/kad/2.0.0`
210    ///  * `/kad/1.0.0`
211    ///
212    /// Where `/kad/2.0.0` is the preferred version, then that should be in `protocol_names` before
213    /// `/kad/1.0.0`.
214    pub fn with_protocol_names(mut self, protocol_names: Vec<ProtocolName>) -> Self {
215        self.protocol_names = protocol_names;
216        self
217    }
218
219    /// Set default TTL for the records.
220    ///
221    /// If unspecified, the default TTL is 36 hours.
222    pub fn with_record_ttl(mut self, record_ttl: Duration) -> Self {
223        self.record_ttl = record_ttl;
224        self
225    }
226
227    /// Set default TTL for the provider records. Recommended value is 2 * (refresh interval) + 20%.
228    ///
229    /// If unspecified, the default TTL is 48 hours.
230    pub fn with_provider_record_ttl(mut self, provider_record_ttl: Duration) -> Self {
231        self.provider_ttl = provider_record_ttl;
232        self
233    }
234
235    /// Build Kademlia [`Config`].
236    pub fn build(self) -> (Config, KademliaHandle) {
237        Config::new(
238            self.replication_factor,
239            self.known_peers,
240            self.protocol_names,
241            self.update_mode,
242            self.validation_mode,
243            self.record_ttl,
244            self.provider_ttl,
245        )
246    }
247}