use std::net::SocketAddr;
use crate::identity::PeerId;
use crate::method::TraversalKind;
use crate::mux::{PeerSession, PeerStream};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PeerTarget {
pub peer_id: PeerId,
direct_addrs: Vec<SocketAddr>,
pub network_id: String,
}
impl PeerTarget {
pub fn with_addr(
peer_id: PeerId,
direct_addr: SocketAddr,
network_id: impl Into<String>,
) -> Self {
PeerTarget::with_addrs(peer_id, vec![direct_addr], network_id)
}
pub fn with_addrs(
peer_id: PeerId,
direct_addrs: Vec<SocketAddr>,
network_id: impl Into<String>,
) -> Self {
let mut t = PeerTarget {
peer_id,
direct_addrs,
network_id: network_id.into(),
};
sort_ipv6_first(&mut t.direct_addrs);
t
}
pub fn relay_only(peer_id: PeerId, network_id: impl Into<String>) -> Self {
PeerTarget {
peer_id,
direct_addrs: Vec::new(),
network_id: network_id.into(),
}
}
pub fn direct_addrs(&self) -> &[SocketAddr] {
&self.direct_addrs
}
pub fn direct_addr(&self) -> Option<SocketAddr> {
self.direct_addrs.first().copied()
}
pub fn set_direct_addrs(&mut self, addrs: Vec<SocketAddr>) {
self.direct_addrs = addrs;
sort_ipv6_first(&mut self.direct_addrs);
}
}
pub fn sort_ipv6_first(addrs: &mut [SocketAddr]) {
addrs.sort_by_key(|a| if a.is_ipv6() { 0u8 } else { 1u8 });
}
pub fn is_ipv6_first(addrs: &[SocketAddr]) -> bool {
fn family_key(a: &SocketAddr) -> u8 {
if a.is_ipv6() {
0
} else {
1
}
}
addrs
.windows(2)
.all(|w| family_key(&w[0]) <= family_key(&w[1]))
}
pub struct PeerConnection {
pub peer_id: PeerId,
pub method: TraversalKind,
pub remote_addr: SocketAddr,
pub session: PeerSession,
}
impl PeerConnection {
pub async fn open_stream(&mut self) -> std::io::Result<PeerStream> {
self.session.open_stream().await
}
pub async fn open_range_stream(
&mut self,
req: &crate::mux::RangeRequest,
) -> std::io::Result<PeerStream> {
self.session.open_range_stream(req).await
}
pub async fn query_availability(
&mut self,
items: Vec<crate::mux::AvailabilityItem>,
) -> std::io::Result<crate::mux::AvailabilityResponse> {
self.session.query_availability(items).await
}
}
impl std::fmt::Debug for PeerConnection {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PeerConnection")
.field("peer_id", &self.peer_id)
.field("method", &self.method)
.field("remote_addr", &self.remote_addr)
.field("session", &"<multiplexed mTLS session>")
.finish()
}
}