1use cid::Cid;
7use ipfrs_core::error::Result;
8use libp2p::PeerId;
9use std::collections::{HashMap, HashSet};
10use std::sync::Arc;
11use tokio::sync::{mpsc, RwLock};
12use tracing::{debug, info};
13
14pub struct Bitswap {
16 want_list: Arc<RwLock<HashSet<Cid>>>,
18 have_list: Arc<RwLock<HashSet<Cid>>>,
20 pending_requests: Arc<RwLock<HashMap<PeerId, HashSet<Cid>>>>,
22 event_tx: mpsc::Sender<BitswapEvent>,
24 event_rx: Option<mpsc::Receiver<BitswapEvent>>,
25}
26
27#[derive(Debug, Clone)]
29pub enum BitswapEvent {
30 BlockReceived {
32 cid: Cid,
33 data: Vec<u8>,
34 from: PeerId,
35 },
36 BlockSent { cid: Cid, to: PeerId },
38 BlockRequested { cid: Cid, from: PeerId },
40 BlockNotFound { cid: Cid, peer: PeerId },
42}
43
44#[derive(Debug, Clone)]
46pub enum BitswapMessage {
47 Want(Cid),
49 Have(Cid),
51 Block { cid: Cid, data: Vec<u8> },
53 DontHave(Cid),
55}
56
57impl Bitswap {
58 pub fn new() -> Self {
60 let (event_tx, event_rx) = mpsc::channel(1024);
61
62 Self {
63 want_list: Arc::new(RwLock::new(HashSet::new())),
64 have_list: Arc::new(RwLock::new(HashSet::new())),
65 pending_requests: Arc::new(RwLock::new(HashMap::new())),
66 event_tx,
67 event_rx: Some(event_rx),
68 }
69 }
70
71 pub async fn want(&self, cid: Cid) -> Result<()> {
73 let mut want_list = self.want_list.write().await;
74 want_list.insert(cid);
75 debug!("Added to want list: {}", cid);
76 Ok(())
77 }
78
79 pub async fn cancel_want(&self, cid: &Cid) -> Result<()> {
81 let mut want_list = self.want_list.write().await;
82 want_list.remove(cid);
83 debug!("Removed from want list: {}", cid);
84 Ok(())
85 }
86
87 pub async fn have(&self, cid: Cid) -> Result<()> {
89 let mut have_list = self.have_list.write().await;
90 have_list.insert(cid);
91 debug!("Added to have list: {}", cid);
92 Ok(())
93 }
94
95 pub async fn wants(&self, cid: &Cid) -> bool {
97 let want_list = self.want_list.read().await;
98 want_list.contains(cid)
99 }
100
101 pub async fn has(&self, cid: &Cid) -> bool {
103 let have_list = self.have_list.read().await;
104 have_list.contains(cid)
105 }
106
107 pub async fn get_want_list(&self) -> HashSet<Cid> {
109 let want_list = self.want_list.read().await;
110 want_list.clone()
111 }
112
113 pub async fn get_have_list(&self) -> HashSet<Cid> {
115 let have_list = self.have_list.read().await;
116 have_list.clone()
117 }
118
119 pub async fn request_block(&self, cid: Cid, peer: PeerId) -> Result<()> {
121 let mut pending = self.pending_requests.write().await;
122 pending.entry(peer).or_insert_with(HashSet::new).insert(cid);
123 debug!("Requesting block {} from peer {}", cid, peer);
124 Ok(())
125 }
126
127 pub async fn handle_message(
129 &self,
130 message: BitswapMessage,
131 from: PeerId,
132 ) -> Result<Option<BitswapMessage>> {
133 match message {
134 BitswapMessage::Want(cid) => {
135 debug!("Peer {} wants block {}", from, cid);
137 let _ = self
138 .event_tx
139 .send(BitswapEvent::BlockRequested { cid, from })
140 .await;
141
142 if self.has(&cid).await {
144 Ok(Some(BitswapMessage::Have(cid)))
147 } else {
148 Ok(Some(BitswapMessage::DontHave(cid)))
149 }
150 }
151 BitswapMessage::Have(cid) => {
152 debug!("Peer {} has block {}", from, cid);
154
155 if self.wants(&cid).await {
157 self.request_block(cid, from).await?;
158 }
159 Ok(None)
160 }
161 BitswapMessage::Block { cid, data } => {
162 info!(
164 "Received block {} ({} bytes) from peer {}",
165 cid,
166 data.len(),
167 from
168 );
169
170 self.cancel_want(&cid).await?;
172
173 let mut pending = self.pending_requests.write().await;
175 if let Some(peer_requests) = pending.get_mut(&from) {
176 peer_requests.remove(&cid);
177 }
178
179 let _ = self
181 .event_tx
182 .send(BitswapEvent::BlockReceived { cid, data, from })
183 .await;
184
185 Ok(None)
186 }
187 BitswapMessage::DontHave(cid) => {
188 debug!("Peer {} doesn't have block {}", from, cid);
190
191 let _ = self
192 .event_tx
193 .send(BitswapEvent::BlockNotFound { cid, peer: from })
194 .await;
195
196 Ok(None)
197 }
198 }
199 }
200
201 pub async fn send_block(&self, cid: Cid, data: Vec<u8>, to: PeerId) -> Result<BitswapMessage> {
203 debug!(
204 "Sending block {} ({} bytes) to peer {}",
205 cid,
206 data.len(),
207 to
208 );
209
210 let _ = self
211 .event_tx
212 .send(BitswapEvent::BlockSent { cid, to })
213 .await;
214
215 Ok(BitswapMessage::Block { cid, data })
216 }
217
218 pub async fn get_pending_requests(&self, peer: &PeerId) -> HashSet<Cid> {
220 let pending = self.pending_requests.read().await;
221 pending.get(peer).cloned().unwrap_or_default()
222 }
223
224 pub async fn stats(&self) -> BitswapStats {
226 let want_list = self.want_list.read().await;
227 let have_list = self.have_list.read().await;
228 let pending = self.pending_requests.read().await;
229
230 BitswapStats {
231 want_list_size: want_list.len(),
232 have_list_size: have_list.len(),
233 pending_requests: pending.values().map(|s| s.len()).sum(),
234 peers_with_pending_requests: pending.len(),
235 }
236 }
237
238 pub fn take_event_receiver(&mut self) -> Option<mpsc::Receiver<BitswapEvent>> {
240 self.event_rx.take()
241 }
242}
243
244impl Default for Bitswap {
245 fn default() -> Self {
246 Self::new()
247 }
248}
249
250#[derive(Debug, Clone, Default, serde::Serialize)]
252pub struct BitswapStats {
253 pub want_list_size: usize,
255 pub have_list_size: usize,
257 pub pending_requests: usize,
259 pub peers_with_pending_requests: usize,
261}
262
263#[cfg(test)]
264mod tests {
265 use super::*;
266 use multihash_codetable::{Code, MultihashDigest};
267
268 fn test_cid() -> Cid {
269 let hash = Code::Sha2_256.digest(b"test data");
270 Cid::new_v1(0x55, hash)
271 }
272
273 fn test_peer_id() -> PeerId {
274 PeerId::random()
275 }
276
277 #[tokio::test]
278 async fn test_bitswap_creation() {
279 let bitswap = Bitswap::new();
280 let stats = bitswap.stats().await;
281
282 assert_eq!(stats.want_list_size, 0);
283 assert_eq!(stats.have_list_size, 0);
284 assert_eq!(stats.pending_requests, 0);
285 }
286
287 #[tokio::test]
288 async fn test_want_list() {
289 let bitswap = Bitswap::new();
290 let cid = test_cid();
291
292 bitswap
294 .want(cid)
295 .await
296 .expect("test: want() should succeed");
297 assert!(bitswap.wants(&cid).await);
298
299 let want_list = bitswap.get_want_list().await;
300 assert_eq!(want_list.len(), 1);
301 assert!(want_list.contains(&cid));
302
303 bitswap
305 .cancel_want(&cid)
306 .await
307 .expect("test: cancel_want() should succeed");
308 assert!(!bitswap.wants(&cid).await);
309 }
310
311 #[tokio::test]
312 async fn test_have_list() {
313 let bitswap = Bitswap::new();
314 let cid = test_cid();
315
316 bitswap
318 .have(cid)
319 .await
320 .expect("test: have() should succeed");
321 assert!(bitswap.has(&cid).await);
322
323 let have_list = bitswap.get_have_list().await;
324 assert_eq!(have_list.len(), 1);
325 assert!(have_list.contains(&cid));
326 }
327
328 #[tokio::test]
329 async fn test_request_block() {
330 let bitswap = Bitswap::new();
331 let cid = test_cid();
332 let peer = test_peer_id();
333
334 bitswap
335 .request_block(cid, peer)
336 .await
337 .expect("test: request_block() should succeed");
338
339 let pending = bitswap.get_pending_requests(&peer).await;
340 assert_eq!(pending.len(), 1);
341 assert!(pending.contains(&cid));
342 }
343
344 #[tokio::test]
345 async fn test_handle_want_message_have_block() {
346 let bitswap = Bitswap::new();
347 let cid = test_cid();
348 let peer = test_peer_id();
349
350 bitswap
352 .have(cid)
353 .await
354 .expect("test: have() should succeed");
355
356 let response = bitswap
358 .handle_message(BitswapMessage::Want(cid), peer)
359 .await
360 .expect("test: handle_message(Want) should succeed when block is in have list");
361
362 assert!(response.is_some());
363 match response
364 .expect("test: handle_message should return Some(Have) when block is in have list")
365 {
366 BitswapMessage::Have(received_cid) => assert_eq!(received_cid, cid),
367 _ => panic!("Expected Have message"),
368 }
369 }
370
371 #[tokio::test]
372 async fn test_handle_want_message_dont_have() {
373 let bitswap = Bitswap::new();
374 let cid = test_cid();
375 let peer = test_peer_id();
376
377 let response = bitswap
379 .handle_message(BitswapMessage::Want(cid), peer)
380 .await
381 .expect("test: handle_message(Want) should succeed when block is not in have list");
382
383 assert!(response.is_some());
384 match response
385 .expect("test: handle_message should return Some(DontHave) when block is absent")
386 {
387 BitswapMessage::DontHave(received_cid) => assert_eq!(received_cid, cid),
388 _ => panic!("Expected DontHave message"),
389 }
390 }
391
392 #[tokio::test]
393 async fn test_handle_have_message() {
394 let bitswap = Bitswap::new();
395 let cid = test_cid();
396 let peer = test_peer_id();
397
398 bitswap
400 .want(cid)
401 .await
402 .expect("test: want() should succeed");
403
404 let response = bitswap
406 .handle_message(BitswapMessage::Have(cid), peer)
407 .await
408 .expect("test: handle_message(Have) should succeed");
409
410 assert!(response.is_none());
411
412 let pending = bitswap.get_pending_requests(&peer).await;
414 assert_eq!(pending.len(), 1);
415 assert!(pending.contains(&cid));
416 }
417
418 #[tokio::test]
419 async fn test_handle_block_message() {
420 let bitswap = Bitswap::new();
421 let cid = test_cid();
422 let peer = test_peer_id();
423 let data = b"test block data".to_vec();
424
425 bitswap
427 .want(cid)
428 .await
429 .expect("test: want() should succeed");
430 bitswap
431 .request_block(cid, peer)
432 .await
433 .expect("test: request_block() should succeed");
434
435 let response = bitswap
437 .handle_message(
438 BitswapMessage::Block {
439 cid,
440 data: data.clone(),
441 },
442 peer,
443 )
444 .await
445 .expect("test: handle_message(Block) should succeed");
446
447 assert!(response.is_none());
448
449 assert!(!bitswap.wants(&cid).await);
451
452 let pending = bitswap.get_pending_requests(&peer).await;
454 assert_eq!(pending.len(), 0);
455 }
456
457 #[tokio::test]
458 async fn test_send_block() {
459 let bitswap = Bitswap::new();
460 let cid = test_cid();
461 let peer = test_peer_id();
462 let data = b"test block data".to_vec();
463
464 let message = bitswap
465 .send_block(cid, data.clone(), peer)
466 .await
467 .expect("test: send_block() should succeed");
468
469 match message {
470 BitswapMessage::Block {
471 cid: received_cid,
472 data: received_data,
473 } => {
474 assert_eq!(received_cid, cid);
475 assert_eq!(received_data, data);
476 }
477 _ => panic!("Expected Block message"),
478 }
479 }
480
481 #[tokio::test]
482 async fn test_bitswap_stats() {
483 let bitswap = Bitswap::new();
484 let cid1 = test_cid();
485 let cid2 = test_cid();
486 let peer = test_peer_id();
487
488 bitswap
489 .want(cid1)
490 .await
491 .expect("test: want() should succeed");
492 bitswap
493 .have(cid2)
494 .await
495 .expect("test: have() should succeed");
496 bitswap
497 .request_block(cid1, peer)
498 .await
499 .expect("test: request_block() should succeed");
500
501 let stats = bitswap.stats().await;
502
503 assert_eq!(stats.want_list_size, 1);
504 assert_eq!(stats.have_list_size, 1);
505 assert_eq!(stats.pending_requests, 1);
506 assert_eq!(stats.peers_with_pending_requests, 1);
507 }
508}