From 85b092872d932f863251350b7dd3996bcb04524d Mon Sep 17 00:00:00 2001 From: Alexis Sellier Date: Wed, 26 Jul 2023 16:22:18 +0200 Subject: [PATCH] node: Support DNS address types at the wire level --- radicle-node/src/wire/message.rs | 16 +++++++++----- radicle/src/node/address.rs | 6 +++--- radicle/src/node/address/store.rs | 4 ++-- radicle/src/test/arbitrary.rs | 35 +++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 16 deletions(-) diff --git a/radicle-node/src/wire/message.rs b/radicle-node/src/wire/message.rs index 5c1d9efd..d65ff5f3 100644 --- a/radicle-node/src/wire/message.rs +++ b/radicle-node/src/wire/message.rs @@ -85,7 +85,7 @@ impl netservices::Frame for Message { pub enum AddressType { Ipv4 = 1, Ipv6 = 2, - Hostname = 3, + Dns = 3, Onion = 4, } @@ -100,7 +100,7 @@ impl From<&Address> for AddressType { match a.host { HostName::Ip(net::IpAddr::V4(_)) => AddressType::Ipv4, HostName::Ip(net::IpAddr::V6(_)) => AddressType::Ipv6, - HostName::Dns(_) => AddressType::Hostname, + HostName::Dns(_) => AddressType::Dns, HostName::Tor(_) => AddressType::Onion, _ => todo!(), // FIXME(cloudhead): Maxim will remove `non-exhaustive` } @@ -114,7 +114,7 @@ impl TryFrom for AddressType { match other { 1 => Ok(AddressType::Ipv4), 2 => Ok(AddressType::Ipv6), - 3 => Ok(AddressType::Hostname), + 3 => Ok(AddressType::Dns), 4 => Ok(AddressType::Onion), _ => Err(other), } @@ -301,6 +301,10 @@ impl wire::Encode for Address { n += u8::from(AddressType::Ipv6).encode(writer)?; n += ip.octets().encode(writer)?; } + HostName::Dns(ref dns) => { + n += u8::from(AddressType::Dns).encode(writer)?; + n += dns.encode(writer)?; + } _ => { todo!(); } @@ -327,8 +331,10 @@ impl wire::Decode for Address { HostName::Ip(net::IpAddr::V6(ip)) } - Ok(AddressType::Hostname) => { - todo!(); + Ok(AddressType::Dns) => { + let dns: String = wire::Decode::decode(reader)?; + + HostName::Dns(dns) } Ok(AddressType::Onion) => { todo!(); diff --git a/radicle/src/node/address.rs b/radicle/src/node/address.rs index e6e6e350..631a674e 100644 --- a/radicle/src/node/address.rs +++ b/radicle/src/node/address.rs @@ -16,7 +16,7 @@ use crate::node::Address; pub enum AddressType { Ipv4 = 1, Ipv6 = 2, - Hostname = 3, + Dns = 3, Onion = 4, } @@ -31,7 +31,7 @@ impl From<&Address> for AddressType { match a.host { HostName::Ip(net::IpAddr::V4(_)) => AddressType::Ipv4, HostName::Ip(net::IpAddr::V6(_)) => AddressType::Ipv6, - HostName::Dns(_) => AddressType::Hostname, + HostName::Dns(_) => AddressType::Dns, HostName::Tor(_) => AddressType::Onion, _ => todo!(), // FIXME(cloudhead): Maxim will remove `non-exhaustive` } @@ -45,7 +45,7 @@ impl TryFrom for AddressType { match other { 1 => Ok(AddressType::Ipv4), 2 => Ok(AddressType::Ipv6), - 3 => Ok(AddressType::Hostname), + 3 => Ok(AddressType::Dns), 4 => Ok(AddressType::Onion), _ => Err(other), } diff --git a/radicle/src/node/address/store.rs b/radicle/src/node/address/store.rs index aff427dd..a9f7669f 100644 --- a/radicle/src/node/address/store.rs +++ b/radicle/src/node/address/store.rs @@ -342,7 +342,7 @@ impl TryFrom<&sql::Value> for AddressType { sql::Value::String(s) => match s.as_str() { "ipv4" => Ok(AddressType::Ipv4), "ipv6" => Ok(AddressType::Ipv6), - "hostname" => Ok(AddressType::Hostname), + "hostname" => Ok(AddressType::Dns), "onion" => Ok(AddressType::Onion), _ => Err(err), }, @@ -356,7 +356,7 @@ impl sql::BindableWithIndex for AddressType { match self { Self::Ipv4 => "ipv4".bind(stmt, i), Self::Ipv6 => "ipv6".bind(stmt, i), - Self::Hostname => "hostname".bind(stmt, i), + Self::Dns => "dns".bind(stmt, i), Self::Onion => "onion".bind(stmt, i), } } diff --git a/radicle/src/test/arbitrary.rs b/radicle/src/test/arbitrary.rs index 54d64fc5..3195cc1b 100644 --- a/radicle/src/test/arbitrary.rs +++ b/radicle/src/test/arbitrary.rs @@ -15,6 +15,7 @@ use crate::identity::{ project::Project, Did, }; +use crate::node::address::AddressType; use crate::node::{Address, Alias}; use crate::storage; use crate::storage::refs::{Refs, SignedRefs}; @@ -214,16 +215,38 @@ impl Arbitrary for Id { } } +impl Arbitrary for AddressType { + fn arbitrary(g: &mut qcheck::Gen) -> Self { + let t = *g.choose(&[1, 2, 3]).unwrap() as u8; + + AddressType::try_from(t).unwrap() + } +} + impl Arbitrary for Address { fn arbitrary(g: &mut qcheck::Gen) -> Self { - let ip = if bool::arbitrary(g) { - net::IpAddr::V4(net::Ipv4Addr::from(u32::arbitrary(g))) - } else { - let octets: [u8; 16] = Arbitrary::arbitrary(g); - net::IpAddr::V6(net::Ipv6Addr::from(octets)) + let host = match AddressType::arbitrary(g) { + AddressType::Ipv4 => cyphernet::addr::HostName::Ip(net::IpAddr::V4( + net::Ipv4Addr::from(u32::arbitrary(g)), + )), + AddressType::Ipv6 => { + let octets: [u8; 16] = Arbitrary::arbitrary(g); + cyphernet::addr::HostName::Ip(net::IpAddr::V6(net::Ipv6Addr::from(octets))) + } + AddressType::Dns => cyphernet::addr::HostName::Dns( + g.choose(&[ + "seed.radicle.xyz", + "seed.radicle.garden", + "seed.radicle.cloudhead.io", + ]) + .unwrap() + .to_string(), + ), + AddressType::Onion => todo!(), }; + Address::from(cyphernet::addr::NetAddr { - host: cyphernet::addr::HostName::Ip(ip), + host, port: u16::arbitrary(g), }) }