// Copyright 2021 Ian Jackson and contributors to Hippotat
-// SPDX-License-Identifier: AGPL-3.0-or-later
+// SPDX-License-Identifier: GPL-3.0-or-later
// There is NO WARRANTY.
use crate::prelude::*;
-#[derive(Debug,Clone,Hash,Eq,PartialEq)]
+#[derive(Debug,Copy,Clone)]
+pub enum LinkEnd { Server, Client }
+
+#[derive(Debug,Clone,Hash,Eq,PartialEq,Ord,PartialOrd)]
pub struct ServerName(pub String);
-#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
-pub struct ClientName(pub Ipv4Addr);
+#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq,Ord,PartialOrd)]
+pub struct ClientName(pub IpAddr);
+
+#[derive(Debug,Clone,Hash,Eq,PartialEq,Ord,PartialOrd)]
+pub struct LinkName {
+ pub server: ServerName,
+ pub client: ClientName,
+}
impl FromStr for ClientName {
type Err = AE;
#[throws(AE)]
fn from_str(s: &str) -> Self {
- let v4addr: Ipv4Addr = s.parse()
- .context("invalid client name (IPv4 address)")?;
- if s != v4addr.to_string() {
- throw!(anyhow!("invalid client name (unusual IPv4 address syntax)"));
- }
- ClientName(v4addr)
+ ClientName(
+ if let Ok(v4addr) = s.parse::<Ipv4Addr>() {
+ if s != v4addr.to_string() {
+ throw!(anyhow!("invalid client name (unusual IPv4 address syntax)"));
+ }
+ v4addr.into()
+ } else if let Ok(v6addr) = s.parse::<Ipv6Addr>() {
+ if s != v6addr.to_string() {
+ throw!(anyhow!("invalid client name (non-canonical IPv6 address)"));
+ }
+ v6addr.into()
+ } else {
+ throw!(anyhow!("invalid client name (IPv4 or IPv6 address)"))
+ }
+ )
}
}
^ (?: SERVER
| [0-9a-z][-0-9a-z]* (:? \.
[0-9a-z][-0-9a-z]* )*
- )"x, s) {
+ ) $"x, s) {
throw!(anyhow!("bad syntax for server name"));
}
- if ! regex_is_match!(r"[a-z-]", s) {
+ if ! regex_is_match!(r"[A-Za-z-]", s) {
throw!(anyhow!("bad syntax for server name \
(too much like an IPv4 address)"));
}
ServerName(s.into())
}
}
+
+impl Display for ServerName {
+ #[throws(fmt::Error)]
+ fn fmt(&self, f: &mut fmt::Formatter) { Display::fmt(&self.0, f)?; }
+}
+impl Display for ClientName {
+ #[throws(fmt::Error)]
+ fn fmt(&self, f: &mut fmt::Formatter) { Display::fmt(&self.0, f)?; }
+}
+impl Display for LinkName {
+ #[throws(fmt::Error)]
+ fn fmt(&self, f: &mut fmt::Formatter) {
+ write!(f, "[{} {}]", &self.server, &self.client)?;
+ }
+}