58 lines
2.0 KiB
Rust
58 lines
2.0 KiB
Rust
use crate::common::network_startup::is_public_network_address;
|
|
use crate::Arc;
|
|
use crate::Mutex;
|
|
use crate::SocketAddr;
|
|
use crate::TcpStream;
|
|
|
|
pub fn endpoint_port(ip_port: &str) -> Option<u16> {
|
|
ip_port
|
|
.rsplit_once(':')
|
|
.and_then(|(_, port)| port.parse::<u16>().ok())
|
|
}
|
|
|
|
// Verify the announced endpoint is public and matches the connected peer.
|
|
pub async fn ip_test(ip_port: &str, stream: &Arc<Mutex<TcpStream>>) -> bool {
|
|
// Private, loopback, malformed, and otherwise non-public addresses
|
|
// are rejected before comparing them with the connected socket.
|
|
if !is_public_network_address(ip_port) {
|
|
return false;
|
|
}
|
|
|
|
let stream_guard = stream.lock().await;
|
|
let remote_addr = stream_guard.peer_addr();
|
|
|
|
// Strip the port from either IPv4 host:port or bracketed IPv6
|
|
// [host]:port forms before comparing against the socket address.
|
|
let submitted_ip = ip_port
|
|
.strip_prefix('[')
|
|
.and_then(|value| value.split_once(']').map(|(ip, _)| ip))
|
|
.or_else(|| ip_port.rsplit_once(':').map(|(ip, _)| ip))
|
|
.unwrap_or(ip_port);
|
|
|
|
remote_addr.is_ok_and(|addr| addr.ip().to_string() == submitted_ip)
|
|
}
|
|
|
|
// check if port is open
|
|
pub async fn is_port_open(ip_port: &str) -> Result<bool, Box<dyn std::error::Error>> {
|
|
// Port 0 is the explicit client marker; it is never a miner endpoint.
|
|
if endpoint_port(ip_port) == Some(0) {
|
|
return Ok(false);
|
|
}
|
|
|
|
// A successful outbound connect confirms the peer can accept inbound
|
|
// node traffic on the port it advertised.
|
|
let Ok(addr) = ip_port.parse::<SocketAddr>() else {
|
|
return Ok(false);
|
|
};
|
|
match tokio::net::TcpStream::connect(addr).await {
|
|
Ok(_) => Ok(true),
|
|
Err(_) => Ok(false),
|
|
}
|
|
}
|
|
|
|
// verify connecting client time is within 1 second of our own.
|
|
pub fn is_within_one_second(timestamp1: u32, timestamp2: u32) -> bool {
|
|
let duration = timestamp1.wrapping_sub(timestamp2);
|
|
duration <= 1 || timestamp2.wrapping_sub(timestamp1) <= 1
|
|
}
|