referrerpolicy=no-referrer-when-downgrade

sc_network/litep2p/shim/notification/
config.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! `litep2p` notification protocol configuration.
20
21use crate::{
22	config::{MultiaddrWithPeerId, NonReservedPeerMode, NotificationHandshake, SetConfig},
23	litep2p::shim::notification::{
24		peerset::{Peerset, PeersetCommand},
25		NotificationProtocol,
26	},
27	peer_store::PeerStoreProvider,
28	service::{metrics::NotificationMetrics, traits::NotificationConfig},
29	NotificationService, ProtocolName,
30};
31
32use litep2p::protocol::notification::{Config, ConfigBuilder};
33
34use sc_utils::mpsc::TracingUnboundedSender;
35
36use std::sync::{atomic::AtomicUsize, Arc};
37
38/// Handle for controlling the notification protocol.
39#[derive(Debug, Clone)]
40pub struct ProtocolControlHandle {
41	/// TX channel for sending commands to `Peerset` of the notification protocol.
42	pub tx: TracingUnboundedSender<PeersetCommand>,
43
44	/// Peers currently connected to this protocol.
45	pub connected_peers: Arc<AtomicUsize>,
46}
47
48impl ProtocolControlHandle {
49	/// Create new [`ProtocolControlHandle`].
50	pub fn new(
51		tx: TracingUnboundedSender<PeersetCommand>,
52		connected_peers: Arc<AtomicUsize>,
53	) -> Self {
54		Self { tx, connected_peers }
55	}
56}
57
58/// Configuration for the notification protocol.
59#[derive(Debug)]
60pub struct NotificationProtocolConfig {
61	/// Name of the notifications protocols of this set. A substream on this set will be
62	/// considered established once this protocol is open.
63	pub protocol_name: ProtocolName,
64
65	/// Maximum allowed size of single notifications.
66	max_notification_size: usize,
67
68	/// Base configuration.
69	set_config: SetConfig,
70
71	/// `litep2p` notification config.
72	pub config: Config,
73
74	/// Handle for controlling the notification protocol.
75	pub handle: ProtocolControlHandle,
76}
77
78impl NotificationProtocolConfig {
79	// Create new [`NotificationProtocolConfig`].
80	pub fn new(
81		protocol_name: ProtocolName,
82		fallback_names: Vec<ProtocolName>,
83		max_notification_size: usize,
84		handshake: Option<NotificationHandshake>,
85		set_config: SetConfig,
86		metrics: NotificationMetrics,
87		peerstore_handle: Arc<dyn PeerStoreProvider>,
88	) -> (Self, Box<dyn NotificationService>) {
89		// create `Peerset`/`Peerstore` handle for the protocol
90		let connected_peers = Arc::new(Default::default());
91		let (peerset, peerset_tx) = Peerset::new(
92			protocol_name.clone(),
93			set_config.out_peers as usize,
94			set_config.in_peers as usize,
95			set_config.non_reserved_mode == NonReservedPeerMode::Deny,
96			set_config.reserved_nodes.iter().map(|address| address.peer_id).collect(),
97			Arc::clone(&connected_peers),
98			peerstore_handle,
99		);
100
101		// create `litep2p` notification protocol configuration for the protocol
102		//
103		// NOTE: currently only dummy value is given as the handshake as protocols (apart from
104		// syncing) are not configuring their own handshake and instead default to role being the
105		// handshake. As the time of writing this, most protocols are not aware of the role and
106		// that should be refactored in the future.
107		let (config, handle) = ConfigBuilder::new(protocol_name.clone().into())
108			.with_handshake(handshake.map_or(vec![1], |handshake| (*handshake).to_vec()))
109			.with_max_size(max_notification_size as usize)
110			.with_auto_accept_inbound(true)
111			.with_fallback_names(fallback_names.into_iter().map(From::from).collect())
112			.build();
113
114		// initialize the actual object implementing `NotificationService` and combine the
115		// `litep2p::NotificationHandle` with `Peerset` to implement a full and independent
116		// notification protocol runner
117		let protocol = NotificationProtocol::new(protocol_name.clone(), handle, peerset, metrics);
118
119		(
120			Self {
121				protocol_name,
122				max_notification_size,
123				set_config,
124				config,
125				handle: ProtocolControlHandle::new(peerset_tx, connected_peers),
126			},
127			Box::new(protocol),
128		)
129	}
130
131	/// Get reference to protocol name.
132	pub fn protocol_name(&self) -> &ProtocolName {
133		&self.protocol_name
134	}
135
136	/// Get reference to `SetConfig`.
137	pub fn set_config(&self) -> &SetConfig {
138		&self.set_config
139	}
140
141	/// Modifies the configuration to allow non-reserved nodes.
142	pub fn allow_non_reserved(&mut self, in_peers: u32, out_peers: u32) {
143		self.set_config.in_peers = in_peers;
144		self.set_config.out_peers = out_peers;
145		self.set_config.non_reserved_mode = NonReservedPeerMode::Accept;
146	}
147
148	/// Add a node to the list of reserved nodes.
149	pub fn add_reserved(&mut self, peer: MultiaddrWithPeerId) {
150		self.set_config.reserved_nodes.push(peer);
151	}
152
153	/// Get maximum notification size.
154	pub fn max_notification_size(&self) -> usize {
155		self.max_notification_size
156	}
157}
158
159impl NotificationConfig for NotificationProtocolConfig {
160	fn set_config(&self) -> &SetConfig {
161		&self.set_config
162	}
163
164	/// Get reference to protocol name.
165	fn protocol_name(&self) -> &ProtocolName {
166		&self.protocol_name
167	}
168}