1use super::{addressbook, protocol};
2
3use super::peerbook::{self};
4use serde::{Deserialize, Serialize};
5
6use crate::repo::DefaultStorage;
7use crate::{IntoAddPeerOpt, IpfsOptions};
8
9use crate::repo::Repo;
10
11use ipld_core::cid::Cid;
12
13use connexa::prelude::dht::Record;
14use connexa::prelude::identity::{Keypair, PublicKey};
15use connexa::prelude::swarm::behaviour::toggle::Toggle;
16use connexa::prelude::swarm::NetworkBehaviour;
17use connexa::prelude::{identify, relay, Multiaddr, PeerId};
18use std::fmt::Debug;
19use std::num::NonZeroU32;
20use std::time::Duration;
21
22#[derive(NetworkBehaviour)]
24#[behaviour(prelude = "connexa::prelude::swarm::derive_prelude")]
25pub struct Behaviour<C>
26where
27 C: NetworkBehaviour,
28 <C as NetworkBehaviour>::ToSwarm: Debug + Send,
29{
30 pub addressbook: addressbook::Behaviour,
31
32 pub bitswap: Toggle<super::bitswap::Behaviour>,
33
34 pub custom: Toggle<C>,
36
37 pub peerbook: peerbook::Behaviour,
39 pub protocol: protocol::Behaviour,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
44pub enum KadResult {
45 Complete,
47 Peers(Vec<PeerId>),
49 Records(Vec<Record>),
51 Record(Record),
52}
53
54#[derive(Serialize, Deserialize, Clone, Debug)]
55pub struct RelayConfig {
56 pub max_reservations: usize,
57 pub max_reservations_per_peer: usize,
58 pub reservation_duration: Duration,
59 pub reservation_rate_limiters: Vec<RateLimit>,
60
61 pub max_circuits: usize,
62 pub max_circuits_per_peer: usize,
63 pub max_circuit_duration: Duration,
64 pub max_circuit_bytes: u64,
65 pub circuit_src_rate_limiters: Vec<RateLimit>,
66}
67
68impl Default for RelayConfig {
69 fn default() -> Self {
70 let limiters = vec![
71 RateLimit::PerPeer {
72 limit: NonZeroU32::new(30).expect("30 > 0"),
73 interval: Duration::from_secs(60 * 2),
74 },
75 RateLimit::PerIp {
76 limit: NonZeroU32::new(60).expect("60 > 0"),
77 interval: Duration::from_secs(60),
78 },
79 ];
80 Self {
81 max_reservations: 128,
82 max_reservations_per_peer: 4,
83 reservation_duration: Duration::from_secs(60 * 60),
84 reservation_rate_limiters: limiters.clone(),
85 max_circuits: 16,
86 max_circuits_per_peer: 4,
87 max_circuit_duration: Duration::from_secs(2 * 60),
88 max_circuit_bytes: 1 << 17,
89 circuit_src_rate_limiters: limiters,
90 }
91 }
92}
93
94impl RelayConfig {
95 pub fn unbounded() -> Self {
97 Self {
98 max_circuits: usize::MAX,
99 max_circuit_bytes: u64::MAX,
100 max_circuit_duration: Duration::MAX,
101 max_circuits_per_peer: usize::MAX,
102 max_reservations: usize::MAX,
103 reservation_duration: Duration::MAX,
104 max_reservations_per_peer: usize::MAX,
105 reservation_rate_limiters: vec![],
106 circuit_src_rate_limiters: vec![],
107 }
108 }
109}
110
111#[derive(Serialize, Deserialize, Clone, Debug)]
112pub struct IdentifyConfiguration {
113 pub protocol_version: String,
114 pub agent_version: String,
115 pub interval: Duration,
116 pub push_update: bool,
117 pub cache: usize,
118}
119
120impl Default for IdentifyConfiguration {
121 fn default() -> Self {
122 Self {
123 protocol_version: "/ipfs/0.1.0".into(),
124 agent_version: "rust-ipfs".into(),
125 interval: Duration::from_secs(5 * 60),
126 push_update: true,
127 cache: 100,
128 }
129 }
130}
131
132impl IdentifyConfiguration {
133 pub fn into(self, publuc_key: PublicKey) -> identify::Config {
134 identify::Config::new(self.protocol_version, publuc_key)
135 .with_agent_version(self.agent_version)
136 .with_interval(self.interval)
137 .with_push_listen_addr_updates(self.push_update)
138 .with_cache_size(self.cache)
139 }
140}
141
142impl From<RelayConfig> for relay::server::Config {
143 fn from(
144 RelayConfig {
145 max_reservations,
146 max_reservations_per_peer,
147 reservation_duration,
148 max_circuits,
149 max_circuits_per_peer,
150 max_circuit_duration,
151 max_circuit_bytes,
152 reservation_rate_limiters,
153 circuit_src_rate_limiters,
154 }: RelayConfig,
155 ) -> Self {
156 let reservation_duration = max_duration(reservation_duration);
157 let max_circuit_duration = max_duration(max_circuit_duration);
158
159 let mut config = relay::server::Config {
160 max_reservations,
161 max_reservations_per_peer,
162 reservation_duration,
163 max_circuits,
164 max_circuits_per_peer,
165 max_circuit_duration,
166 max_circuit_bytes,
167 ..Default::default()
168 };
169
170 for rate in circuit_src_rate_limiters {
171 match rate {
172 RateLimit::PerPeer { limit, interval } => {
173 config = config.circuit_src_per_peer(limit, interval);
174 }
175 RateLimit::PerIp { limit, interval } => {
176 config = config.circuit_src_per_ip(limit, interval);
177 }
178 }
179 }
180
181 for rate in reservation_rate_limiters {
182 match rate {
183 RateLimit::PerPeer { limit, interval } => {
184 config = config.reservation_rate_per_peer(limit, interval);
185 }
186 RateLimit::PerIp { limit, interval } => {
187 config = config.reservation_rate_per_ip(limit, interval);
188 }
189 }
190 }
191
192 config
193 }
194}
195
196fn max_duration(duration: Duration) -> Duration {
197 let start = web_time::Instant::now();
198 if start.checked_add(duration).is_none() {
199 return Duration::from_secs(u32::MAX as _);
200 }
201 duration
202}
203
204#[derive(Serialize, Deserialize, Clone, Debug)]
205pub enum RateLimit {
206 PerPeer {
207 limit: NonZeroU32,
208 interval: Duration,
209 },
210 PerIp {
211 limit: NonZeroU32,
212 interval: Duration,
213 },
214}
215impl<C> Behaviour<C>
216where
217 C: NetworkBehaviour,
218 <C as NetworkBehaviour>::ToSwarm: Debug + Send,
219{
220 pub(crate) fn new(
221 keypair: &Keypair,
222 options: &IpfsOptions,
223 repo: &Repo<DefaultStorage>,
224 custom: Option<C>,
225 ) -> Self {
226 let bootstrap = options.bootstrap.clone();
227
228 let protocols = options.protocols;
229
230 let peer_id = keypair.public().to_peer_id();
231
232 info!("net: starting with peer id {}", peer_id);
233
234 let bitswap = protocols
235 .bitswap
236 .then(|| {
237 let config = (options.bitswap_config)(super::bitswap::Config::default());
238 super::bitswap::Behaviour::new(repo, config)
239 })
240 .into();
241
242 let peerbook = peerbook::Behaviour::default();
243
244 let addressbook = addressbook::Behaviour::with_config(options.addr_config);
245
246 let protocol = protocol::Behaviour::default();
247 let custom = Toggle::from(custom);
248
249 let mut behaviour = Behaviour {
250 bitswap,
251 peerbook,
252 addressbook,
253 protocol,
254 custom,
255 };
256
257 for addr in bootstrap {
258 let Ok(mut opt) = IntoAddPeerOpt::into_opt(addr) else {
259 continue;
260 };
261
262 opt = opt.set_dial(true);
264
265 _ = behaviour.add_peer(opt);
266 }
267
268 behaviour
269 }
270
271 pub fn add_peer<I: IntoAddPeerOpt>(&mut self, opt: I) -> bool {
272 let opt = opt.into_opt().expect("valid entries");
273
274 self.addressbook.add_address(opt);
275
276 true
277 }
278
279 pub fn remove_peer(&mut self, peer: &PeerId) {
280 self.addressbook.remove_peer(peer);
281 }
282
283 pub fn addrs(&self) -> Vec<(PeerId, Vec<Multiaddr>)> {
284 self.peerbook.connected_peers_addrs().collect()
285 }
286
287 pub fn stop_providing_block(&mut self, cid: &Cid) {
289 info!("Finished providing block {}", cid.to_string());
290 let _key = cid.hash().to_bytes();
291 }
295
296 pub fn supported_protocols(&self) -> Vec<String> {
297 self.protocol.iter().collect::<Vec<_>>()
298 }
299}