Skip to content

Commit e877d0c

Browse files
committed
(fix): prefer declared external IP instead of observed address
1 parent cd76272 commit e877d0c

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

p2p/src/connection/outgoing/mod.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ pub use p2p_connection_outgoing_actions::*;
66

77
mod p2p_connection_outgoing_reducer;
88

9+
use std::net::IpAddr;
910
#[cfg(feature = "p2p-libp2p")]
1011
use std::net::SocketAddr;
1112
use std::{fmt, str::FromStr};
1213

1314
use binprot_derive::{BinProtRead, BinProtWrite};
15+
use multiaddr::{Multiaddr, Protocol};
1416
use serde::{Deserialize, Serialize};
1517
use thiserror::Error;
1618

@@ -44,6 +46,42 @@ pub struct P2pConnectionOutgoingInitLibp2pOpts {
4446
pub port: u16,
4547
}
4648

49+
impl P2pConnectionOutgoingInitLibp2pOpts {
50+
/// If the current host is local and there is a better host among the `addrs`,
51+
/// replace the current one with the better one.
52+
pub fn update_host_if_needed<'a>(&mut self, mut addrs: impl Iterator<Item = &'a Multiaddr>) {
53+
fn is_local(ip: impl Into<IpAddr>) -> bool {
54+
match ip.into() {
55+
IpAddr::V4(ip) => ip.is_loopback() || ip.is_private(),
56+
IpAddr::V6(ip) => ip.is_loopback(),
57+
}
58+
}
59+
60+
// if current dial opts is not good enough
61+
let update = match &self.host {
62+
Host::Domain(_) => false,
63+
Host::Ipv4(ip) => is_local(*ip),
64+
Host::Ipv6(ip) => is_local(*ip),
65+
};
66+
if update {
67+
// if new options is better
68+
let new = addrs.find_map(|x| {
69+
x.iter().find_map(|x| match x {
70+
Protocol::Dns4(hostname) | Protocol::Dns6(hostname) => {
71+
Some(Host::Domain(hostname.into_owned()))
72+
}
73+
Protocol::Ip4(ip) if !is_local(ip) => Some(Host::Ipv4(ip)),
74+
Protocol::Ip6(ip) if !is_local(ip) => Some(Host::Ipv6(ip)),
75+
_ => None,
76+
})
77+
});
78+
if let Some(new) = new {
79+
self.host = new;
80+
}
81+
}
82+
}
83+
}
84+
4785
pub(crate) mod libp2p_opts {
4886
use std::net::{IpAddr, SocketAddr};
4987

p2p/src/identify/p2p_identify_reducer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use openmina_core::{bug_condition, Substate};
22
use redux::ActionWithMeta;
33

44
use crate::{
5+
connection::outgoing::P2pConnectionOutgoingInitOpts,
56
disconnection::{P2pDisconnectionAction, P2pDisconnectionReason},
67
token::{BroadcastAlgorithm, DiscoveryAlgorithm, IdentifyAlgorithm, RpcAlgorithm, StreamKind},
78
P2pNetworkConnectionMuxState, P2pNetworkKadRequestAction, P2pNetworkKadState,
@@ -60,6 +61,9 @@ impl P2pState {
6061
let info = *info;
6162
if let Some(peer) = p2p_state.peers.get_mut(&peer_id) {
6263
peer.identify = Some(info.clone());
64+
if let Some(P2pConnectionOutgoingInitOpts::LibP2P(opts)) = &mut peer.dial_opts {
65+
opts.update_host_if_needed(info.listen_addrs.iter());
66+
}
6367
} else {
6468
bug_condition!(
6569
"Peer state not found for `P2pIdentifyAction::UpdatePeerInformation`"

0 commit comments

Comments
 (0)