Skip to main content

forest/libp2p_bitswap/
message.rs

1// Copyright 2019-2026 ChainSafe Systems
2// SPDX-License-Identifier: Apache-2.0, MIT
3
4use super::bitswap_pb::mod_Message::{BlockPresenceType, Wantlist, mod_Wantlist::WantType};
5use serde::{Deserialize, Serialize};
6
7use crate::libp2p_bitswap::{prefix::Prefix, *};
8
9/// Type of a `bitswap` request
10#[derive(Debug, Clone, Copy, Eq, PartialEq, Deserialize, Serialize)]
11pub enum RequestType {
12    Have,
13    Block,
14}
15
16impl From<WantType> for RequestType {
17    fn from(value: WantType) -> Self {
18        match value {
19            WantType::Have => RequestType::Have,
20            WantType::Block => RequestType::Block,
21        }
22    }
23}
24
25impl From<RequestType> for WantType {
26    fn from(value: RequestType) -> Self {
27        match value {
28            RequestType::Have => WantType::Have,
29            RequestType::Block => WantType::Block,
30        }
31    }
32}
33
34/// `Bitswap` request type
35#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
36pub struct BitswapRequest {
37    pub ty: RequestType,
38    pub cid: Cid,
39    pub send_dont_have: bool,
40    pub cancel: bool,
41}
42
43impl BitswapRequest {
44    pub fn new_have(cid: Cid) -> Self {
45        Self {
46            ty: RequestType::Have,
47            cid,
48            send_dont_have: false,
49            cancel: false,
50        }
51    }
52
53    pub fn new_block(cid: Cid) -> Self {
54        Self {
55            ty: RequestType::Block,
56            cid,
57            send_dont_have: false,
58            cancel: false,
59        }
60    }
61
62    pub fn send_dont_have(mut self, b: bool) -> Self {
63        self.send_dont_have = b;
64        self
65    }
66
67    pub fn new_cancel(cid: Cid) -> Self {
68        // Matches `https://github.com/ipfs/go-libipfs/blob/v0.6.0/bitswap/message/message.go#L309`
69        Self {
70            ty: RequestType::Block,
71            cid,
72            send_dont_have: false,
73            cancel: true,
74        }
75    }
76}
77
78/// `Bitswap` response type
79#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
80pub enum BitswapResponse {
81    Have(bool),
82    Block(Vec<u8>),
83}
84
85/// `Bitswap` message Enum type that is either a [`BitswapRequest`] or a
86/// [`BitswapResponse`]
87#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
88pub enum BitswapMessage {
89    Request(BitswapRequest),
90    Response(Cid, BitswapResponse),
91}
92
93impl BitswapMessage {
94    pub fn into_proto(self) -> IOResult<bitswap_pb::Message> {
95        let mut msg = bitswap_pb::Message::default();
96        match self {
97            Self::Request(BitswapRequest {
98                ty,
99                cid,
100                send_dont_have,
101                cancel,
102            }) => {
103                let wantlist = Wantlist {
104                    entries: vec![bitswap_pb::mod_Message::mod_Wantlist::Entry {
105                        block: cid.to_bytes(),
106                        wantType: ty.into(),
107                        sendDontHave: send_dont_have,
108                        cancel,
109                        priority: 1,
110                    }],
111                    ..Default::default()
112                };
113
114                msg.wantlist = Some(wantlist);
115            }
116            Self::Response(cid, BitswapResponse::Have(have)) => {
117                msg.blockPresences
118                    .push(bitswap_pb::mod_Message::BlockPresence {
119                        cid: cid.to_bytes(),
120                        type_pb: if have {
121                            BlockPresenceType::Have
122                        } else {
123                            BlockPresenceType::DontHave
124                        },
125                    });
126            }
127            Self::Response(cid, BitswapResponse::Block(bytes)) => {
128                msg.payload.push(bitswap_pb::mod_Message::Block {
129                    prefix: Prefix::from(&cid).to_bytes(),
130                    data: bytes,
131                });
132            }
133        }
134        Ok(msg)
135    }
136}