litep2p/protocol/libp2p/bitswap/
handle.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
21//! Bitswap handle for communicating with the bitswap protocol implementation.
22
23use crate::{
24    protocol::libp2p::bitswap::{BlockPresenceType, WantType},
25    PeerId,
26};
27
28use cid::Cid;
29use tokio::sync::mpsc::{Receiver, Sender};
30
31use std::{
32    pin::Pin,
33    task::{Context, Poll},
34};
35
36/// Events emitted by the bitswap protocol.
37#[derive(Debug)]
38pub enum BitswapEvent {
39    /// Bitswap request.
40    Request {
41        /// Peer ID.
42        peer: PeerId,
43
44        /// Requested CIDs.
45        cids: Vec<(Cid, WantType)>,
46    },
47
48    /// Bitswap response.
49    Response {
50        /// Peer ID.
51        peer: PeerId,
52
53        /// Response entries: vector of CIDs with either block data or block presence.
54        responses: Vec<ResponseType>,
55    },
56}
57
58/// Response type for received bitswap request.
59#[derive(Debug, Clone)]
60#[cfg_attr(feature = "fuzz", derive(serde::Serialize, serde::Deserialize))]
61pub enum ResponseType {
62    /// Block.
63    Block {
64        /// CID.
65        cid: Cid,
66
67        /// Found block.
68        block: Vec<u8>,
69    },
70
71    /// Presense.
72    Presence {
73        /// CID.
74        cid: Cid,
75
76        /// Whether the requested block exists or not.
77        presence: BlockPresenceType,
78    },
79}
80
81/// Commands sent from the user to `Bitswap`.
82#[derive(Debug)]
83#[cfg_attr(feature = "fuzz", derive(serde::Serialize, serde::Deserialize))]
84pub enum BitswapCommand {
85    /// Send bitswap request.
86    SendRequest {
87        /// Peer ID.
88        peer: PeerId,
89
90        /// Requested CIDs.
91        cids: Vec<(Cid, WantType)>,
92    },
93
94    /// Send bitswap response.
95    SendResponse {
96        /// Peer ID.
97        peer: PeerId,
98
99        /// CIDs.
100        responses: Vec<ResponseType>,
101    },
102}
103
104/// Handle for communicating with the bitswap protocol.
105pub struct BitswapHandle {
106    /// RX channel for receiving bitswap events.
107    event_rx: Receiver<BitswapEvent>,
108
109    /// TX channel for sending commads to `Bitswap`.
110    cmd_tx: Sender<BitswapCommand>,
111}
112
113impl BitswapHandle {
114    /// Create new [`BitswapHandle`].
115    pub(super) fn new(event_rx: Receiver<BitswapEvent>, cmd_tx: Sender<BitswapCommand>) -> Self {
116        Self { event_rx, cmd_tx }
117    }
118
119    /// Send `request` to `peer`.
120    pub async fn send_request(&self, peer: PeerId, cids: Vec<(Cid, WantType)>) {
121        let _ = self.cmd_tx.send(BitswapCommand::SendRequest { peer, cids }).await;
122    }
123
124    /// Send `response` to `peer`.
125    pub async fn send_response(&self, peer: PeerId, responses: Vec<ResponseType>) {
126        let _ = self.cmd_tx.send(BitswapCommand::SendResponse { peer, responses }).await;
127    }
128
129    #[cfg(feature = "fuzz")]
130    /// Expose functionality for fuzzing
131    pub async fn fuzz_send_message(&mut self, command: BitswapCommand) -> crate::Result<()> {
132        let _ = self.cmd_tx.try_send(command);
133        Ok(())
134    }
135}
136
137impl futures::Stream for BitswapHandle {
138    type Item = BitswapEvent;
139
140    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
141        Pin::new(&mut self.event_rx).poll_recv(cx)
142    }
143}