p2p/network/select/
token.rs

1use malloc_size_of_derive::MallocSizeOf;
2use serde::{Deserialize, Serialize};
3
4use crate::Data;
5
6const MAX_TOKEN_LENGTH: usize = 256;
7
8/// Possible valid token of multistream-select protocol
9#[derive(Clone, Serialize, Deserialize, Debug, MallocSizeOf)]
10pub enum Token {
11    Handshake,
12    Na,
13    SimultaneousConnect,
14    Protocol(Protocol),
15    UnknownProtocol(Data),
16}
17
18impl Token {
19    pub const fn name(&self) -> &'static [u8] {
20        match self {
21            Self::Handshake => b"\x13/multistream/1.0.0\n",
22            Self::Na => b"\x03na\n",
23            Self::SimultaneousConnect => b"\x1d/libp2p/simultaneous-connect\n",
24            Self::Protocol(v) => v.name(),
25            Self::UnknownProtocol(_) => b"",
26        }
27    }
28
29    // WARNING: don't forget to add net protocol here
30    pub const ALL: &'static [Self] = &[
31        Token::Handshake,
32        Token::Na,
33        Token::SimultaneousConnect,
34        Token::Protocol(Protocol::Auth(AuthKind::Noise)),
35        Token::Protocol(Protocol::Mux(MuxKind::Yamux1_0_0)),
36        Token::Protocol(Protocol::Mux(MuxKind::YamuxNoNewLine1_0_0)),
37        Token::Protocol(Protocol::Stream(StreamKind::Status(
38            StatusAlgorithm::MinaNodeStatus,
39        ))),
40        Token::Protocol(Protocol::Stream(StreamKind::Bitswap(
41            BitswapAlgorithm::MinaBitswap,
42        ))),
43        Token::Protocol(Protocol::Stream(StreamKind::Bitswap(
44            BitswapAlgorithm::MinaBitswap1_0_0,
45        ))),
46        Token::Protocol(Protocol::Stream(StreamKind::Bitswap(
47            BitswapAlgorithm::MinaBitswap1_1_0,
48        ))),
49        Token::Protocol(Protocol::Stream(StreamKind::Bitswap(
50            BitswapAlgorithm::MinaBitswap1_2_0,
51        ))),
52        Token::Protocol(Protocol::Stream(StreamKind::Ping(PingAlgorithm::Ping1_0_0))),
53        Token::Protocol(Protocol::Stream(StreamKind::Identify(
54            IdentifyAlgorithm::Identify1_0_0,
55        ))),
56        Token::Protocol(Protocol::Stream(StreamKind::Identify(
57            IdentifyAlgorithm::IdentifyPush1_0_0,
58        ))),
59        Token::Protocol(Protocol::Stream(StreamKind::Discovery(
60            DiscoveryAlgorithm::Kademlia1_0_0,
61        ))),
62        Token::Protocol(Protocol::Stream(StreamKind::Broadcast(
63            BroadcastAlgorithm::Floodsub1_0_0,
64        ))),
65        Token::Protocol(Protocol::Stream(StreamKind::Broadcast(
66            BroadcastAlgorithm::Meshsub1_0_0,
67        ))),
68        Token::Protocol(Protocol::Stream(StreamKind::Broadcast(
69            BroadcastAlgorithm::Meshsub1_1_0,
70        ))),
71        Token::Protocol(Protocol::Stream(StreamKind::Rpc(RpcAlgorithm::Rpc0_0_1))),
72    ];
73}
74
75#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
76pub enum Protocol {
77    Auth(AuthKind),
78    Mux(MuxKind),
79    Stream(StreamKind),
80}
81
82impl malloc_size_of::MallocSizeOf for Protocol {
83    fn size_of(&self, _ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
84        0
85    }
86}
87
88impl Protocol {
89    pub const fn name(&self) -> &'static [u8] {
90        match self {
91            Self::Auth(v) => v.name(),
92            Self::Mux(v) => v.name(),
93            Self::Stream(v) => v.name(),
94        }
95    }
96
97    pub const fn name_str(&self) -> &'static str {
98        match self {
99            Self::Auth(v) => v.name_str(),
100            Self::Mux(v) => v.name_str(),
101            Self::Stream(v) => v.name_str(),
102        }
103    }
104}
105
106#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
107pub enum AuthKind {
108    Noise,
109}
110
111impl AuthKind {
112    pub const fn name(&self) -> &'static [u8] {
113        b"\x07/noise\n"
114    }
115
116    pub const fn name_str(&self) -> &'static str {
117        "/noise"
118    }
119}
120
121#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
122pub enum MuxKind {
123    Yamux1_0_0,
124    YamuxNoNewLine1_0_0,
125}
126
127impl MuxKind {
128    pub const fn name(&self) -> &'static [u8] {
129        match self {
130            Self::Yamux1_0_0 => b"\x12/coda/yamux/1.0.0\n",
131            Self::YamuxNoNewLine1_0_0 => b"\x11/coda/yamux/1.0.0",
132        }
133    }
134
135    pub const fn name_str(&self) -> &'static str {
136        match self {
137            Self::Yamux1_0_0 => "/coda/yamux/1.0.0",
138            Self::YamuxNoNewLine1_0_0 => "/coda/yamux/1.0.0",
139        }
140    }
141}
142
143#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
144pub enum StreamKind {
145    Status(StatusAlgorithm),
146    Bitswap(BitswapAlgorithm),
147    Ping(PingAlgorithm),
148    Identify(IdentifyAlgorithm),
149    Discovery(DiscoveryAlgorithm),
150    Broadcast(BroadcastAlgorithm),
151    Rpc(RpcAlgorithm),
152}
153
154impl malloc_size_of::MallocSizeOf for StreamKind {
155    fn size_of(&self, _ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
156        0
157    }
158}
159
160impl StreamKind {
161    pub const fn name(&self) -> &'static [u8] {
162        match self {
163            Self::Status(v) => v.name(),
164            Self::Bitswap(v) => v.name(),
165            Self::Ping(v) => v.name(),
166            Self::Identify(v) => v.name(),
167            Self::Discovery(v) => v.name(),
168            Self::Broadcast(v) => v.name(),
169            Self::Rpc(v) => v.name(),
170        }
171    }
172
173    pub const fn name_str(&self) -> &'static str {
174        match self {
175            Self::Status(v) => v.name_str(),
176            Self::Bitswap(v) => v.name_str(),
177            Self::Ping(v) => v.name_str(),
178            Self::Identify(v) => v.name_str(),
179            Self::Discovery(v) => v.name_str(),
180            Self::Broadcast(v) => v.name_str(),
181            Self::Rpc(v) => v.name_str(),
182        }
183    }
184}
185
186#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
187pub enum StatusAlgorithm {
188    MinaNodeStatus,
189}
190
191impl StatusAlgorithm {
192    pub const fn name(&self) -> &'static [u8] {
193        match self {
194            Self::MinaNodeStatus => b"\x12/mina/node-status\n",
195        }
196    }
197
198    pub const fn name_str(&self) -> &'static str {
199        match self {
200            Self::MinaNodeStatus => "/mina/node-status",
201        }
202    }
203}
204
205#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
206pub enum BitswapAlgorithm {
207    MinaBitswap,
208    MinaBitswap1_0_0,
209    MinaBitswap1_1_0,
210    MinaBitswap1_2_0,
211}
212
213impl malloc_size_of::MallocSizeOf for BitswapAlgorithm {
214    fn size_of(&self, _ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
215        0
216    }
217}
218
219impl BitswapAlgorithm {
220    pub const fn name(&self) -> &'static [u8] {
221        match self {
222            Self::MinaBitswap => b"\x24/mina/bitswap-exchange/ipfs/bitswap\n",
223            Self::MinaBitswap1_0_0 => b"\x2a/mina/bitswap-exchange/ipfs/bitswap/1.0.0\n",
224            Self::MinaBitswap1_1_0 => b"\x2a/mina/bitswap-exchange/ipfs/bitswap/1.1.0\n",
225            Self::MinaBitswap1_2_0 => b"\x2a/mina/bitswap-exchange/ipfs/bitswap/1.2.0\n",
226        }
227    }
228
229    pub const fn name_str(&self) -> &'static str {
230        match self {
231            Self::MinaBitswap => "/mina/bitswap-exchange/ipfs/bitswap",
232            Self::MinaBitswap1_0_0 => "/mina/bitswap-exchange/ipfs/bitswap/1.0.0",
233            Self::MinaBitswap1_1_0 => "/mina/bitswap-exchange/ipfs/bitswap/1.1.0",
234            Self::MinaBitswap1_2_0 => "/mina/bitswap-exchange/ipfs/bitswap/1.2.0",
235        }
236    }
237}
238
239#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
240pub enum PingAlgorithm {
241    Ping1_0_0,
242}
243
244impl PingAlgorithm {
245    pub const fn name(&self) -> &'static [u8] {
246        match self {
247            Self::Ping1_0_0 => b"\x11/ipfs/ping/1.0.0\n",
248        }
249    }
250
251    pub const fn name_str(&self) -> &'static str {
252        match self {
253            Self::Ping1_0_0 => "/ipfs/ping/1.0.0",
254        }
255    }
256}
257
258#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
259pub enum IdentifyAlgorithm {
260    Identify1_0_0,
261    IdentifyPush1_0_0,
262}
263
264impl IdentifyAlgorithm {
265    pub const fn name(&self) -> &'static [u8] {
266        match self {
267            Self::Identify1_0_0 => b"\x0f/ipfs/id/1.0.0\n",
268            Self::IdentifyPush1_0_0 => b"\x14/ipfs/id/push/1.0.0\n",
269        }
270    }
271
272    pub const fn name_str(&self) -> &'static str {
273        match self {
274            Self::Identify1_0_0 => "/ipfs/id/1.0.0",
275            Self::IdentifyPush1_0_0 => "/ipfs/id/push/1.0.0",
276        }
277    }
278}
279
280#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
281pub enum DiscoveryAlgorithm {
282    Kademlia1_0_0,
283}
284
285impl DiscoveryAlgorithm {
286    pub const fn name(&self) -> &'static [u8] {
287        match self {
288            Self::Kademlia1_0_0 => b"\x10/coda/kad/1.0.0\n",
289        }
290    }
291
292    pub const fn name_str(&self) -> &'static str {
293        match self {
294            Self::Kademlia1_0_0 => "/coda/kad/1.0.0",
295        }
296    }
297}
298
299#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
300pub enum BroadcastAlgorithm {
301    Floodsub1_0_0,
302    Meshsub1_0_0,
303    Meshsub1_1_0,
304}
305
306impl malloc_size_of::MallocSizeOf for BroadcastAlgorithm {
307    fn size_of(&self, _ops: &mut malloc_size_of::MallocSizeOfOps) -> usize {
308        0
309    }
310}
311
312impl BroadcastAlgorithm {
313    pub const fn name(&self) -> &'static [u8] {
314        match self {
315            Self::Floodsub1_0_0 => b"\x10/floodsub/1.0.0\n",
316            Self::Meshsub1_0_0 => b"\x0f/meshsub/1.0.0\n",
317            Self::Meshsub1_1_0 => b"\x0f/meshsub/1.1.0\n",
318        }
319    }
320
321    pub const fn name_str(&self) -> &'static str {
322        match self {
323            Self::Floodsub1_0_0 => "/floodsub/1.0.0",
324            Self::Meshsub1_0_0 => "/meshsub/1.0.0",
325            Self::Meshsub1_1_0 => "/meshsub/1.1.0",
326        }
327    }
328}
329
330#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)]
331pub enum RpcAlgorithm {
332    Rpc0_0_1,
333}
334
335impl RpcAlgorithm {
336    pub const fn name(&self) -> &'static [u8] {
337        match self {
338            Self::Rpc0_0_1 => b"\x10coda/rpcs/0.0.1\n",
339        }
340    }
341
342    pub const fn name_str(&self) -> &'static str {
343        match self {
344            Self::Rpc0_0_1 => "coda/rpcs/0.0.1",
345        }
346    }
347}
348
349#[derive(Default, Serialize, Deserialize, Debug, Clone, MallocSizeOf)]
350pub struct State {
351    pub buffer: Vec<u8>,
352}
353
354#[derive(Debug)]
355pub struct ParseTokenError;
356
357impl State {
358    pub fn put(&mut self, data: &[u8]) {
359        self.buffer.extend_from_slice(data);
360    }
361
362    /// return protocol name followed by the rest of unparsed data
363    /// use `State::consume` after return some parsed token
364    pub fn parse_token(&mut self) -> Result<Option<Token>, ParseTokenError> {
365        use unsigned_varint::decode::{self, Error::*};
366
367        let (len, rem) = match decode::usize(&self.buffer) {
368            Ok(v) => v,
369            Err(Insufficient) => return Ok(None),
370            Err(_) => return Err(ParseTokenError),
371        };
372        let len_length = self.buffer.len() - rem.len();
373
374        if len > MAX_TOKEN_LENGTH {
375            return Err(ParseTokenError);
376        }
377
378        if len_length > MAX_TOKEN_LENGTH {
379            return Err(ParseTokenError);
380        }
381
382        if self.buffer.len() < len_length + len {
383            return Ok(None);
384        }
385
386        // buffer content should match one of tokens
387        let token = Token::ALL
388            .iter()
389            .find(|t| t.name() == &self.buffer[..(len_length + len)]);
390        let name = self.buffer.drain(..(len_length + len)).collect::<Vec<_>>();
391        Ok(Some(token.cloned().unwrap_or(Token::UnknownProtocol(
392            Data(name.into_boxed_slice()),
393        ))))
394    }
395}