Skip to content

Commit 0074237

Browse files
committed
docs and cleanup
1 parent 40f5387 commit 0074237

File tree

3 files changed

+50
-54
lines changed

3 files changed

+50
-54
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

iroh-net/Cargo.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,12 @@ data-encoding = "2.3.3"
2525
default-net = "0.20"
2626
der = { version = "0.7", features = ["alloc", "derive"] }
2727
derive_more = { version = "1.0.0-beta.1", features = ["debug", "display", "from", "try_into", "deref"] }
28-
ed25519-dalek = { version = "2.0.0", features = ["serde", "rand_core"], optional = true }
2928
flume = "0.11"
3029
futures = "0.3.25"
3130
governor = "0.6.0"
3231
hex = "0.4.3"
32+
hickory-proto = "0.24.0"
33+
hickory-resolver = "0.24.0"
3334
hostname = "0.3.1"
3435
http = "1"
3536
http-body-util = "0.1.0"
@@ -41,6 +42,7 @@ libc = "0.2.139"
4142
num_enum = "0.7"
4243
once_cell = "1.18.0"
4344
parking_lot = "0.12.1"
45+
pkarr = { version = "1.1.3", default-features = false, features = ["async", "relay"] }
4446
postcard = { version = "1", default-features = false, features = ["alloc", "use-std", "experimental-derive"] }
4547
quinn = "0.10"
4648
quinn-proto = "0.10.5"
@@ -66,12 +68,12 @@ tokio-rustls = { version = "0.24" }
6668
tokio-rustls-acme = { version = "0.2" }
6769
tokio-util = { version = "0.7", features = ["io-util", "io", "codec"] }
6870
tracing = "0.1"
69-
hickory-resolver = "0.24.0"
7071
url = { version = "2.4", features = ["serde"] }
7172
watchable = "1.1.2"
7273
webpki = { package = "rustls-webpki", version = "0.101.4", features = ["std"] }
7374
webpki-roots = "0.25"
7475
x509-parser = "0.15"
76+
z32 = "1.0.3"
7577

7678
# derper
7779
clap = { version = "4", features = ["derive"], optional = true }
@@ -83,9 +85,6 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = tr
8385

8486
# metrics
8587
iroh-metrics = { version = "0.12.0", path = "../iroh-metrics", default-features = false }
86-
z32 = "1.0.3"
87-
hickory-proto = "0.24.0"
88-
pkarr = { version = "1.1.3", default-features = false, features = ["async", "relay"] }
8988

9089
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
9190
netlink-packet-core = "0.7.0"

iroh-net/src/dns/node_info.rs

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//! todo
1+
//! This module contains functions and structs to lookup node information from DNS
2+
//! and to encode node information in Pkarr signed packets.
23
34
use std::{collections::HashMap, fmt, str::FromStr};
45

@@ -9,23 +10,23 @@ use url::Url;
910

1011
use crate::{key::SecretKey, AddrInfo, NodeAddr, NodeId};
1112

12-
///
13-
pub const ATTR_DERP: &str = "derp";
14-
///
15-
pub const ATTR_NODE_ID: &str = "node";
16-
///
17-
pub const ATTR_ADDR: &str = "addr";
18-
///
13+
const ATTR_DERP: &str = "derp";
14+
const ATTR_NODE_ID: &str = "node";
15+
16+
/// The label for the node info TXT record
1917
pub const IROH_NODE_TXT_LABEL: &str = "_iroh_node";
2018

19+
/// Lookup node info by domain name
2120
///
21+
/// The domain name must either contain an _iroh_node TXT record or be a CNAME record that leads to
22+
/// an _iroh_node TXT record.
2223
pub async fn lookup_by_domain(domain: &str) -> Result<NodeAddr> {
2324
let name = Name::from_str(domain)?;
2425
let info = lookup_node_info(name).await?;
2526
Ok(info.into())
2627
}
2728

28-
///
29+
/// Lookup node info by node id and origin domain name.
2930
pub async fn lookup_by_id(node_id: &NodeId, origin: &str) -> Result<NodeAddr> {
3031
let domain = format!("{}.{}", to_z32(node_id), origin);
3132
lookup_by_domain(&domain).await
@@ -45,12 +46,29 @@ fn ensure_iroh_node_txt_label(name: Name) -> Result<Name, ProtoError> {
4546
}
4647
}
4748

49+
/// Encode a [`NodeId`] in [`z-base-32`] encoding.
50+
///
51+
/// [z-base-32]: https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
52+
pub fn to_z32(node_id: &NodeId) -> String {
53+
z32::encode(node_id.as_bytes())
54+
}
55+
56+
/// Parse a [`NodeId`] from [`z-base-32`] encoding.
4857
///
58+
/// [z-base-32]: https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
59+
pub fn from_z32(s: &str) -> Result<NodeId> {
60+
let bytes = z32::decode(s.as_bytes()).map_err(|_| anyhow!("invalid z32"))?;
61+
let bytes: &[u8; 32] = &bytes.try_into().map_err(|_| anyhow!("not 32 bytes long"))?;
62+
let node_id = NodeId::from_bytes(bytes)?;
63+
Ok(node_id)
64+
}
65+
66+
/// Node info contained in a DNS _iroh_node TXT record.
4967
#[derive(derive_more::Debug, Clone, Eq, PartialEq)]
5068
pub struct NodeInfo {
51-
///
69+
/// The node id
5270
pub node_id: NodeId,
53-
///
71+
/// Home Derp server for this node
5472
#[debug("{:?}", self.derp_url.as_ref().map(|s| s.to_string()))]
5573
pub derp_url: Option<Url>,
5674
}
@@ -74,22 +92,16 @@ impl From<NodeInfo> for AddrInfo {
7492
}
7593

7694
impl NodeInfo {
77-
///
95+
/// Create a new [`NodeInfo`] from its parts.
7896
pub fn new(node_id: NodeId, derp_url: Option<Url>) -> Self {
7997
Self { node_id, derp_url }
8098
}
81-
///
82-
pub fn node_domain(&self, origin: &str) -> String {
83-
format!("{}.{}", to_z32(&self.node_id), origin)
84-
}
85-
86-
///
87-
pub fn node_info_domain(&self, origin: &str) -> String {
88-
format!("{}.{}", IROH_NODE_TXT_LABEL, self.node_domain(origin))
89-
}
9099

100+
/// Convert this node info into a DNS attribute string.
91101
///
92-
pub fn to_attr_string(&self) -> String {
102+
/// It will look like this:
103+
/// node=b32encodednodeid derp=https://myderp.example
104+
pub fn into_attribute_string(&self) -> String {
93105
let mut attrs = vec![];
94106
attrs.push(fmt_attr(ATTR_NODE_ID, self.node_id));
95107
if let Some(derp) = &self.derp_url {
@@ -98,12 +110,12 @@ impl NodeInfo {
98110
attrs.join(" ")
99111
}
100112

101-
///
113+
/// Try to parse a [`NodeInfo`] from the lookup result of our DNS resolver.
102114
pub fn from_hickory_lookup(lookup: &hickory_resolver::lookup::Lookup) -> Result<Self> {
103115
Self::from_hickory_records(lookup.records())
104116
}
105117

106-
///
118+
/// Try to parse a [`NodeInfo`] from a set of DNS records.
107119
pub fn from_hickory_records(records: &[hickory_proto::rr::Record]) -> Result<Self> {
108120
use hickory_proto::rr;
109121
let (node_id, txt) = records
@@ -122,7 +134,9 @@ impl NodeInfo {
122134
Ok(node_info)
123135
}
124136

137+
/// Parse the [`NodeInfo`] from an attribute string.
125138
///
139+
/// See [Self::into_attribute_string] for the expected format.
126140
pub fn parse_from_attributes(attrs: &str) -> Result<Self> {
127141
let attrs = parse_attrs(attrs);
128142
let Some(node) = attrs.get(ATTR_NODE_ID) else {
@@ -143,7 +157,8 @@ impl NodeInfo {
143157
})
144158
}
145159

146-
///
160+
/// Create a [`pkarr::SignedPacket`] by constructing a DNS packet and
161+
/// signing it with a [`SecretKey`].
147162
pub fn into_pkarr_signed_packet(
148163
&self,
149164
secret_key: &SecretKey,
@@ -155,12 +170,11 @@ impl NodeInfo {
155170
Ok(signed_packet)
156171
}
157172

158-
///
159-
pub fn into_pkarr_dns_packet(&self, ttl: u32) -> Result<pkarr::dns::Packet<'static>> {
173+
fn into_pkarr_dns_packet(&self, ttl: u32) -> Result<pkarr::dns::Packet<'static>> {
160174
use pkarr::dns::{self, rdata};
161175
let name = dns::Name::new(IROH_NODE_TXT_LABEL)?.into_owned();
162176
let rdata = {
163-
let value = self.to_attr_string();
177+
let value = self.into_attribute_string();
164178
let txt = rdata::TXT::new().with_string(&value)?.into_owned();
165179
rdata::RData::TXT(txt)
166180
};
@@ -172,7 +186,7 @@ impl NodeInfo {
172186
Ok(packet)
173187
}
174188

175-
///
189+
/// Try to parse a [`NodeInfo`] from a [`pkarr::SignedPacket`].
176190
pub fn from_pkarr_signed_packet(packet: &pkarr::SignedPacket) -> Result<Self> {
177191
use pkarr::dns::{self, rdata::RData};
178192
let pubkey = packet.public_key();
@@ -194,11 +208,11 @@ impl NodeInfo {
194208

195209
let txt_record = txt_record.to_owned();
196210
let txt = String::try_from(txt_record)?;
197-
let an = Self::parse_from_attributes(&txt)?;
198-
if an.node_id != node_id {
211+
let info = Self::parse_from_attributes(&txt)?;
212+
if info.node_id != node_id {
199213
bail!("node id mismatch between record name and TXT value");
200214
}
201-
Ok(an)
215+
Ok(info)
202216
}
203217
}
204218

@@ -231,19 +245,3 @@ fn parse_attrs<'a>(s: &'a str) -> HashMap<&'a str, Vec<&'a str>> {
231245
map
232246
}
233247

234-
/// Encode a [`NodeId`] in [`z-base-32`] encoding.
235-
///
236-
/// [z-base-32]: https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
237-
pub fn to_z32(node_id: &NodeId) -> String {
238-
z32::encode(node_id.as_bytes())
239-
}
240-
241-
/// Parse a [`NodeId`] from [`z-base-32`] encoding.
242-
///
243-
/// [z-base-32]: https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
244-
pub fn from_z32(s: &str) -> Result<NodeId> {
245-
let bytes = z32::decode(s.as_bytes()).map_err(|_| anyhow!("invalid z32"))?;
246-
let bytes: &[u8; 32] = &bytes.try_into().map_err(|_| anyhow!("not 32 bytes long"))?;
247-
let node_id = NodeId::from_bytes(bytes)?;
248-
Ok(node_id)
249-
}

0 commit comments

Comments
 (0)