use std::net::SocketAddr;
use zebra_chain::parameters::Network;
use crate::PeerSocketAddr;
use AttributePreference::*;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum AttributePreference {
Preferred,
Acceptable,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct PeerPreference {
canonical_port: AttributePreference,
}
impl AttributePreference {
pub fn preferred_from(is_preferred: bool) -> Self {
if is_preferred {
Preferred
} else {
Acceptable
}
}
#[allow(dead_code)]
pub fn is_preferred(&self) -> bool {
match self {
Preferred => true,
Acceptable => false,
}
}
}
impl PeerPreference {
pub fn new(
peer_addr: impl Into<PeerSocketAddr>,
network: impl Into<Option<Network>>,
) -> Result<PeerPreference, &'static str> {
let peer_addr = peer_addr.into();
address_is_valid_for_outbound_connections(peer_addr, network)?;
let canonical_port =
AttributePreference::preferred_from([8232, 18232].contains(&peer_addr.port()));
Ok(PeerPreference { canonical_port })
}
}
pub fn address_is_valid_for_outbound_connections(
peer_addr: PeerSocketAddr,
network: impl Into<Option<Network>>,
) -> Result<(), &'static str> {
if peer_addr.ip().is_unspecified() {
return Err("invalid peer IP address: unspecified addresses can not be used for outbound connections");
}
if peer_addr.port() == 0 {
return Err(
"invalid peer port: unspecified ports can not be used for outbound connections",
);
}
address_is_valid_for_inbound_listeners(*peer_addr, network)
}
pub fn address_is_valid_for_inbound_listeners(
listener_addr: SocketAddr,
network: impl Into<Option<Network>>,
) -> Result<(), &'static str> {
if let Some(network) = network.into() {
if listener_addr.port() == network.default_port() {
return Ok(());
}
if listener_addr.port() == 8232 {
return Err(
"invalid peer port: port is for Mainnet, but this node is configured for Testnet",
);
} else if listener_addr.port() == 18232 {
return Err(
"invalid peer port: port is for Testnet, but this node is configured for Mainnet",
);
}
}
if listener_addr.port() == 18344 {
return Err(
"invalid peer port: port is for Regtest, but Zebra does not support that network",
);
} else if [8033, 18033, 16125, 26125].contains(&listener_addr.port()) {
return Err("invalid peer port: port is for a non-Zcash coin");
}
Ok(())
}