litep2p/protocol/libp2p/ping/
config.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
21use crate::{
22    codec::ProtocolCodec, protocol::libp2p::ping::PingEvent, types::protocol::ProtocolName,
23    DEFAULT_CHANNEL_SIZE,
24};
25use std::time::Duration;
26
27use futures::Stream;
28use tokio::sync::mpsc::{channel, Sender};
29use tokio_stream::wrappers::ReceiverStream;
30
31/// IPFS Ping protocol name as a string.
32pub const PROTOCOL_NAME: &str = "/ipfs/ping/1.0.0";
33
34/// Size for `/ipfs/ping/1.0.0` payloads.
35const PING_PAYLOAD_SIZE: usize = 32;
36
37/// Maximum PING failures.
38const MAX_FAILURES: usize = 3;
39
40/// Ping interval must be set to < 10 secs, because litep2p versions before
41/// <https://github.com/paritytech/litep2p/pull/416> reset the inbound substream if not receive
42/// the payload within 10 seconds of opening the substream.
43pub const PING_INTERVAL: Duration = Duration::from_secs(5);
44
45/// Ping configuration.
46pub struct Config {
47    /// Protocol name.
48    pub(crate) protocol: ProtocolName,
49
50    /// Codec used by the protocol.
51    pub(crate) codec: ProtocolCodec,
52
53    /// Maximum failures before the peer is considered unreachable.
54    pub(crate) max_failures: usize,
55
56    /// TX channel for sending events to the user protocol.
57    pub(crate) tx_event: Sender<PingEvent>,
58
59    pub(crate) ping_interval: Duration,
60}
61
62impl Config {
63    /// Create new [`Config`] with default values.
64    ///
65    /// Returns a config that is given to `Litep2pConfig` and an event stream for [`PingEvent`]s.
66    pub fn default() -> (Self, Box<dyn Stream<Item = PingEvent> + Send + Unpin>) {
67        let (tx_event, rx_event) = channel(DEFAULT_CHANNEL_SIZE);
68
69        (
70            Self {
71                tx_event,
72                ping_interval: PING_INTERVAL,
73                max_failures: MAX_FAILURES,
74                protocol: ProtocolName::from(PROTOCOL_NAME),
75                codec: ProtocolCodec::Identity(PING_PAYLOAD_SIZE),
76            },
77            Box::new(ReceiverStream::new(rx_event)),
78        )
79    }
80}
81
82/// Ping configuration builder.
83pub struct ConfigBuilder {
84    /// Protocol name.
85    protocol: ProtocolName,
86
87    /// Codec used by the protocol.
88    codec: ProtocolCodec,
89
90    /// Maximum failures before the peer is considered unreachable.
91    max_failures: usize,
92
93    /// Interval between outbound pings.
94    ping_interval: Duration,
95}
96
97impl Default for ConfigBuilder {
98    fn default() -> Self {
99        Self::new()
100    }
101}
102
103impl ConfigBuilder {
104    /// Create new default [`Config`] which can be modified by the user.
105    pub fn new() -> Self {
106        Self {
107            ping_interval: PING_INTERVAL,
108            max_failures: MAX_FAILURES,
109            protocol: ProtocolName::from(PROTOCOL_NAME),
110            codec: ProtocolCodec::Identity(PING_PAYLOAD_SIZE),
111        }
112    }
113
114    /// Set maximum failures the protocol.
115    pub fn with_max_failure(mut self, max_failures: usize) -> Self {
116        self.max_failures = max_failures;
117        self
118    }
119
120    /// Set ping interval.
121    ///
122    /// The default is 5 seconds and should be kept like this for compatibility
123    /// with litep2p <= v0.13.0.
124    pub fn with_ping_interval(mut self, ping_interval: Duration) -> Self {
125        self.ping_interval = ping_interval;
126        self
127    }
128
129    /// Build [`Config`].
130    pub fn build(self) -> (Config, Box<dyn Stream<Item = PingEvent> + Send + Unpin>) {
131        let (tx_event, rx_event) = channel(DEFAULT_CHANNEL_SIZE);
132
133        (
134            Config {
135                tx_event,
136                ping_interval: self.ping_interval,
137                max_failures: self.max_failures,
138                protocol: self.protocol,
139                codec: self.codec,
140            },
141            Box::new(ReceiverStream::new(rx_event)),
142        )
143    }
144}