use crate::data::error::{Error, Result};
use ant_protocol::transport::{
CoreNodeConfig, IPDiversityConfig, MultiAddr, NodeMode, P2PNode, PeerId,
};
use ant_protocol::MAX_WIRE_MESSAGE_SIZE;
use std::net::SocketAddr;
use std::sync::Arc;
pub struct Network {
node: Arc<P2PNode>,
}
impl Network {
pub async fn new(
bootstrap_peers: &[SocketAddr],
allow_loopback: bool,
ipv6: bool,
) -> Result<Self> {
let mut core_config = CoreNodeConfig::builder()
.port(0)
.ipv6(ipv6)
.local(allow_loopback)
.mode(NodeMode::Client)
.max_message_size(MAX_WIRE_MESSAGE_SIZE)
.build()
.map_err(|e| Error::Network(format!("Failed to create core config: {e}")))?;
core_config.diversity_config = Some(IPDiversityConfig::permissive());
core_config.bootstrap_peers = bootstrap_peers
.iter()
.map(|addr| MultiAddr::quic(*addr))
.collect();
let node = P2PNode::new(core_config)
.await
.map_err(|e| Error::Network(format!("Failed to create P2P node: {e}")))?;
node.start()
.await
.map_err(|e| Error::Network(format!("Failed to start P2P node: {e}")))?;
Ok(Self {
node: Arc::new(node),
})
}
#[must_use]
pub fn from_node(node: Arc<P2PNode>) -> Self {
Self { node }
}
#[must_use]
pub fn node(&self) -> &Arc<P2PNode> {
&self.node
}
#[must_use]
pub fn peer_id(&self) -> &PeerId {
self.node.peer_id()
}
pub async fn find_closest_peers(
&self,
target: &[u8; 32],
count: usize,
) -> Result<Vec<(PeerId, Vec<MultiAddr>)>> {
let local_peer_id = self.node.peer_id();
let closest_nodes = self
.node
.dht()
.find_closest_nodes(target, count + 1)
.await
.map_err(|e| Error::Network(format!("DHT closest-nodes lookup failed: {e}")))?;
Ok(closest_nodes
.into_iter()
.filter(|n| n.peer_id != *local_peer_id)
.take(count)
.map(|n| {
let addrs = n.addresses_by_priority();
(n.peer_id, addrs)
})
.collect())
}
pub async fn connected_peers(&self) -> Vec<PeerId> {
self.node.connected_peers().await
}
}