use mac_addr::MacAddr;
use std::{
fmt,
net::{Ipv4Addr, Ipv6Addr},
};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Protocol {
Mac(MacAddr),
Ip4(Ipv4Addr),
Ip6(Ipv6Addr),
Dns(String),
Dns4(String),
Dns6(String),
Tcp(u16),
Udp(u16),
Tls,
Quic,
Http,
Https,
Ws(u16),
Wss(u16),
WebTransport(u16),
WebRTC,
Onion(String),
Custom(String),
}
impl fmt::Display for Protocol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Protocol::*;
match self {
Ip4(addr) => write!(f, "/ip4/{}", addr),
Ip6(addr) => write!(f, "/ip6/{}", addr),
Dns(name) => write!(f, "/dns/{}", name),
Dns4(name) => write!(f, "/dns4/{}", name),
Dns6(name) => write!(f, "/dns6/{}", name),
Mac(addr) => write!(f, "/mac/{}", addr),
Tcp(port) => write!(f, "/tcp/{}", port),
Udp(port) => write!(f, "/udp/{}", port),
Tls => write!(f, "/tls"),
Quic => write!(f, "/quic"),
Http => write!(f, "/http"),
Https => write!(f, "/https"),
Ws(port) => write!(f, "/ws/{}", port),
Wss(port) => write!(f, "/wss/{}", port),
WebTransport(port) => write!(f, "/wtr/{}", port),
WebRTC => write!(f, "/webrtc"),
Onion(addr) => write!(f, "/onion/{}", addr),
Custom(name) => write!(f, "/custom/{}", name),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TransportProtocol {
Tcp(u16),
Udp(u16),
TlsTcp(u16),
Quic(u16),
Ws(u16),
Wss(u16),
WebTransport(u16),
}
impl TransportProtocol {
pub fn port(&self) -> u16 {
match self {
TransportProtocol::Tcp(p)
| TransportProtocol::Udp(p)
| TransportProtocol::TlsTcp(p)
| TransportProtocol::Quic(p)
| TransportProtocol::Ws(p)
| TransportProtocol::Wss(p)
| TransportProtocol::WebTransport(p) => *p,
}
}
pub fn is_secure(&self) -> bool {
matches!(
self,
TransportProtocol::TlsTcp(_)
| TransportProtocol::Quic(_)
| TransportProtocol::Wss(_)
| TransportProtocol::WebTransport(_)
)
}
}
impl fmt::Display for TransportProtocol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use TransportProtocol::*;
match self {
Tcp(port) => write!(f, "tcp/{}", port),
Udp(port) => write!(f, "udp/{}", port),
TlsTcp(port) => write!(f, "tls/tcp/{}", port),
Quic(port) => write!(f, "quic/{}", port),
Ws(port) => write!(f, "ws/{}", port),
Wss(port) => write!(f, "wss/{}", port),
WebTransport(port) => write!(f, "wtr/{}", port),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_display_macaddr() {
use mac_addr::MacAddr;
let mac = MacAddr::new(0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff);
let proto = vec![
Protocol::Mac(mac),
Protocol::Ip4("192.168.10.10".parse().unwrap()),
];
let text = proto.iter().map(|p| p.to_string()).collect::<String>();
assert_eq!(text, "/mac/aa:bb:cc:dd:ee:ff/ip4/192.168.10.10");
}
#[test]
fn test_display_ip4_quic() {
let proto = vec![
Protocol::Ip4("127.0.0.1".parse().unwrap()),
Protocol::Udp(4433),
Protocol::Quic,
];
let text = proto.iter().map(|p| p.to_string()).collect::<String>();
assert_eq!(text, "/ip4/127.0.0.1/udp/4433/quic");
}
#[test]
fn test_display_ip6_tcp_https() {
let proto = vec![
Protocol::Ip6("::1".parse().unwrap()),
Protocol::Tcp(443),
Protocol::Https,
];
let text = proto.iter().map(|p| p.to_string()).collect::<String>();
assert_eq!(text, "/ip6/::1/tcp/443/https");
}
}