use crate::multihash::Multihash;
use libp2p_identity::PeerId;
use litep2p::types::multiaddr::Protocol as LiteP2pProtocol;
use multiaddr::Protocol as LibP2pProtocol;
use std::{
borrow::Cow,
fmt::{self, Debug, Display},
net::{IpAddr, Ipv4Addr, Ipv6Addr},
};
const LOG_TARGET: &str = "sub-libp2p";
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Protocol<'a> {
Dccp(u16),
Dns(Cow<'a, str>),
Dns4(Cow<'a, str>),
Dns6(Cow<'a, str>),
Dnsaddr(Cow<'a, str>),
Http,
Https,
Ip4(Ipv4Addr),
Ip6(Ipv6Addr),
P2pWebRtcDirect,
P2pWebRtcStar,
WebRTC,
Certhash(Multihash),
P2pWebSocketStar,
Memory(u64),
Onion(Cow<'a, [u8; 10]>, u16),
Onion3(Cow<'a, [u8; 35]>, u16),
P2p(Multihash),
P2pCircuit,
Quic,
QuicV1,
Sctp(u16),
Tcp(u16),
Tls,
Noise,
Udp(u16),
Udt,
Unix(Cow<'a, str>),
Utp,
Ws(Cow<'a, str>),
Wss(Cow<'a, str>),
}
impl<'a> Display for Protocol<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let protocol = LiteP2pProtocol::from(self.clone());
Display::fmt(&protocol, f)
}
}
impl<'a> From<IpAddr> for Protocol<'a> {
#[inline]
fn from(addr: IpAddr) -> Self {
match addr {
IpAddr::V4(addr) => Protocol::Ip4(addr),
IpAddr::V6(addr) => Protocol::Ip6(addr),
}
}
}
impl<'a> From<Ipv4Addr> for Protocol<'a> {
#[inline]
fn from(addr: Ipv4Addr) -> Self {
Protocol::Ip4(addr)
}
}
impl<'a> From<Ipv6Addr> for Protocol<'a> {
#[inline]
fn from(addr: Ipv6Addr) -> Self {
Protocol::Ip6(addr)
}
}
impl<'a> From<LiteP2pProtocol<'a>> for Protocol<'a> {
fn from(protocol: LiteP2pProtocol<'a>) -> Self {
match protocol {
LiteP2pProtocol::Dccp(port) => Protocol::Dccp(port),
LiteP2pProtocol::Dns(str) => Protocol::Dns(str),
LiteP2pProtocol::Dns4(str) => Protocol::Dns4(str),
LiteP2pProtocol::Dns6(str) => Protocol::Dns6(str),
LiteP2pProtocol::Dnsaddr(str) => Protocol::Dnsaddr(str),
LiteP2pProtocol::Http => Protocol::Http,
LiteP2pProtocol::Https => Protocol::Https,
LiteP2pProtocol::Ip4(ipv4_addr) => Protocol::Ip4(ipv4_addr),
LiteP2pProtocol::Ip6(ipv6_addr) => Protocol::Ip6(ipv6_addr),
LiteP2pProtocol::P2pWebRtcDirect => Protocol::P2pWebRtcDirect,
LiteP2pProtocol::P2pWebRtcStar => Protocol::P2pWebRtcStar,
LiteP2pProtocol::WebRTC => Protocol::WebRTC,
LiteP2pProtocol::Certhash(multihash) => Protocol::Certhash(multihash.into()),
LiteP2pProtocol::P2pWebSocketStar => Protocol::P2pWebSocketStar,
LiteP2pProtocol::Memory(port) => Protocol::Memory(port),
LiteP2pProtocol::Onion(str, port) => Protocol::Onion(str, port),
LiteP2pProtocol::Onion3(addr) =>
Protocol::Onion3(Cow::Owned(*addr.hash()), addr.port()),
LiteP2pProtocol::P2p(multihash) => Protocol::P2p(multihash.into()),
LiteP2pProtocol::P2pCircuit => Protocol::P2pCircuit,
LiteP2pProtocol::Quic => Protocol::Quic,
LiteP2pProtocol::QuicV1 => Protocol::QuicV1,
LiteP2pProtocol::Sctp(port) => Protocol::Sctp(port),
LiteP2pProtocol::Tcp(port) => Protocol::Tcp(port),
LiteP2pProtocol::Tls => Protocol::Tls,
LiteP2pProtocol::Noise => Protocol::Noise,
LiteP2pProtocol::Udp(port) => Protocol::Udp(port),
LiteP2pProtocol::Udt => Protocol::Udt,
LiteP2pProtocol::Unix(str) => Protocol::Unix(str),
LiteP2pProtocol::Utp => Protocol::Utp,
LiteP2pProtocol::Ws(str) => Protocol::Ws(str),
LiteP2pProtocol::Wss(str) => Protocol::Wss(str),
}
}
}
impl<'a> From<Protocol<'a>> for LiteP2pProtocol<'a> {
fn from(protocol: Protocol<'a>) -> Self {
match protocol {
Protocol::Dccp(port) => LiteP2pProtocol::Dccp(port),
Protocol::Dns(str) => LiteP2pProtocol::Dns(str),
Protocol::Dns4(str) => LiteP2pProtocol::Dns4(str),
Protocol::Dns6(str) => LiteP2pProtocol::Dns6(str),
Protocol::Dnsaddr(str) => LiteP2pProtocol::Dnsaddr(str),
Protocol::Http => LiteP2pProtocol::Http,
Protocol::Https => LiteP2pProtocol::Https,
Protocol::Ip4(ipv4_addr) => LiteP2pProtocol::Ip4(ipv4_addr),
Protocol::Ip6(ipv6_addr) => LiteP2pProtocol::Ip6(ipv6_addr),
Protocol::P2pWebRtcDirect => LiteP2pProtocol::P2pWebRtcDirect,
Protocol::P2pWebRtcStar => LiteP2pProtocol::P2pWebRtcStar,
Protocol::WebRTC => LiteP2pProtocol::WebRTC,
Protocol::Certhash(multihash) => LiteP2pProtocol::Certhash(multihash.into()),
Protocol::P2pWebSocketStar => LiteP2pProtocol::P2pWebSocketStar,
Protocol::Memory(port) => LiteP2pProtocol::Memory(port),
Protocol::Onion(str, port) => LiteP2pProtocol::Onion(str, port),
Protocol::Onion3(str, port) => LiteP2pProtocol::Onion3((str.into_owned(), port).into()),
Protocol::P2p(multihash) => LiteP2pProtocol::P2p(multihash.into()),
Protocol::P2pCircuit => LiteP2pProtocol::P2pCircuit,
Protocol::Quic => LiteP2pProtocol::Quic,
Protocol::QuicV1 => LiteP2pProtocol::QuicV1,
Protocol::Sctp(port) => LiteP2pProtocol::Sctp(port),
Protocol::Tcp(port) => LiteP2pProtocol::Tcp(port),
Protocol::Tls => LiteP2pProtocol::Tls,
Protocol::Noise => LiteP2pProtocol::Noise,
Protocol::Udp(port) => LiteP2pProtocol::Udp(port),
Protocol::Udt => LiteP2pProtocol::Udt,
Protocol::Unix(str) => LiteP2pProtocol::Unix(str),
Protocol::Utp => LiteP2pProtocol::Utp,
Protocol::Ws(str) => LiteP2pProtocol::Ws(str),
Protocol::Wss(str) => LiteP2pProtocol::Wss(str),
}
}
}
impl<'a> From<LibP2pProtocol<'a>> for Protocol<'a> {
fn from(protocol: LibP2pProtocol<'a>) -> Self {
match protocol {
LibP2pProtocol::Dccp(port) => Protocol::Dccp(port),
LibP2pProtocol::Dns(str) => Protocol::Dns(str),
LibP2pProtocol::Dns4(str) => Protocol::Dns4(str),
LibP2pProtocol::Dns6(str) => Protocol::Dns6(str),
LibP2pProtocol::Dnsaddr(str) => Protocol::Dnsaddr(str),
LibP2pProtocol::Http => Protocol::Http,
LibP2pProtocol::Https => Protocol::Https,
LibP2pProtocol::Ip4(ipv4_addr) => Protocol::Ip4(ipv4_addr),
LibP2pProtocol::Ip6(ipv6_addr) => Protocol::Ip6(ipv6_addr),
LibP2pProtocol::P2pWebRtcDirect => Protocol::P2pWebRtcDirect,
LibP2pProtocol::P2pWebRtcStar => Protocol::P2pWebRtcStar,
LibP2pProtocol::Certhash(multihash) => Protocol::Certhash(multihash.into()),
LibP2pProtocol::P2pWebSocketStar => Protocol::P2pWebSocketStar,
LibP2pProtocol::Memory(port) => Protocol::Memory(port),
LibP2pProtocol::Onion(str, port) => Protocol::Onion(str, port),
LibP2pProtocol::Onion3(addr) => Protocol::Onion3(Cow::Owned(*addr.hash()), addr.port()),
LibP2pProtocol::P2p(peer_id) => Protocol::P2p((*peer_id.as_ref()).into()),
LibP2pProtocol::P2pCircuit => Protocol::P2pCircuit,
LibP2pProtocol::Quic => Protocol::Quic,
LibP2pProtocol::QuicV1 => Protocol::QuicV1,
LibP2pProtocol::Sctp(port) => Protocol::Sctp(port),
LibP2pProtocol::Tcp(port) => Protocol::Tcp(port),
LibP2pProtocol::Tls => Protocol::Tls,
LibP2pProtocol::Noise => Protocol::Noise,
LibP2pProtocol::Udp(port) => Protocol::Udp(port),
LibP2pProtocol::Udt => Protocol::Udt,
LibP2pProtocol::Unix(str) => Protocol::Unix(str),
LibP2pProtocol::Utp => Protocol::Utp,
LibP2pProtocol::Ws(str) => Protocol::Ws(str),
LibP2pProtocol::Wss(str) => Protocol::Wss(str),
protocol => {
log::error!(
target: LOG_TARGET,
"Got unsupported multiaddr protocol '{}'",
protocol.tag(),
);
Protocol::Dccp(0)
},
}
}
}
impl<'a> From<Protocol<'a>> for LibP2pProtocol<'a> {
fn from(protocol: Protocol<'a>) -> Self {
match protocol {
Protocol::Dccp(port) => LibP2pProtocol::Dccp(port),
Protocol::Dns(str) => LibP2pProtocol::Dns(str),
Protocol::Dns4(str) => LibP2pProtocol::Dns4(str),
Protocol::Dns6(str) => LibP2pProtocol::Dns6(str),
Protocol::Dnsaddr(str) => LibP2pProtocol::Dnsaddr(str),
Protocol::Http => LibP2pProtocol::Http,
Protocol::Https => LibP2pProtocol::Https,
Protocol::Ip4(ipv4_addr) => LibP2pProtocol::Ip4(ipv4_addr),
Protocol::Ip6(ipv6_addr) => LibP2pProtocol::Ip6(ipv6_addr),
Protocol::P2pWebRtcDirect => LibP2pProtocol::P2pWebRtcDirect,
Protocol::P2pWebRtcStar => LibP2pProtocol::P2pWebRtcStar,
Protocol::WebRTC => LibP2pProtocol::WebRTCDirect,
Protocol::Certhash(multihash) => LibP2pProtocol::Certhash(multihash.into()),
Protocol::P2pWebSocketStar => LibP2pProtocol::P2pWebSocketStar,
Protocol::Memory(port) => LibP2pProtocol::Memory(port),
Protocol::Onion(str, port) => LibP2pProtocol::Onion(str, port),
Protocol::Onion3(str, port) => LibP2pProtocol::Onion3((str.into_owned(), port).into()),
Protocol::P2p(multihash) =>
LibP2pProtocol::P2p(PeerId::from_multihash(multihash.into()).unwrap_or_else(|_| {
log::error!(
target: LOG_TARGET,
"Received multiaddr with p2p multihash which is not a valid \
peer_id. Replacing with random peer_id."
);
PeerId::random()
})),
Protocol::P2pCircuit => LibP2pProtocol::P2pCircuit,
Protocol::Quic => LibP2pProtocol::Quic,
Protocol::QuicV1 => LibP2pProtocol::QuicV1,
Protocol::Sctp(port) => LibP2pProtocol::Sctp(port),
Protocol::Tcp(port) => LibP2pProtocol::Tcp(port),
Protocol::Tls => LibP2pProtocol::Tls,
Protocol::Noise => LibP2pProtocol::Noise,
Protocol::Udp(port) => LibP2pProtocol::Udp(port),
Protocol::Udt => LibP2pProtocol::Udt,
Protocol::Unix(str) => LibP2pProtocol::Unix(str),
Protocol::Utp => LibP2pProtocol::Utp,
Protocol::Ws(str) => LibP2pProtocol::Ws(str),
Protocol::Wss(str) => LibP2pProtocol::Wss(str),
}
}
}