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}