srt_protocol/options/
address.rs1use std::{
2 borrow::Cow,
3 convert::{TryFrom, TryInto},
4 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
5 num::ParseIntError,
6 str::FromStr,
7};
8
9use thiserror::Error;
10use url::Host;
11
12#[derive(Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
16pub struct SocketAddress {
17 pub host: SocketHost,
18 pub port: u16,
19}
20
21impl<'a> TryFrom<Cow<'a, str>> for SocketAddress {
22 type Error = SocketAddressParseError;
23
24 fn try_from(value: Cow<'a, str>) -> Result<Self, Self::Error> {
25 TryFrom::try_from(value.as_ref())
26 }
27}
28
29impl TryFrom<String> for SocketAddress {
30 type Error = SocketAddressParseError;
31
32 fn try_from(value: String) -> Result<Self, Self::Error> {
33 TryFrom::try_from(value.as_ref())
34 }
35}
36
37impl TryFrom<&str> for SocketAddress {
38 type Error = SocketAddressParseError;
39
40 fn try_from(address: &str) -> Result<Self, Self::Error> {
41 let mut split = address.split(':');
42 match (split.next(), split.next(), split.next()) {
43 (Some(""), Some(port), None) => Ok(Self {
44 host: SocketHost::Ipv4(Ipv4Addr::UNSPECIFIED),
45 port: u16::from_str(port)?,
46 }),
47 (Some(host), port, None) => Ok(Self {
48 host: match url::Host::parse(host)? {
49 Host::Domain(domain) => SocketHost::Domain(domain),
50 Host::Ipv4(ipv4) => SocketHost::Ipv4(ipv4),
51 Host::Ipv6(ipv6) => SocketHost::Ipv6(ipv6),
52 },
53 port: port.map(u16::from_str).unwrap_or(Ok(0))?,
54 }),
55 _ => Err(SocketAddressParseError::Invalid(address.to_string())),
56 }
57 }
58}
59
60impl From<u16> for SocketAddress {
61 fn from(port: u16) -> Self {
62 Self {
63 host: SocketHost::Ipv4(Ipv4Addr::UNSPECIFIED),
64 port,
65 }
66 }
67}
68
69impl From<SocketAddr> for SocketAddress {
70 fn from(addr: SocketAddr) -> Self {
71 Self {
72 host: addr.ip().into(),
73 port: addr.port(),
74 }
75 }
76}
77
78impl TryInto<SocketAddr> for SocketAddress {
79 type Error = ();
80
81 fn try_into(self) -> Result<SocketAddr, Self::Error> {
82 Ok(SocketAddr::new(self.host.try_into()?, self.port))
83 }
84}
85
86#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
87pub enum SocketHost {
88 Domain(String),
90
91 Ipv4(Ipv4Addr),
93
94 Ipv6(Ipv6Addr),
96}
97
98impl From<IpAddr> for SocketHost {
99 fn from(addr: IpAddr) -> Self {
100 use SocketHost::*;
101 match addr {
102 IpAddr::V4(v4) => Ipv4(v4),
103 IpAddr::V6(v6) => Ipv6(v6),
104 }
105 }
106}
107
108impl TryInto<IpAddr> for SocketHost {
109 type Error = ();
110
111 fn try_into(self) -> Result<IpAddr, Self::Error> {
112 use SocketHost::*;
113 match self {
114 Ipv4(ipv4) => Ok(ipv4.into()),
115 Ipv6(ipv6) => Ok(ipv6.into()),
116 _ => Err(()),
117 }
118 }
119}
120
121impl From<Ipv4Addr> for SocketHost {
122 fn from(ipv4: Ipv4Addr) -> SocketHost {
123 SocketHost::Ipv4(ipv4)
124 }
125}
126
127impl From<Ipv6Addr> for SocketHost {
128 fn from(ipv6: Ipv6Addr) -> SocketHost {
129 SocketHost::Ipv6(ipv6)
130 }
131}
132
133impl Default for SocketHost {
134 fn default() -> Self {
135 SocketHost::Ipv4(Ipv4Addr::UNSPECIFIED)
136 }
137}
138
139#[derive(Error, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
140pub enum SocketAddressParseError {
141 #[error("Invalid address: {0}")]
142 Invalid(String),
143 #[error("Invalid host: {0}")]
144 InvalidHost(String),
145 #[error("Invalid port: {0}")]
146 InvalidPort(String),
147}
148
149impl From<ParseIntError> for SocketAddressParseError {
150 fn from(error: ParseIntError) -> Self {
151 SocketAddressParseError::InvalidPort(error.to_string())
152 }
153}
154
155impl From<url::ParseError> for SocketAddressParseError {
156 fn from(error: url::ParseError) -> Self {
157 SocketAddressParseError::InvalidHost(error.to_string())
158 }
159}