use std::net::SocketAddr;
use async_trait::async_trait;
use crate::error::MethodError;
use crate::method::{MethodOutcome, TraversalKind, TraversalMethod};
use crate::peer::PeerTarget;
#[async_trait]
pub trait HolePunchCoordinator: Send + Sync {
async fn coordinate(
&self,
target_peer: &str,
network_id: &str,
my_external_addr: SocketAddr,
) -> Result<SocketAddr, String>;
}
pub struct HolePunchMethod<C: HolePunchCoordinator> {
coordinator: C,
pub my_external_addr: SocketAddr,
}
impl<C: HolePunchCoordinator> HolePunchMethod<C> {
pub fn new(coordinator: C, my_external_addr: SocketAddr) -> Self {
HolePunchMethod {
coordinator,
my_external_addr,
}
}
}
#[async_trait]
impl<C: HolePunchCoordinator> TraversalMethod for HolePunchMethod<C> {
fn kind(&self) -> TraversalKind {
TraversalKind::HolePunch
}
async fn attempt(&self, peer: &PeerTarget) -> Result<MethodOutcome, MethodError> {
let peer_addr = self
.coordinator
.coordinate(
&peer.peer_id.to_hex(),
&peer.network_id,
self.my_external_addr,
)
.await
.map_err(|e| MethodError::failed(TraversalKind::HolePunch, e))?;
Ok(MethodOutcome::single(TraversalKind::HolePunch, peer_addr))
}
}