@@ -162,9 +162,9 @@ impl NodeInfo {
162
162
self . into ( )
163
163
}
164
164
165
- /// Parses a [`NodeInfo`] from a set of DNS records.
166
- pub fn from_hickory_records ( records : & [ hickory_resolver:: proto :: rr :: Record ] ) -> Result < Self > {
167
- let attrs = TxtAttrs :: from_hickory_records ( records ) ?;
165
+ /// Parses a [`NodeInfo`] from a TXT records lookup .
166
+ pub fn from_hickory_lookup ( lookup : hickory_resolver:: lookup :: TxtLookup ) -> Result < Self > {
167
+ let attrs = TxtAttrs :: from_hickory_lookup ( lookup ) ?;
168
168
Ok ( attrs. into ( ) )
169
169
}
170
170
@@ -240,13 +240,9 @@ impl<T: FromStr + Display + Hash + Ord> TxtAttrs<T> {
240
240
}
241
241
242
242
/// Creates [`TxtAttrs`] from a node id and an iterator of "{key}={value}" strings.
243
- pub fn from_strings (
244
- node_id : NodeId ,
245
- strings : impl Iterator < Item = Result < String > > ,
246
- ) -> Result < Self > {
243
+ pub fn from_strings ( node_id : NodeId , strings : impl Iterator < Item = String > ) -> Result < Self > {
247
244
let mut attrs: BTreeMap < T , Vec < String > > = BTreeMap :: new ( ) ;
248
245
for s in strings {
249
- let s = s?;
250
246
let mut parts = s. split ( '=' ) ;
251
247
let ( Some ( key) , Some ( value) ) = ( parts. next ( ) , parts. next ( ) ) else {
252
248
continue ;
@@ -262,7 +258,7 @@ impl<T: FromStr + Display + Hash + Ord> TxtAttrs<T> {
262
258
async fn lookup ( resolver : & TokioResolver , name : Name ) -> Result < Self > {
263
259
let name = ensure_iroh_txt_label ( name) ?;
264
260
let lookup = resolver. txt_lookup ( name) . await ?;
265
- let attrs = Self :: from_hickory_records ( lookup. as_lookup ( ) . records ( ) ) ?;
261
+ let attrs = Self :: from_hickory_lookup ( lookup) ?;
266
262
Ok ( attrs)
267
263
}
268
264
@@ -311,29 +307,23 @@ impl<T: FromStr + Display + Hash + Ord> TxtAttrs<T> {
311
307
_ => None ,
312
308
} ) ;
313
309
314
- let txt_strs = txt_data. filter_map ( |s| String :: try_from ( s. clone ( ) ) . ok ( ) . map ( Ok ) ) ;
310
+ let txt_strs = txt_data. filter_map ( |s| String :: try_from ( s. clone ( ) ) . ok ( ) ) ;
315
311
Self :: from_strings ( node_id, txt_strs)
316
312
}
317
313
318
- /// Parses a set of DNS resource records.
319
- pub fn from_hickory_records ( records : & [ hickory_resolver:: proto:: rr:: Record ] ) -> Result < Self > {
320
- use hickory_resolver:: proto:: rr;
321
- let mut records = records. iter ( ) . filter_map ( |rr| match rr. data ( ) {
322
- rr:: RData :: TXT ( txt) => {
323
- node_id_from_hickory_name ( rr. name ( ) ) . map ( |node_id| ( node_id, txt) )
314
+ /// Parses a TXT records lookup.
315
+ pub fn from_hickory_lookup ( lookup : hickory_resolver:: lookup:: TxtLookup ) -> Result < Self > {
316
+ let node_id = node_id_from_hickory_name ( lookup. query ( ) . name ( ) )
317
+ . ok_or_else ( || anyhow ! ( "invalid DNS answer: not a query for _iroh.z32encodedpubkey" ) ) ?;
318
+
319
+ let strings = lookup. as_lookup ( ) . record_iter ( ) . filter_map ( |record| {
320
+ match node_id_from_hickory_name ( record. name ( ) ) {
321
+ // Filter out only TXT record answers that match the node_id we searched for.
322
+ Some ( n) if n == node_id => record. data ( ) . as_txt ( ) . map ( |txt| txt. to_string ( ) ) ,
323
+ _ => None ,
324
324
}
325
- _ => None ,
326
325
} ) ;
327
- let ( node_id, first) = records. next ( ) . ok_or_else ( || {
328
- anyhow ! ( "invalid DNS answer: no TXT record with name _iroh.z32encodedpubkey found" )
329
- } ) ?;
330
- let strings = records. map ( |( n, txt) | {
331
- if n == node_id {
332
- Ok ( txt. to_string ( ) )
333
- } else {
334
- Err ( anyhow ! ( "invalid DNS answer: all _iroh txt records must belong to the same node domain" ) )
335
- }
336
- } ) . chain ( Some ( Ok ( first. to_string ( ) ) ) ) ;
326
+
337
327
Self :: from_strings ( node_id, strings)
338
328
}
339
329
@@ -410,10 +400,14 @@ fn node_domain(node_id: &NodeId, origin: &str) -> Result<Name> {
410
400
411
401
#[ cfg( test) ]
412
402
mod tests {
413
- use std:: { collections:: BTreeSet , str:: FromStr } ;
403
+ use std:: { collections:: BTreeSet , str:: FromStr , sync :: Arc } ;
414
404
415
405
use hickory_resolver:: {
416
- proto:: rr:: { rdata:: TXT , RData , Record } ,
406
+ lookup:: Lookup ,
407
+ proto:: {
408
+ op:: Query ,
409
+ rr:: { rdata:: TXT , RData , Record , RecordType } ,
410
+ } ,
417
411
Name ,
418
412
} ;
419
413
use iroh_base:: { NodeId , SecretKey } ;
@@ -460,7 +454,8 @@ mod tests {
460
454
let name = Name :: from_utf8 (
461
455
"_iroh.dgjpkxyn3zyrk3zfads5duwdgbqpkwbjxfj4yt7rezidr3fijccy.dns.iroh.link." ,
462
456
) ?;
463
- let test_records = [
457
+ let query = Query :: query ( name. clone ( ) , RecordType :: TXT ) ;
458
+ let records = [
464
459
Record :: from_rdata (
465
460
name. clone ( ) ,
466
461
30 ,
@@ -479,9 +474,9 @@ mod tests {
479
474
] ) ) ,
480
475
) ,
481
476
] ;
477
+ let lookup = Lookup :: new_with_max_ttl ( query, Arc :: new ( records) ) ;
482
478
483
- let node_info = NodeInfo :: from_hickory_records ( & test_records) ?;
484
-
479
+ let node_info = NodeInfo :: from_hickory_lookup ( lookup. into ( ) ) ?;
485
480
assert_eq ! (
486
481
node_info,
487
482
NodeInfo {
0 commit comments