urma_node/
peer_transport.rs1use crate::{
6 Error, peer::REQUEST_TIMEOUT, peer_codec::Codec, peer_limits::Limits, peer_protocol::PROTOCOL,
7};
8use libp2p::{
9 Multiaddr, StreamProtocol, Swarm, SwarmBuilder, identify, identity::Keypair,
10 multiaddr::Protocol, noise, request_response, swarm::NetworkBehaviour, tcp, yamux,
11};
12use std::{
13 num::{NonZeroU8, NonZeroUsize},
14 time::Duration,
15};
16
17#[derive(NetworkBehaviour)]
18pub(crate) struct Behaviour {
19 pub(crate) limits: Limits,
21 pub(crate) records: request_response::Behaviour<Codec>,
22 pub(crate) identify: identify::Behaviour,
23}
24
25impl Behaviour {
26 const IDENTIFY_PROTOCOL: &str = "/urma/node/4";
27}
28
29#[derive(Clone, Debug, PartialEq, Eq)]
32pub enum DnsMode {
33 System,
34 Refuse(String),
35}
36
37#[derive(Clone, Debug, PartialEq, Eq)]
39pub enum Dns {
40 Available,
41 Unavailable(String),
42}
43
44impl Dns {
45 pub fn admits(&self, address: &Multiaddr) -> Result<(), Error> {
47 let named = address.iter().any(|part| {
48 matches!(
49 part,
50 Protocol::Dns(_) | Protocol::Dns4(_) | Protocol::Dns6(_) | Protocol::Dnsaddr(_)
51 )
52 });
53 match (self, named) {
54 (Self::Unavailable(cause), true) => Err(Error::Transport(format!(
55 "system DNS resolver unavailable: {cause}"
56 ))),
57 (Self::Unavailable(_) | Self::Available, false) | (Self::Available, true) => Ok(()),
58 }
59 }
60}
61
62fn behaviour(identity: &Keypair) -> Behaviour {
63 let records = request_response::Behaviour::with_codec(
64 Codec,
65 [(
66 StreamProtocol::new(PROTOCOL),
67 request_response::ProtocolSupport::Full,
68 )],
69 request_response::Config::default()
70 .with_request_timeout(REQUEST_TIMEOUT)
71 .with_max_concurrent_streams(2),
72 );
73 let identify = identify::Behaviour::new(
74 identify::Config::new(Behaviour::IDENTIFY_PROTOCOL.into(), identity.public())
75 .with_agent_version(format!("urma-node/{}", env!("CARGO_PKG_VERSION"))),
76 );
77 Behaviour {
78 limits: Limits::default(),
79 records,
80 identify,
81 }
82}
83
84fn multiplexer() -> yamux::Config {
85 let mut config = yamux::Config::default();
86 config.set_max_num_streams(4);
88 config.set_max_buffer_size(256 * 1024);
89 config.set_receive_window_size(256 * 1024);
90 config
91}
92
93fn configure(config: libp2p::swarm::Config) -> libp2p::swarm::Config {
94 config
95 .with_notify_handler_buffer_size(NonZeroUsize::new(2).unwrap())
96 .with_per_connection_event_buffer_size(2)
97 .with_max_negotiating_inbound_streams(2)
98 .with_dial_concurrency_factor(NonZeroU8::MIN)
99 .with_idle_connection_timeout(Duration::from_secs(20))
100}
101
102fn transport_error(error: impl std::fmt::Display) -> Error {
103 Error::Invalid(format!("peer transport: {error}"))
104}
105
106fn behaviour_error(error: impl std::fmt::Display) -> Error {
107 Error::Invalid(format!("peer behaviour: {error}"))
108}
109
110pub(crate) fn swarm(identity: Keypair, mode: &DnsMode) -> Result<(Swarm<Behaviour>, Dns), Error> {
113 let cause = match mode {
114 DnsMode::System => {
115 let tcp = SwarmBuilder::with_existing_identity(identity.clone())
116 .with_tokio()
117 .with_tcp(
118 tcp::Config::default().nodelay(true),
119 noise::Config::new,
120 multiplexer,
121 )
122 .map_err(transport_error)?;
123 match tcp.with_dns() {
124 Ok(resolving) => {
125 let swarm = resolving
126 .with_behaviour(behaviour)
127 .map_err(behaviour_error)?
128 .with_swarm_config(configure)
129 .with_connection_timeout(Duration::from_secs(5))
130 .build();
131 return Ok((swarm, Dns::Available));
132 }
133 Err(error) => error.to_string(),
134 }
135 }
136 DnsMode::Refuse(cause) => cause.clone(),
137 };
138 tracing::warn!(%cause, "system DNS resolver unavailable; overlay runs for IP-literal peers only");
139 let swarm = SwarmBuilder::with_existing_identity(identity)
140 .with_tokio()
141 .with_tcp(
142 tcp::Config::default().nodelay(true),
143 noise::Config::new,
144 multiplexer,
145 )
146 .map_err(transport_error)?
147 .with_behaviour(behaviour)
148 .map_err(behaviour_error)?
149 .with_swarm_config(configure)
150 .with_connection_timeout(Duration::from_secs(5))
151 .build();
152 Ok((swarm, Dns::Unavailable(cause)))
153}