From bd583a107f95871f1bef159f0620bd606c7f6621 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 11:52:31 -0400 Subject: [PATCH 01/12] Add SRV rr to rrtype.rs --- src/message/rrtype.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/message/rrtype.rs b/src/message/rrtype.rs index 0f1030d9..febc8494 100644 --- a/src/message/rrtype.rs +++ b/src/message/rrtype.rs @@ -13,6 +13,7 @@ pub enum Rrtype { MX, TXT, AAAA, + SRV, DNAME, OPT, DS, @@ -43,6 +44,7 @@ impl From for u16 { Rrtype::MX => 15, Rrtype::TXT => 16, Rrtype::AAAA => 28, + Rrtype::SRV => 33, Rrtype::DNAME => 39, Rrtype::OPT => 41, Rrtype::DS => 43, @@ -74,6 +76,7 @@ impl From for Rrtype { 15 => Rrtype::MX, 16 => Rrtype::TXT, 28 => Rrtype::AAAA, + 33 => Rrtype::SRV, 39 => Rrtype::DNAME, 41 => Rrtype::OPT, 43 => Rrtype::DS, @@ -105,6 +108,7 @@ impl From<&str> for Rrtype { "MX" => Rrtype::MX, "TXT" => Rrtype::TXT, "AAAA" => Rrtype::AAAA, + "SRV" => Rrtype::SRV, "DNAME" => Rrtype::DNAME, "OPT" => Rrtype::OPT, "DS" => Rrtype::DS, @@ -139,6 +143,7 @@ impl fmt::Display for Rrtype { Rrtype::MX => "MX", Rrtype::TXT => "TXT", Rrtype::AAAA => "AAAA", + Rrtype::SRV => "SRV", Rrtype::DNAME => "DNAME", Rrtype::OPT => "OPT", Rrtype::DS => "DS", From 94ecc4802dbfb40cc59dbd2f88b51d3152e466b6 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 12:20:49 -0400 Subject: [PATCH 02/12] feat: Add SrvRdata struct for SRV resource record type --- src/message/rdata/srv_rdata.rs | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/message/rdata/srv_rdata.rs diff --git a/src/message/rdata/srv_rdata.rs b/src/message/rdata/srv_rdata.rs new file mode 100644 index 00000000..e4adf8c2 --- /dev/null +++ b/src/message/rdata/srv_rdata.rs @@ -0,0 +1,48 @@ +use crate::domain_name::DomainName; + + +/// RFC 2782: https://datatracker.ietf.org/doc/html/rfc2782 +/// An struct that represents the `Rdata` for srv type. + +pub struct SrvRdata { + /// The priority of this target host. A client MUST attempt to contact the target host with the lowest-numbered priority it can reach; target hosts with the same priority SHOULD be tried in an order defined by the weight field. + priority: u16, + /// A server selection mechanism. The weight field specifies a relative weight for entries with the same priority. Larger weights SHOULD be given a proportionately higher probability of being selected. + weight: u16, + /// The port on this target host of this service. + port: u16, + /// The domain name of the target host. + target: DomainName, +} + +impl SrvRdata { + + /// Creates a new `SrvRdata` with default values. + /// + /// # Example + /// ``` + /// let srv_rdata = SrvRdata::new(); + /// ``` + pub fn new() -> SrvRdata { + SrvRdata { + priority: 0, + weight: 0, + port: 0, + target: DomainName::new(), + } + } + + /// Creates a new `SrvRdata` with the specified values. + /// # Example + /// ``` + /// let srv_rdata = SrvRdata::new_with_values(1, 2, 3, DomainName::new_from_str("www.example.com")); + /// ``` + pub fn new_with_values(priority: u16, weight: u16, port: u16, target: DomainName) -> SrvRdata { + SrvRdata { + priority, + weight, + port, + target, + } + } +} \ No newline at end of file From e39a96a863ef5c3d2c478d5bdd1022b5abe0661f Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 12:24:19 -0400 Subject: [PATCH 03/12] add getters and setters --- src/message/rdata/srv_rdata.rs | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/message/rdata/srv_rdata.rs b/src/message/rdata/srv_rdata.rs index e4adf8c2..41a00c40 100644 --- a/src/message/rdata/srv_rdata.rs +++ b/src/message/rdata/srv_rdata.rs @@ -45,4 +45,48 @@ impl SrvRdata { target, } } +} + +impl SrvRdata { + /// Gets the priority atrribute of the SrvRdata. + pub fn get_priority(&self) -> u16 { + self.priority + } + + /// Gets the weight atrribute of the SrvRdata. + pub fn get_weight(&self) -> u16 { + self.weight + } + + /// Gets the port atrribute of the SrvRdata. + pub fn get_port(&self) -> u16 { + self.port + } + + /// Gets the target atrribute of the SrvRdata. + pub fn get_target(&self) -> DomainName { + self.target.clone() + } +} + +impl SrvRdata { + /// Sets the priority atrribute of the SrvRdata. + pub fn set_priority(&mut self, priority: u16) { + self.priority = priority; + } + + /// Sets the weight atrribute of the SrvRdata. + pub fn set_weight(&mut self, weight: u16) { + self.weight = weight; + } + + /// Sets the port atrribute of the SrvRdata. + pub fn set_port(&mut self, port: u16) { + self.port = port; + } + + /// Sets the target atrribute of the SrvRdata. + pub fn set_target(&mut self, target: DomainName) { + self.target = target; + } } \ No newline at end of file From d04b77591e0c40aa13ade4a83fc93bb7f05034b4 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 12:30:31 -0400 Subject: [PATCH 04/12] implement tobytes fn --- src/message/rdata/srv_rdata.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/message/rdata/srv_rdata.rs b/src/message/rdata/srv_rdata.rs index 41a00c40..c2e76ec1 100644 --- a/src/message/rdata/srv_rdata.rs +++ b/src/message/rdata/srv_rdata.rs @@ -1,4 +1,5 @@ use crate::domain_name::DomainName; +use crate::message::resource_record::{FromBytes, ToBytes}; /// RFC 2782: https://datatracker.ietf.org/doc/html/rfc2782 @@ -15,6 +16,36 @@ pub struct SrvRdata { target: DomainName, } +impl ToBytes for SrvRdata { + /// Return a `Vec` of bytes that represents the srv rdata. + fn to_bytes(&self) -> Vec { + let mut bytes: Vec = Vec::new(); + let priority_bytes = self.get_priority().to_be_bytes(); + let weight_bytes = self.get_weight().to_be_bytes(); + let port_bytes = self.get_port().to_be_bytes(); + let target_bytes = self.get_target().to_bytes(); + + for byte in priority_bytes.as_slice() { + bytes.push(*byte); + } + + for byte in weight_bytes.as_slice() { + bytes.push(*byte); + } + + for byte in port_bytes.as_slice() { + bytes.push(*byte); + } + + for byte in target_bytes.as_slice() { + bytes.push(*byte); + } + + bytes + + } +} + impl SrvRdata { /// Creates a new `SrvRdata` with default values. From 5dd10dc0840c9efee23eef2e69a4091fe01024c9 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 12:35:20 -0400 Subject: [PATCH 05/12] feat: Implement FromBytes trait for SrvRdata --- src/message/rdata/srv_rdata.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/message/rdata/srv_rdata.rs b/src/message/rdata/srv_rdata.rs index c2e76ec1..c0ec4c34 100644 --- a/src/message/rdata/srv_rdata.rs +++ b/src/message/rdata/srv_rdata.rs @@ -46,6 +46,26 @@ impl ToBytes for SrvRdata { } } +impl FromBytes> for SrvRdata { + /// Return a `SrvRdata` from an array of bytes. + fn from_bytes(bytes: &[u8], full_msg: &[u8]) -> Result { + let bytes_len = bytes.len(); + + if bytes_len < 6 { + return Err("The bytes slice is too short to parse the SRV Rdata"); + } + + let priority = u16::from_be_bytes([bytes[0], bytes[1]]); + let weight = u16::from_be_bytes([bytes[2], bytes[3]]); + let port = u16::from_be_bytes([bytes[4], bytes[5]]); + let (target, _) = DomainName::from_bytes(&bytes[6..], full_msg).unwrap(); + + let srv_rdata = SrvRdata::new_with_values(priority, weight, port, target); + + Ok(srv_rdata) + } +} + impl SrvRdata { /// Creates a new `SrvRdata` with default values. From b65a5b1465d938d0ca86f31f4fdd46e4b0b96b65 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 13:49:59 -0400 Subject: [PATCH 06/12] add basic tests --- src/message/rdata.rs | 1 + src/message/rdata/srv_rdata.rs | 37 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/message/rdata.rs b/src/message/rdata.rs index 4075b0c0..2aa10fe5 100644 --- a/src/message/rdata.rs +++ b/src/message/rdata.rs @@ -16,6 +16,7 @@ pub mod dnskey_rdata; pub mod nsec3_rdata; pub mod nsec3param_rdata; pub mod tsig_rdata; +pub mod srv_rdata; use core::fmt; use crate::message::resource_record::{FromBytes, ToBytes}; diff --git a/src/message/rdata/srv_rdata.rs b/src/message/rdata/srv_rdata.rs index c0ec4c34..2461c000 100644 --- a/src/message/rdata/srv_rdata.rs +++ b/src/message/rdata/srv_rdata.rs @@ -140,4 +140,41 @@ impl SrvRdata { pub fn set_target(&mut self, target: DomainName) { self.target = target; } +} + +#[cfg(test)] +mod srv_rdata_tests { + use super::*; + + #[test] + fn construct_srv_rdata() { + let srv_rdata = SrvRdata::new(); + assert_eq!(srv_rdata.get_priority(), 0); + assert_eq!(srv_rdata.get_weight(), 0); + assert_eq!(srv_rdata.get_port(), 0); + assert_eq!(srv_rdata.get_target(), DomainName::new()); + } + + #[test] + fn construct_srv_rdata_with_values() { + let srv_rdata = SrvRdata::new_with_values(1, 2, 3, DomainName::new_from_str("www.example.com")); + assert_eq!(srv_rdata.get_priority(), 1); + assert_eq!(srv_rdata.get_weight(), 2); + assert_eq!(srv_rdata.get_port(), 3); + assert_eq!(srv_rdata.get_target(), DomainName::new_from_str("www.example.com")); + } + + #[test] + fn get_and_set_srv_rdata_values() { + let mut srv_rdata = SrvRdata::new(); + srv_rdata.set_priority(1); + srv_rdata.set_weight(2); + srv_rdata.set_port(3); + srv_rdata.set_target(DomainName::new_from_str("www.example.com")); + + assert_eq!(srv_rdata.get_priority(), 1); + assert_eq!(srv_rdata.get_weight(), 2); + assert_eq!(srv_rdata.get_port(), 3); + assert_eq!(srv_rdata.get_target(), DomainName::new_from_str("www.example.com")); + } } \ No newline at end of file From c4baccf7171a137d048027db718fb115e0c12651 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 17:41:09 -0400 Subject: [PATCH 07/12] Implement to_bytes function for SrvRdata --- src/message/rdata/srv_rdata.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/message/rdata/srv_rdata.rs b/src/message/rdata/srv_rdata.rs index 2461c000..3a2e7fc2 100644 --- a/src/message/rdata/srv_rdata.rs +++ b/src/message/rdata/srv_rdata.rs @@ -177,4 +177,34 @@ mod srv_rdata_tests { assert_eq!(srv_rdata.get_port(), 3); assert_eq!(srv_rdata.get_target(), DomainName::new_from_str("www.example.com")); } + + #[test] + fn to_bytes() { + let srv_rdata = SrvRdata::new_with_values(1, 2, 3, DomainName::new_from_str("www.example.com")); + let bytes = srv_rdata.to_bytes(); + let expected_bytes = vec![0, 1, + 0, 2, + 0, 3, + 3, 119, 119, 119, + 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, + 0]; + assert_eq!(bytes, expected_bytes); + } + + #[test] + fn from_bytes() { + let bytes = vec![0, 1, + 0, 2, + 0, 3, + 3, 119, 119, 119, + 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, + 0]; + + let srv_rdata = SrvRdata::from_bytes(&bytes, &bytes).unwrap(); + + assert_eq!(srv_rdata.get_priority(), 1); + assert_eq!(srv_rdata.get_weight(), 2); + assert_eq!(srv_rdata.get_port(), 3); + assert_eq!(srv_rdata.get_target(), DomainName::new_from_str("www.example.com")); + } } \ No newline at end of file From a61a4bca453e5d5f9aadb40b9a1f14ab22529fc2 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 17:42:14 -0400 Subject: [PATCH 08/12] Refactor SrvRdata serialization and add tests --- src/message/rdata/srv_rdata.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/message/rdata/srv_rdata.rs b/src/message/rdata/srv_rdata.rs index 3a2e7fc2..34e9770f 100644 --- a/src/message/rdata/srv_rdata.rs +++ b/src/message/rdata/srv_rdata.rs @@ -186,7 +186,8 @@ mod srv_rdata_tests { 0, 2, 0, 3, 3, 119, 119, 119, - 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, + 7, 101, 120, 97, 109, 112, 108, 101, + 3, 99, 111, 109, 0]; assert_eq!(bytes, expected_bytes); } @@ -197,7 +198,8 @@ mod srv_rdata_tests { 0, 2, 0, 3, 3, 119, 119, 119, - 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, + 7, 101, 120, 97, 109, 112, 108, 101, + 3, 99, 111, 109, 0]; let srv_rdata = SrvRdata::from_bytes(&bytes, &bytes).unwrap(); From b9ad8bd4235897719969db91cf8d8dcc075e75ff Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 17:47:00 -0400 Subject: [PATCH 09/12] integrate srv_rdata to rdata --- src/message/rdata.rs | 16 ++++++++++++++++ src/message/rdata/srv_rdata.rs | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/message/rdata.rs b/src/message/rdata.rs index 2aa10fe5..485986c2 100644 --- a/src/message/rdata.rs +++ b/src/message/rdata.rs @@ -38,6 +38,7 @@ use dnskey_rdata::DnskeyRdata; use nsec3_rdata::Nsec3Rdata; use nsec3param_rdata::Nsec3ParamRdata; use tsig_rdata::TSigRdata; +use srv_rdata::SrvRdata; #[derive(Clone, PartialEq, Debug)] /// Enumerates the differents types of `Rdata` struct. @@ -52,6 +53,7 @@ pub enum Rdata { CNAME(CnameRdata), HINFO(HinfoRdata), AAAA(AAAARdata), + SRV(SrvRdata), OPT(OptRdata), DS(DsRdata), RRSIG(RRSIGRdata), @@ -87,6 +89,7 @@ impl ToBytes for Rdata { Rdata::SOA(val) => val.to_bytes(), Rdata::TXT(val) => val.to_bytes(), Rdata::AAAA(val) => val.to_bytes(), + Rdata::SRV(val) => val.to_bytes(), Rdata::CNAME(val) => val.to_bytes(), Rdata::HINFO(val) => val.to_bytes(), Rdata::OPT(val) => val.to_bytes(), @@ -229,6 +232,18 @@ impl FromBytes> for Rdata { Ok(Rdata::AAAA(rdata.unwrap())) } + 33 => { + let rdata = SrvRdata::from_bytes(&bytes[..bytes.len() - 4], full_msg); + + match rdata { + Ok(_) => {} + Err(e) => { + return Err(e); + } + } + + Ok(Rdata::SRV(rdata.unwrap())) + } 39 => { let rdata = CnameRdata::from_bytes(&bytes[..bytes.len() - 4], full_msg); @@ -348,6 +363,7 @@ impl fmt::Display for Rdata { Rdata::SOA(val) => write!(f, "{}", val), Rdata::TXT(val) => write!(f, "{}", val), Rdata::AAAA(val) => write!(f, "{}", val), + Rdata::SRV(val) => write!(f, "{}", val), Rdata::CNAME(val) => write!(f, "{}", val), Rdata::HINFO(val) => write!(f, "{}", val), Rdata::OPT(val) => write!(f, "{}", val), diff --git a/src/message/rdata/srv_rdata.rs b/src/message/rdata/srv_rdata.rs index 34e9770f..95180c6e 100644 --- a/src/message/rdata/srv_rdata.rs +++ b/src/message/rdata/srv_rdata.rs @@ -1,3 +1,5 @@ +use core::fmt; + use crate::domain_name::DomainName; use crate::message::resource_record::{FromBytes, ToBytes}; @@ -5,6 +7,7 @@ use crate::message::resource_record::{FromBytes, ToBytes}; /// RFC 2782: https://datatracker.ietf.org/doc/html/rfc2782 /// An struct that represents the `Rdata` for srv type. +#[derive(Clone, Debug, PartialEq)] pub struct SrvRdata { /// The priority of this target host. A client MUST attempt to contact the target host with the lowest-numbered priority it can reach; target hosts with the same priority SHOULD be tried in an order defined by the weight field. priority: u16, @@ -142,6 +145,20 @@ impl SrvRdata { } } +impl fmt::Display for SrvRdata { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Priority: {}, + Weight: {}, + Port: {}, + Target: {}", + self.get_priority(), + self.get_weight(), + self.get_port(), + self.get_target()) + + } +} + #[cfg(test)] mod srv_rdata_tests { use super::*; From 7cbc0ad8e85ae885d741e1a9de2b964589876867 Mon Sep 17 00:00:00 2001 From: Litr0 Date: Wed, 17 Jul 2024 17:51:37 -0400 Subject: [PATCH 10/12] test from and to bytes in rdata for srv rdata. --- src/message/rdata.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/message/rdata.rs b/src/message/rdata.rs index 485986c2..c186c080 100644 --- a/src/message/rdata.rs +++ b/src/message/rdata.rs @@ -403,6 +403,7 @@ mod resolver_query_tests { use super::nsec3param_rdata::Nsec3ParamRdata; use super::tsig_rdata::TSigRdata; use super::aaaa_rdata::AAAARdata; + use super::srv_rdata::SrvRdata; use std::net::IpAddr; use std::vec; @@ -760,6 +761,17 @@ mod resolver_query_tests { assert_eq!(bytes, expected_bytes); } + #[test] + fn to_bytes_srv_rdata(){ + let srv_rdata = SrvRdata::new_with_values(1, 2, 3, DomainName::new_from_str("example.com")); + + let expected_bytes = [0, 1, 0, 2, 0, 3, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0]; + + let bytes = Rdata::SRV(srv_rdata).to_bytes(); + + assert_eq!(bytes, expected_bytes); + } + //from bytes tests #[test] fn from_bytes_a_ch_rdata(){ @@ -1108,6 +1120,21 @@ mod resolver_query_tests { } } + #[test] + fn from_bytes_srv_rdata(){ + let data_bytes = [0, 1, 0, 2, 0, 3, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 0, 33, 0, 1]; + let rdata = Rdata::from_bytes(&data_bytes, &data_bytes).unwrap(); + match rdata { + Rdata::SRV(val) => { + assert_eq!(val.get_priority(), 1); + assert_eq!(val.get_weight(), 2); + assert_eq!(val.get_port(), 3); + assert_eq!(val.get_target().get_name(), "example.com"); + } + _ => {} + } + } + #[test] #[should_panic] fn from_bytes_format_error(){ From df478aee56b86124f29fec83c02af28f34759753 Mon Sep 17 00:00:00 2001 From: Ephy Date: Wed, 24 Jul 2024 13:05:49 -0400 Subject: [PATCH 11/12] unused save_negative_answer --- src/resolver_cache.rs | 582 ++++++++++++++++++++++++++++++++---------- 1 file changed, 445 insertions(+), 137 deletions(-) diff --git a/src/resolver_cache.rs b/src/resolver_cache.rs index eb0a52d5..fce779d1 100644 --- a/src/resolver_cache.rs +++ b/src/resolver_cache.rs @@ -1,11 +1,11 @@ use crate::dns_cache::{CacheKey, DnsCache}; use crate::domain_name::DomainName; -use crate::message::resource_record::ResourceRecord; -use crate::message::rrtype::Rrtype; use crate::message::rclass::Rclass; use crate::message::rcode::Rcode; -use crate::message::DnsMessage; use crate::message::rdata::*; +use crate::message::resource_record::ResourceRecord; +use crate::message::rrtype::Rrtype; +use crate::message::DnsMessage; use std::num::NonZeroUsize; @@ -17,7 +17,6 @@ pub struct ResolverCache { } impl ResolverCache { - /// Create a new ResolverCache with the given size. pub fn new(size: Option) -> Self { let size = size.unwrap_or(NonZeroUsize::new(1667).unwrap()); @@ -50,33 +49,61 @@ impl ResolverCache { /// See if the cache is empty. pub fn is_empty(&self) -> bool { - self.cache_answer.is_empty() && self.cache_authority.is_empty() && self.cache_additional.is_empty() + self.cache_answer.is_empty() + && self.cache_authority.is_empty() + && self.cache_additional.is_empty() } /// See if an element is in the cache. pub fn is_cached(&self, cache_key: CacheKey) -> bool { - self.cache_answer.is_cached(cache_key.clone()) || self.cache_authority.is_cached(cache_key.clone()) || self.cache_additional.is_cached(cache_key.clone()) + self.cache_answer.is_cached(cache_key.clone()) + || self.cache_authority.is_cached(cache_key.clone()) + || self.cache_additional.is_cached(cache_key.clone()) } /// Add an element to the answer cache. - pub fn add_answer(&mut self, domain_name: DomainName, resource_record: ResourceRecord, qtype: Option, qclass: Rclass, rcode: Option) { + pub fn add_answer( + &mut self, + domain_name: DomainName, + resource_record: ResourceRecord, + qtype: Option, + qclass: Rclass, + rcode: Option, + ) { if resource_record.get_ttl() > 0 { - self.cache_answer.add(domain_name, resource_record, qtype, qclass, rcode); + self.cache_answer + .add(domain_name, resource_record, qtype, qclass, rcode); } } /// Add an element to the authority cache. - pub fn add_authority(&mut self, domain_name: DomainName, resource_record: ResourceRecord, qtype: Option, qclass: Rclass, rcode: Option) { + pub fn add_authority( + &mut self, + domain_name: DomainName, + resource_record: ResourceRecord, + qtype: Option, + qclass: Rclass, + rcode: Option, + ) { if resource_record.get_ttl() > 0 { - self.cache_authority.add(domain_name, resource_record, qtype, qclass, rcode); + self.cache_authority + .add(domain_name, resource_record, qtype, qclass, rcode); } } /// Add an element to the additional cache. - pub fn add_additional(&mut self, domain_name: DomainName, resource_record: ResourceRecord, qtype: Option, qclass: Rclass, rcode: Option) { + pub fn add_additional( + &mut self, + domain_name: DomainName, + resource_record: ResourceRecord, + qtype: Option, + qclass: Rclass, + rcode: Option, + ) { if resource_record.get_ttl() > 0 { if resource_record.get_rtype() != Rrtype::OPT { - self.cache_additional.add(domain_name, resource_record, qtype, qclass, rcode); + self.cache_additional + .add(domain_name, resource_record, qtype, qclass, rcode); } } } @@ -92,9 +119,7 @@ impl ResolverCache { let key; if rcode == Some(Rcode::NXDOMAIN) { key = CacheKey::Secondary(qclass, qname.clone()); - } - - else { + } else { key = CacheKey::Primary(qtype.unwrap(), qclass, qname.clone()); } @@ -102,20 +127,18 @@ impl ResolverCache { self.remove(qname.clone(), qtype, qclass); } - // Get the minimum TTL from the SOA record if the answer is negative let mut minimum = 0; if rcode != Some(Rcode::NOERROR) { - for rr in message.get_authority(){ + for rr in message.get_authority() { if rr.get_rtype() == Rrtype::SOA { match rr.get_rdata() { Rdata::SOA(soa) => { minimum = soa.get_minimum(); - } _ => {} } - break + break; } } } @@ -124,37 +147,38 @@ impl ResolverCache { let authorities = message.get_authority(); let additionals = message.get_additional(); - answers.iter() - .for_each(|rr| { - let mut rr = rr.clone(); - if minimum != 0 { - rr.set_ttl(minimum); - } - self.add_answer(qname.clone(), rr, qtype, qclass, rcode); - }); + answers.iter().for_each(|rr| { + let mut rr = rr.clone(); + if minimum != 0 { + rr.set_ttl(minimum); + } + self.add_answer(qname.clone(), rr, qtype, qclass, rcode); + }); - authorities.iter() - .for_each(|rr| { + authorities.iter().for_each(|rr| { let mut rr = rr.clone(); - if minimum != 0 { - rr.set_ttl(minimum); - } + if minimum != 0 { + rr.set_ttl(minimum); + } self.add_authority(qname.clone(), rr.clone(), qtype, qclass, rcode); - }); - additionals.iter() - .for_each(|rr| { + additionals.iter().for_each(|rr| { let mut rr = rr.clone(); - if minimum != 0 { - rr.set_ttl(minimum); - } - self.add_additional(qname.clone(), rr.clone(), qtype, qclass, rcode); + if minimum != 0 { + rr.set_ttl(minimum); + } + self.add_additional(qname.clone(), rr.clone(), qtype, qclass, rcode); }); } /// Gets elements from the answer cache - pub fn get_answer(&mut self, domain_name: DomainName, qtype: Rrtype, qclass: Rclass) -> Option> { + pub fn get_answer( + &mut self, + domain_name: DomainName, + qtype: Rrtype, + qclass: Rclass, + ) -> Option> { let rr_stored_data = self.cache_answer.get(domain_name, qtype, qclass); if let Some(rr_stored_data) = rr_stored_data { @@ -169,7 +193,12 @@ impl ResolverCache { } /// Gets elements from the authority cache - pub fn get_authority(&mut self, domain_name: DomainName, qtype: Rrtype, qclass: Rclass) -> Option> { + pub fn get_authority( + &mut self, + domain_name: DomainName, + qtype: Rrtype, + qclass: Rclass, + ) -> Option> { let rr_stored_data = self.cache_authority.get(domain_name, qtype, qclass); if let Some(rr_stored_data) = rr_stored_data { @@ -184,7 +213,12 @@ impl ResolverCache { } /// Gets elements from the additional cache - pub fn get_additional(&mut self, domain_name: DomainName, qtype: Rrtype, qclass: Rclass) -> Option> { + pub fn get_additional( + &mut self, + domain_name: DomainName, + qtype: Rrtype, + qclass: Rclass, + ) -> Option> { let rr_stored_data = self.cache_additional.get(domain_name, qtype, qclass); if let Some(rr_stored_data) = rr_stored_data { @@ -198,7 +232,12 @@ impl ResolverCache { } } - pub fn get_rcode(&mut self, domain_name: DomainName, qtype: Rrtype, qclass: Rclass) -> Option { + pub fn get_rcode( + &mut self, + domain_name: DomainName, + qtype: Rrtype, + qclass: Rclass, + ) -> Option { let rr_stored_data = self.cache_answer.get(domain_name, qtype, qclass); if let Some(rr_stored_data) = rr_stored_data { @@ -245,9 +284,10 @@ impl ResolverCache { message.set_additional(additionals); } - if message.get_answer().is_empty() && - message.get_authority().is_empty() && - message.get_additional().is_empty() { + if message.get_answer().is_empty() + && message.get_authority().is_empty() + && message.get_additional().is_empty() + { None } else { Some(message) @@ -255,20 +295,35 @@ impl ResolverCache { } /// Removes an element from the answer cache. - pub fn remove_answer(&mut self, domain_name: DomainName, qtype: Option, qclass: Rclass) { + pub fn remove_answer( + &mut self, + domain_name: DomainName, + qtype: Option, + qclass: Rclass, + ) { self.cache_answer.remove(domain_name, qtype, qclass); } - + /// Removes an element from the authority cache. - pub fn remove_authority(&mut self, domain_name: DomainName, qtype: Option, qclass: Rclass) { + pub fn remove_authority( + &mut self, + domain_name: DomainName, + qtype: Option, + qclass: Rclass, + ) { self.cache_authority.remove(domain_name, qtype, qclass); } - + /// Removes an element from the additional cache. - pub fn remove_additional(&mut self, domain_name: DomainName, qtype: Option, qclass: Rclass) { + pub fn remove_additional( + &mut self, + domain_name: DomainName, + qtype: Option, + qclass: Rclass, + ) { self.cache_additional.remove(domain_name, qtype, qclass); } - + /// Removes an element from the cache. pub fn remove(&mut self, domain_name: DomainName, qtype: Option, qclass: Rclass) { self.remove_answer(domain_name.clone(), qtype, qclass); @@ -300,7 +355,6 @@ impl ResolverCache { } impl ResolverCache { - /// Get the answer cache. pub fn get_cache_answer(&self) -> &DnsCache { &self.cache_answer @@ -317,9 +371,7 @@ impl ResolverCache { } } - impl ResolverCache { - /// Set the answer cache. pub fn set_cache_answer(&mut self, cache: DnsCache) { self.cache_answer = cache; @@ -337,73 +389,104 @@ impl ResolverCache { } #[cfg(test)] -mod resolver_cache_test{ +mod resolver_cache_test { use super::*; - use crate::message::rrtype::Rrtype; + use crate::message::question::Question; use crate::message::rdata::a_rdata::ARdata; use crate::message::rdata::Rdata; - use crate::message::question::Question; + use crate::message::rrtype::Rrtype; use std::net::IpAddr; #[test] fn constructor_test() { let resolver_cache = ResolverCache::new(None); - assert_eq!(resolver_cache.get_cache_answer().get_max_size(), NonZeroUsize::new(1667).unwrap()); - assert_eq!(resolver_cache.get_cache_authority().get_max_size(), NonZeroUsize::new(1667).unwrap()); - assert_eq!(resolver_cache.get_cache_additional().get_max_size(), NonZeroUsize::new(1667).unwrap()); + assert_eq!( + resolver_cache.get_cache_answer().get_max_size(), + NonZeroUsize::new(1667).unwrap() + ); + assert_eq!( + resolver_cache.get_cache_authority().get_max_size(), + NonZeroUsize::new(1667).unwrap() + ); + assert_eq!( + resolver_cache.get_cache_additional().get_max_size(), + NonZeroUsize::new(1667).unwrap() + ); } #[test] fn with_sizes_test() { - let resolver_cache = ResolverCache::with_sizes(Some(NonZeroUsize::new(100).unwrap()), Some(NonZeroUsize::new(200).unwrap()), Some(NonZeroUsize::new(300).unwrap())); - assert_eq!(resolver_cache.get_cache_answer().get_max_size(), NonZeroUsize::new(100).unwrap()); - assert_eq!(resolver_cache.get_cache_authority().get_max_size(), NonZeroUsize::new(200).unwrap()); - assert_eq!(resolver_cache.get_cache_additional().get_max_size(), NonZeroUsize::new(300).unwrap()); + let resolver_cache = ResolverCache::with_sizes( + Some(NonZeroUsize::new(100).unwrap()), + Some(NonZeroUsize::new(200).unwrap()), + Some(NonZeroUsize::new(300).unwrap()), + ); + assert_eq!( + resolver_cache.get_cache_answer().get_max_size(), + NonZeroUsize::new(100).unwrap() + ); + assert_eq!( + resolver_cache.get_cache_authority().get_max_size(), + NonZeroUsize::new(200).unwrap() + ); + assert_eq!( + resolver_cache.get_cache_additional().get_max_size(), + NonZeroUsize::new(300).unwrap() + ); } #[test] - fn get_cache_answer(){ + fn get_cache_answer() { let resolver_cache = ResolverCache::new(None); let cache = resolver_cache.get_cache_answer(); assert_eq!(cache.get_max_size(), NonZeroUsize::new(1667).unwrap()); } #[test] - fn get_cache_authority(){ + fn get_cache_authority() { let resolver_cache = ResolverCache::new(None); let cache = resolver_cache.get_cache_authority(); assert_eq!(cache.get_max_size(), NonZeroUsize::new(1667).unwrap()); } #[test] - fn get_cache_additional(){ + fn get_cache_additional() { let resolver_cache = ResolverCache::new(None); let cache = resolver_cache.get_cache_additional(); assert_eq!(cache.get_max_size(), NonZeroUsize::new(1667).unwrap()); } #[test] - fn set_cache_answer(){ + fn set_cache_answer() { let mut resolver_cache = ResolverCache::new(None); let cache = DnsCache::new(None); resolver_cache.set_cache_answer(cache.clone()); - assert_eq!(resolver_cache.get_cache_answer().get_max_size(), cache.get_max_size()); + assert_eq!( + resolver_cache.get_cache_answer().get_max_size(), + cache.get_max_size() + ); } #[test] - fn set_cache_authority(){ + fn set_cache_authority() { let mut resolver_cache = ResolverCache::new(None); let cache = DnsCache::new(None); resolver_cache.set_cache_authority(cache.clone()); - assert_eq!(resolver_cache.get_cache_authority().get_max_size(), cache.get_max_size()); + assert_eq!( + resolver_cache.get_cache_authority().get_max_size(), + cache.get_max_size() + ); } #[test] - fn set_cache_additional(){ + fn set_cache_additional() { let mut resolver_cache = ResolverCache::new(None); let cache = DnsCache::new(None); resolver_cache.set_cache_additional(cache.clone()); - assert_eq!(resolver_cache.get_cache_additional().get_max_size(), cache.get_max_size()); + assert_eq!( + resolver_cache.get_cache_additional().get_max_size(), + cache.get_max_size() + ); } #[test] @@ -422,9 +505,18 @@ mod resolver_cache_test{ resource_record.set_type_code(Rrtype::A); resource_record.set_ttl(1000); - resolver_cache.add_answer(domain_name.clone(), resource_record.clone(), Some(Rrtype::A), Rclass::IN, None); - - let rr = resolver_cache.cache_answer.get(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); + resolver_cache.add_answer( + domain_name.clone(), + resource_record.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + + let rr = resolver_cache + .cache_answer + .get(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); assert_eq!(rr[0].get_resource_record(), resource_record); } @@ -445,9 +537,18 @@ mod resolver_cache_test{ resource_record.set_type_code(Rrtype::A); resource_record.set_ttl(1000); - resolver_cache.add_authority(domain_name.clone(), resource_record.clone(), Some(Rrtype::A), Rclass::IN, None); + resolver_cache.add_authority( + domain_name.clone(), + resource_record.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); - let rr = resolver_cache.cache_authority.get(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); + let rr = resolver_cache + .cache_authority + .get(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); assert_eq!(rr[0].get_resource_record(), resource_record); } @@ -468,15 +569,24 @@ mod resolver_cache_test{ resource_record.set_type_code(Rrtype::A); resource_record.set_ttl(1000); - resolver_cache.add_additional(domain_name.clone(), resource_record.clone(), Some(Rrtype::A), Rclass::IN, None); + resolver_cache.add_additional( + domain_name.clone(), + resource_record.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); - let rr = resolver_cache.cache_additional.get(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); + let rr = resolver_cache + .cache_additional + .get(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); assert_eq!(rr[0].get_resource_record(), resource_record); } #[test] - fn add(){ + fn add() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -522,7 +632,6 @@ mod resolver_cache_test{ message.set_query_id(1); - let mut question = Question::new(); question.set_qname(domain_name.clone()); question.set_rrtype(Rrtype::A); @@ -536,9 +645,18 @@ mod resolver_cache_test{ resolver_cache.add(message.clone()); - let rr_answer = resolver_cache.cache_answer.get(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); - let rr_authority = resolver_cache.cache_authority.get(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); - let rr_additional = resolver_cache.cache_additional.get(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); + let rr_answer = resolver_cache + .cache_answer + .get(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); + let rr_authority = resolver_cache + .cache_authority + .get(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); + let rr_additional = resolver_cache + .cache_additional + .get(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); assert_eq!(rr_answer[0].get_resource_record(), resource_record_1); assert_eq!(rr_authority[0].get_resource_record(), resource_record_2); @@ -546,7 +664,7 @@ mod resolver_cache_test{ } #[test] - fn get_answer(){ + fn get_answer() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -585,11 +703,31 @@ mod resolver_cache_test{ resource_record_3.set_type_code(Rrtype::A); resource_record_3.set_ttl(1000); - resolver_cache.add_answer(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_answer(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_answer(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); - - let rr = resolver_cache.get_answer(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); + resolver_cache.add_answer( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_answer( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_answer( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + + let rr = resolver_cache + .get_answer(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); assert_eq!(rr[0], resource_record_1); assert_eq!(rr[1], resource_record_2); @@ -597,7 +735,7 @@ mod resolver_cache_test{ } #[test] - fn get_authority(){ + fn get_authority() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -636,11 +774,31 @@ mod resolver_cache_test{ resource_record_3.set_type_code(Rrtype::A); resource_record_3.set_ttl(1000); - resolver_cache.add_authority(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_authority(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_authority(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); - - let rr = resolver_cache.get_authority(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); + resolver_cache.add_authority( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_authority( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_authority( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + + let rr = resolver_cache + .get_authority(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); assert_eq!(rr[0], resource_record_1); assert_eq!(rr[1], resource_record_2); @@ -648,7 +806,7 @@ mod resolver_cache_test{ } #[test] - fn get_additional(){ + fn get_additional() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -687,11 +845,31 @@ mod resolver_cache_test{ resource_record_3.set_type_code(Rrtype::A); resource_record_3.set_ttl(1000); - resolver_cache.add_additional(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_additional(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_additional(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); - - let rr = resolver_cache.get_additional(domain_name.clone(), Rrtype::A, Rclass::IN).unwrap(); + resolver_cache.add_additional( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_additional( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_additional( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + + let rr = resolver_cache + .get_additional(domain_name.clone(), Rrtype::A, Rclass::IN) + .unwrap(); assert_eq!(rr[0], resource_record_1); assert_eq!(rr[1], resource_record_2); @@ -699,7 +877,7 @@ mod resolver_cache_test{ } #[test] - fn get(){ + fn get() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -738,9 +916,27 @@ mod resolver_cache_test{ resource_record_3.set_type_code(Rrtype::A); resource_record_3.set_ttl(1000); - resolver_cache.add_answer(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_authority(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_additional(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); + resolver_cache.add_answer( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_authority( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_additional( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); let qname = DomainName::new_from_string("www.example.com".to_string()); let qtype = Rrtype::A; @@ -748,8 +944,15 @@ mod resolver_cache_test{ let op_code = 0; let rd = true; let id = 1; - - let query = DnsMessage::new_query_message(qname.clone(), qtype.clone(), qclass.clone(), op_code.clone(), rd.clone(), id.clone()); + + let query = DnsMessage::new_query_message( + qname.clone(), + qtype.clone(), + qclass.clone(), + op_code.clone(), + rd.clone(), + id.clone(), + ); let message = resolver_cache.get(query).unwrap(); @@ -763,7 +966,7 @@ mod resolver_cache_test{ } #[test] - fn remove_answer(){ + fn remove_answer() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -802,9 +1005,27 @@ mod resolver_cache_test{ resource_record_3.set_type_code(Rrtype::A); resource_record_3.set_ttl(1000); - resolver_cache.add_answer(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_answer(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_answer(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); + resolver_cache.add_answer( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_answer( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_answer( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); resolver_cache.remove_answer(domain_name.clone(), Some(Rrtype::A), Rclass::IN); @@ -814,7 +1035,7 @@ mod resolver_cache_test{ } #[test] - fn remove_authority(){ + fn remove_authority() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -853,9 +1074,27 @@ mod resolver_cache_test{ resource_record_3.set_type_code(Rrtype::A); resource_record_3.set_ttl(1000); - resolver_cache.add_authority(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_authority(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_authority(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); + resolver_cache.add_authority( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_authority( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_authority( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); resolver_cache.remove_authority(domain_name.clone(), Some(Rrtype::A), Rclass::IN); @@ -865,7 +1104,7 @@ mod resolver_cache_test{ } #[test] - fn remove_additional(){ + fn remove_additional() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -904,10 +1143,28 @@ mod resolver_cache_test{ resource_record_3.set_type_code(Rrtype::A); resource_record_3.set_ttl(1000); - resolver_cache.add_additional(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_additional(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_additional(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); - + resolver_cache.add_additional( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_additional( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_additional( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.remove_additional(domain_name.clone(), Some(Rrtype::A), Rclass::IN); let rr = resolver_cache.get_additional(domain_name.clone(), Rrtype::A, Rclass::IN); @@ -916,7 +1173,7 @@ mod resolver_cache_test{ } #[test] - fn remove(){ + fn remove() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -955,9 +1212,27 @@ mod resolver_cache_test{ resource_record_3.set_type_code(Rrtype::A); resource_record_3.set_ttl(1000); - resolver_cache.add_answer(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_authority(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.add_additional(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); + resolver_cache.add_answer( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_authority( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.add_additional( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); let qname = DomainName::new_from_string("www.example.com".to_string()); let qtype = Rrtype::A; @@ -965,8 +1240,15 @@ mod resolver_cache_test{ let op_code = 0; let rd = true; let id = 1; - - let query = DnsMessage::new_query_message(qname.clone(), qtype.clone(), qclass.clone(), op_code.clone(), rd.clone(), id.clone()); + + let query = DnsMessage::new_query_message( + qname.clone(), + qtype.clone(), + qclass.clone(), + op_code.clone(), + rd.clone(), + id.clone(), + ); resolver_cache.remove(domain_name.clone(), Some(Rrtype::A), Rclass::IN); @@ -976,7 +1258,7 @@ mod resolver_cache_test{ } #[test] - fn timeout(){ + fn timeout() { let mut resolver_cache = ResolverCache::new(None); let domain_name = DomainName::new_from_string("www.example.com".to_string()); @@ -1012,18 +1294,44 @@ mod resolver_cache_test{ resource_record_3.set_name(domain_name.clone()); resource_record_3.set_type_code(Rrtype::A); - resolver_cache.cache_answer.add(domain_name.clone(), resource_record_1.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.cache_authority.add(domain_name.clone(), resource_record_2.clone(), Some(Rrtype::A), Rclass::IN, None); - resolver_cache.cache_additional.add(domain_name.clone(), resource_record_3.clone(), Some(Rrtype::A), Rclass::IN, None); + resolver_cache.cache_answer.add( + domain_name.clone(), + resource_record_1.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.cache_authority.add( + domain_name.clone(), + resource_record_2.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); + resolver_cache.cache_additional.add( + domain_name.clone(), + resource_record_3.clone(), + Some(Rrtype::A), + Rclass::IN, + None, + ); resolver_cache.timeout(); - let rr_answer = resolver_cache.cache_answer.get(domain_name.clone(), Rrtype::A, Rclass::IN); - let rr_authority = resolver_cache.cache_authority.get(domain_name.clone(), Rrtype::A, Rclass::IN); - let rr_additional = resolver_cache.cache_additional.get(domain_name.clone(), Rrtype::A, Rclass::IN); + let rr_answer = resolver_cache + .cache_answer + .get(domain_name.clone(), Rrtype::A, Rclass::IN); + let rr_authority = + resolver_cache + .cache_authority + .get(domain_name.clone(), Rrtype::A, Rclass::IN); + let rr_additional = + resolver_cache + .cache_additional + .get(domain_name.clone(), Rrtype::A, Rclass::IN); assert_eq!(rr_answer, None); assert_eq!(rr_authority, None); assert_eq!(rr_additional, None); } -} \ No newline at end of file +} From 7ff273227c7f0155222219abbf7249e38103f32d Mon Sep 17 00:00:00 2001 From: Ephy Date: Thu, 25 Jul 2024 11:16:10 -0400 Subject: [PATCH 12/12] fix bug negative answers --- src/async_resolver.rs | 918 +++++++++++++++++++++++------------------- 1 file changed, 507 insertions(+), 411 deletions(-) diff --git a/src/async_resolver.rs b/src/async_resolver.rs index 3ea503cb..3a150a9f 100644 --- a/src/async_resolver.rs +++ b/src/async_resolver.rs @@ -1,26 +1,25 @@ pub mod config; pub mod lookup; -pub mod slist; -pub mod resolver_error; pub mod lookup_response; +pub mod resolver_error; pub mod server_info; +pub mod slist; -use std::net::IpAddr; -use std::sync::{Arc, Mutex}; +use self::lookup_response::LookupResponse; +use crate::async_resolver::resolver_error::ResolverError; +use crate::async_resolver::{config::ResolverConfig, lookup::LookupStrategy}; +use crate::client::client_connection::ConnectionProtocol; use crate::client::client_error::ClientError; -use crate::resolver_cache::ResolverCache; use crate::domain_name::DomainName; -use crate::message::rcode::Rcode; -use crate::message::{self, DnsMessage}; use crate::message::rclass::Rclass; -use crate::message::resource_record::ResourceRecord; -use crate::async_resolver::{config::ResolverConfig,lookup::LookupStrategy}; +use crate::message::rcode::Rcode; use crate::message::rdata::Rdata; -use crate::client::client_connection::ConnectionProtocol; -use crate::async_resolver::resolver_error::ResolverError; +use crate::message::resource_record::ResourceRecord; use crate::message::rrtype::Rrtype; -use self::lookup_response::LookupResponse; - +use crate::message::{self, DnsMessage}; +use crate::resolver_cache::ResolverCache; +use std::net::IpAddr; +use std::sync::{Arc, Mutex}; /// Asynchronous resolver for DNS queries. /// @@ -40,11 +39,10 @@ pub struct AsyncResolver { /// Cache for the resolver cache: Arc>, /// Configuration for the resolver. - config: ResolverConfig , + config: ResolverConfig, } impl AsyncResolver { - /// Creates a new `AsyncResolver` with the given configuration. /// /// # Example @@ -57,7 +55,7 @@ impl AsyncResolver { /// let resolver = AsyncResolver::new(config.clone()); /// assert_eq!(resolver.config, config); /// ``` - pub fn new(config: ResolverConfig)-> Self { + pub fn new(config: ResolverConfig) -> Self { let async_resolver = AsyncResolver { cache: Arc::new(Mutex::new(ResolverCache::new(None))), config: config, @@ -95,26 +93,25 @@ impl AsyncResolver { &mut self, domain_name: &str, transport_protocol: &str, - rclass: &str + rclass: &str, ) -> Result, ClientError> { let domain_name_struct = DomainName::new_from_string(domain_name.to_string()); let transport_protocol_struct = ConnectionProtocol::from(transport_protocol); self.config.set_protocol(transport_protocol_struct); - let response = self.inner_lookup( - domain_name_struct, - Rrtype::A, - rclass.into() - ).await; - - return self.check_error_from_msg(response).and_then(|lookup_response| { - let rrs_iter = lookup_response - .to_vec_of_rr() - .into_iter(); - let ip_addresses: Result, _> = rrs_iter.map(|rr| - {AsyncResolver::from_rr_to_ip(rr)}).collect(); - return ip_addresses; - }); + let response = self + .inner_lookup(domain_name_struct, Rrtype::A, rclass.into()) + .await; + + return self + .check_error_from_msg(response) + .and_then(|lookup_response| { + let rrs_iter = lookup_response.to_vec_of_rr().into_iter(); + let ip_addresses: Result, _> = rrs_iter + .map(|rr| AsyncResolver::from_rr_to_ip(rr)) + .collect(); + return ip_addresses; + }); } /// Performs a DNS lookup of the given domain name, qtype and rclass. @@ -124,7 +121,7 @@ impl AsyncResolver { /// asynchronously and returns the corresponding `Result`. /// The `LookupResponse` contains the response of the query which can be translated /// to different formats. - /// + /// /// If the response has an error, the method returns the corresponding `ClientError` /// to the Client. /// @@ -155,17 +152,19 @@ impl AsyncResolver { domain_name: &str, transport_protocol: &str, rrtype: &str, - rclass: &str + rclass: &str, ) -> Result { let domain_name_struct = DomainName::new_from_string(domain_name.to_string()); let transport_protocol_struct = ConnectionProtocol::from(transport_protocol); self.config.set_protocol(transport_protocol_struct); - let response = self.inner_lookup( - domain_name_struct, - Rrtype::from(rrtype), - Rclass::from(rclass) - ).await; + let response = self + .inner_lookup( + domain_name_struct, + Rrtype::from(rrtype), + Rclass::from(rclass), + ) + .await; return self.check_error_from_msg(response); } @@ -176,23 +175,25 @@ impl AsyncResolver { if let Rdata::A(ip) = rdata { return Ok(ip.get_address()); } else { - Err(ClientError::TemporaryError("Response does not match type A."))? + Err(ClientError::TemporaryError( + "Response does not match type A.", + ))? } } /// Host name to address translation. /// - /// Performs a DNS lookup for the given domain name and returns the corresponding + /// Performs a DNS lookup for the given domain name and returns the corresponding /// `Result`. Here, the `LookupResponse` contains the /// response of the query which can translate the response to different formats. - /// - /// This lookup is done asynchronously using the `tokio` runtime. It calls the + /// + /// This lookup is done asynchronously using the `tokio` runtime. It calls the /// asynchronous method `run()` of the `LookupStrategy` struct. This method /// is used to perform the DNS lookup and return the response of the query. - /// + /// /// If the response has an error, the method returns the corresponding `ResolverError` /// to the Client. - /// + /// /// # Examples /// /// ``` @@ -209,7 +210,7 @@ impl AsyncResolver { &self, domain_name: DomainName, rrtype: Rrtype, - rclass: Rclass + rclass: Rclass, ) -> Result { let mut query = message::create_recursive_query(domain_name.clone(), rrtype, rclass); @@ -225,14 +226,13 @@ impl AsyncResolver { let lock_result = self.cache.lock(); let cache = match lock_result { Ok(val) => val, - Err(_) => Err(ClientError::Message("Error getting cache"))?, // FIXME: it shouldn't - // return the error, it should go to the next part of the code + Err(_) => Err(ClientError::Message("Error getting cache"))?, // FIXME: it shouldn't + // return the error, it should go to the next part of the code }; if let Some(cache_lookup) = cache.clone().get(query.clone()) { - let new_lookup_response = LookupResponse::new(cache_lookup.clone()); - return Ok(new_lookup_response) + return Ok(new_lookup_response); } } @@ -244,7 +244,7 @@ impl AsyncResolver { if let Ok(ref r) = lookup_response { self.store_data_cache(r.to_dns_msg().clone()); } - + return lookup_response; } @@ -315,12 +315,11 @@ impl AsyncResolver { let truncated = response.get_header().get_tc(); let rcode = response.get_header().get_rcode(); { - let mut cache = self.cache.lock().unwrap(); - cache.timeout(); - if !truncated { - cache.add(response.clone()); - } - self.save_negative_answers(response); + let mut cache = self.cache.lock().unwrap(); + cache.timeout(); + if !truncated { + cache.add(response.clone()); + } } } @@ -354,7 +353,8 @@ impl AsyncResolver { /// the answer section, or name error if applicable. The MINIMUM field of /// the SOA controls the length of time that the negative result may be /// cached. - fn save_negative_answers(&self, response: DnsMessage){ + #[allow(unused)] + fn save_negative_answers(&self, response: DnsMessage) { let qname = response.get_question().get_qname(); let qtype = response.get_question().get_rrtype(); let qclass = response.get_question().get_rclass(); @@ -365,14 +365,19 @@ impl AsyncResolver { // If not existence RR for query, add SOA to cache let mut cache = self.cache.lock().unwrap(); // FIXME: que la función entregue result - if additionals.len() > 0 && answer.len() == 0 && aa == true{ + if additionals.len() > 0 && answer.len() == 0 && aa == true { for additional in additionals { if additional.get_rtype() == Rrtype::SOA { - cache.add_additional(qname.clone(), additional, Some(qtype), qclass, Some(rcode)); + cache.add_additional( + qname.clone(), + additional, + Some(qtype), + qclass, + Some(rcode), + ); } } } - } /// Checks the received `LookupResponse` for errors to return to the Client. @@ -380,15 +385,15 @@ impl AsyncResolver { /// After receiving the response of the query, this method checks if the /// corresponding `DnsMessage` contained in the `LookupResponse` has any /// error. This error could be specified in the RCODE of the DNS message or it - /// could be any other temporary error. If the response has an error, the method + /// could be any other temporary error. If the response has an error, the method /// returns the corresponding`ClientError` to the Client. fn check_error_from_msg( - &self, - response: Result + &self, + response: Result, ) -> Result { let lookup_response = match response { Ok(val) => val, - Err(_) => Err(ClientError::TemporaryError("no DNS message found"))?, + Err(_) => Err(ClientError::TemporaryError("no DNS message found"))?, }; let header = lookup_response.to_dns_msg().get_header(); @@ -424,34 +429,33 @@ impl AsyncResolver { #[cfg(test)] mod async_resolver_test { - use tokio::io; + use super::lookup_response::LookupResponse; + use super::AsyncResolver; + use crate::async_resolver::config::ResolverConfig; + use crate::async_resolver::resolver_error::ResolverError; use crate::async_resolver::server_info::ServerInfo; use crate::client::client_connection::ClientConnection; use crate::client::client_error::ClientError; use crate::client::tcp_connection::ClientTCPConnection; use crate::client::udp_connection::ClientUDPConnection; use crate::dns_cache::CacheKey; - use crate::message::DnsMessage; + use crate::domain_name::DomainName; use crate::message::rclass::Rclass; - use crate::message::rrtype::Rrtype; - use crate::message::rdata::Rdata; + use crate::message::rcode::Rcode; use crate::message::rdata::a_rdata::ARdata; use crate::message::rdata::soa_rdata::SoaRdata; + use crate::message::rdata::Rdata; use crate::message::resource_record::ResourceRecord; - use crate::message::rcode::Rcode; - use crate::async_resolver::config::ResolverConfig; - use super::lookup_response::LookupResponse; - use super::AsyncResolver; + use crate::message::rrtype::Rrtype; + use crate::message::DnsMessage; use std::net::{IpAddr, Ipv4Addr}; use std::str::FromStr; use std::time::Duration; use std::vec; - use crate::domain_name::DomainName; - use crate::async_resolver::resolver_error::ResolverError; + use tokio::io; static TIMEOUT: u64 = 45; - use std::sync::Arc; use std::num::NonZeroUsize; - + use std::sync::Arc; #[test] fn create_async_resolver() { @@ -468,7 +472,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::A; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -483,7 +489,6 @@ mod async_resolver_test { } } - #[tokio::test] async fn inner_lookup_rrtype_ns() { // Create a new resolver with default values @@ -491,7 +496,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::NS; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -513,7 +520,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::MX; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -535,7 +544,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::PTR; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -557,7 +568,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::SOA; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -579,7 +592,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::TXT; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -601,7 +616,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::CNAME; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -623,7 +640,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::HINFO; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -645,7 +664,9 @@ mod async_resolver_test { let domain_name = DomainName::new_from_string("example.com".to_string()); let rrtype = Rrtype::TSIG; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; let response = match response { Ok(val) => val, @@ -667,11 +688,13 @@ mod async_resolver_test { let rrtype = Rrtype::NS; let record_class = Rclass::IN; - let response = resolver.inner_lookup(domain_name,rrtype,record_class).await; + let response = resolver + .inner_lookup(domain_name, rrtype, record_class) + .await; assert!(response.is_ok()); //FIXME: add assert - println!("Response: {:?}",response); + println!("Response: {:?}", response); } #[tokio::test] @@ -680,7 +703,10 @@ mod async_resolver_test { let domain_name = "example.com"; let transport_protocol = "TCP"; let rclass = "IN"; - let ip_addresses = resolver.lookup_ip(domain_name, transport_protocol,rclass).await.unwrap(); + let ip_addresses = resolver + .lookup_ip(domain_name, transport_protocol, rclass) + .await + .unwrap(); println!("RESPONSE : {:?}", ip_addresses); assert!(ip_addresses[0].is_ipv4()); @@ -693,7 +719,9 @@ mod async_resolver_test { let domain_name = "example.com"; let transport_protocol = "UDP"; let rclass = "CH"; - let ip_addresses = resolver.lookup_ip(domain_name, transport_protocol,rclass).await; + let ip_addresses = resolver + .lookup_ip(domain_name, transport_protocol, rclass) + .await; println!("RESPONSE : {:?}", ip_addresses); assert!(ip_addresses.is_err()); @@ -705,7 +733,9 @@ mod async_resolver_test { let domain_name = "example.com"; let transport_protocol = "UDP"; let rclass = "ANY"; - let ip_addresses = resolver.lookup_ip(domain_name, transport_protocol,rclass).await; + let ip_addresses = resolver + .lookup_ip(domain_name, transport_protocol, rclass) + .await; println!("RESPONSE : {:?}", ip_addresses); assert!(ip_addresses.is_err()); @@ -718,7 +748,9 @@ mod async_resolver_test { let transport_protocol = "UDP"; let rrtype = "NS"; let rclass = "CH"; - let ip_addresses = resolver.lookup(domain_name, transport_protocol,rrtype,rclass).await; + let ip_addresses = resolver + .lookup(domain_name, transport_protocol, rrtype, rclass) + .await; println!("RESPONSE : {:?}", ip_addresses); assert!(ip_addresses.is_err()); @@ -730,7 +762,10 @@ mod async_resolver_test { let domain_name = "example.com"; let transport_protocol = "TCP"; let rclass = "IN"; - let ip_addresses = resolver.lookup_ip(domain_name, transport_protocol,rclass).await.unwrap(); + let ip_addresses = resolver + .lookup_ip(domain_name, transport_protocol, rclass) + .await + .unwrap(); println!("RESPONSE : {:?}", ip_addresses); assert!(ip_addresses[0].is_ipv4()); @@ -743,14 +778,14 @@ mod async_resolver_test { resolver.config.set_retransmission_loop_attempts(10); let domain_name = "example.com"; let transport_protocol = "UDP"; - match resolver.lookup( - domain_name, - transport_protocol, - "NS", - "IN" - ).await { - Ok(val) => {println!("RESPONSE : {:?}",val);}, - Err(e) => assert!(false, "Error: {:?}", e) + match resolver + .lookup(domain_name, transport_protocol, "NS", "IN") + .await + { + Ok(val) => { + println!("RESPONSE : {:?}", val); + } + Err(e) => assert!(false, "Error: {:?}", e), }; } @@ -782,8 +817,11 @@ mod async_resolver_test { let timeout_duration = std::time::Duration::from_secs(2); let result = tokio::time::timeout(timeout_duration, async { - resolver.lookup_ip(domain_name, transport_protocol,rclass).await - }).await; + resolver + .lookup_ip(domain_name, transport_protocol, rclass) + .await + }) + .await; // Verifica que el resultado sea un error de timeout match result { @@ -791,7 +829,7 @@ mod async_resolver_test { panic!("Se esperaba un error de timeout, pero se resolvió exitosamente"); } Ok(Err(_err)) => { - assert!(true); + assert!(true); } Err(_) => { panic!("El timeout no se manejó correctamente"); @@ -811,14 +849,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::A, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -842,16 +880,28 @@ mod async_resolver_test { #[tokio::test] async fn inner_lookup_cache_available() { let resolver = AsyncResolver::new(ResolverConfig::default()); - resolver.cache.lock().unwrap().set_max_size(NonZeroUsize::new(1).unwrap()); + resolver + .cache + .lock() + .unwrap() + .set_max_size(NonZeroUsize::new(1).unwrap()); let domain_name = DomainName::new_from_string("example.com".to_string()); let a_rdata = ARdata::new_from_addr(IpAddr::from_str("93.184.216.34").unwrap()); let a_rdata = Rdata::A(a_rdata); let resource_record = ResourceRecord::new(a_rdata); - resolver.cache.lock().unwrap().add_answer(domain_name, resource_record, Some(Rrtype::A), Rclass::IN, None); + resolver.cache.lock().unwrap().add_answer( + domain_name, + resource_record, + Some(Rrtype::A), + Rclass::IN, + None, + ); let domain_name = DomainName::new_from_string("example.com".to_string()); - let response = resolver.inner_lookup(domain_name, Rrtype::A, Rclass::IN).await; + let response = resolver + .inner_lookup(domain_name, Rrtype::A, Rclass::IN) + .await; if let Ok(msg) = response { assert_eq!(msg.to_dns_msg().get_header().get_aa(), false); @@ -868,18 +918,26 @@ mod async_resolver_test { let resolver = AsyncResolver::new(config); { - let mut cache = resolver.cache.lock().unwrap(); - cache.set_max_size(NonZeroUsize::new(1).unwrap()); - - let domain_name = DomainName::new_from_string("example.com".to_string()); - let a_rdata = ARdata::new_from_addr(IpAddr::from_str("93.184.216.34").unwrap()); - let a_rdata = Rdata::A(a_rdata); - let resource_record = ResourceRecord::new(a_rdata); - cache.add_answer(domain_name, resource_record, Some(Rrtype::A), Rclass::IN, None); + let mut cache = resolver.cache.lock().unwrap(); + cache.set_max_size(NonZeroUsize::new(1).unwrap()); + + let domain_name = DomainName::new_from_string("example.com".to_string()); + let a_rdata = ARdata::new_from_addr(IpAddr::from_str("93.184.216.34").unwrap()); + let a_rdata = Rdata::A(a_rdata); + let resource_record = ResourceRecord::new(a_rdata); + cache.add_answer( + domain_name, + resource_record, + Some(Rrtype::A), + Rclass::IN, + None, + ); } let domain_name = DomainName::new_from_string("example.com".to_string()); - let response = resolver.inner_lookup(domain_name, Rrtype::A, Rclass::IN).await; + let response = resolver + .inner_lookup(domain_name, Rrtype::A, Rclass::IN) + .await; if let Ok(msg) = response { assert_eq!(msg.to_dns_msg().get_header().get_aa(), false); @@ -892,36 +950,46 @@ mod async_resolver_test { #[tokio::test] async fn cache_data() { let mut resolver = AsyncResolver::new(ResolverConfig::default()); - resolver.cache.lock().unwrap().set_max_size(NonZeroUsize::new(1).unwrap()); + resolver + .cache + .lock() + .unwrap() + .set_max_size(NonZeroUsize::new(1).unwrap()); assert_eq!(resolver.cache.lock().unwrap().is_empty(), true); - let _response = resolver.lookup("example.com", "UDP", "A","IN").await; - assert_eq!(resolver.cache.lock().unwrap().is_cached(CacheKey::Primary(Rrtype::A, Rclass::IN, DomainName::new_from_str("example.com"))), true); + let _response = resolver.lookup("example.com", "UDP", "A", "IN").await; + assert_eq!( + resolver.cache.lock().unwrap().is_cached(CacheKey::Primary( + Rrtype::A, + Rclass::IN, + DomainName::new_from_str("example.com") + )), + true + ); // TODO: Test special cases from RFC } - #[tokio::test] async fn max_number_of_retry() { let mut config = ResolverConfig::default(); let max_retries = 6; config.set_retransmission_loop_attempts(max_retries); - let bad_server:IpAddr = IpAddr::V4(Ipv4Addr::new(7, 7, 7, 7)); + let bad_server: IpAddr = IpAddr::V4(Ipv4Addr::new(7, 7, 7, 7)); let timeout = Duration::from_secs(2); - - let conn_udp:ClientUDPConnection = ClientUDPConnection::new(bad_server, timeout); - let conn_tcp:ClientTCPConnection = ClientTCPConnection::new(bad_server, timeout); + + let conn_udp: ClientUDPConnection = ClientUDPConnection::new(bad_server, timeout); + let conn_tcp: ClientTCPConnection = ClientTCPConnection::new(bad_server, timeout); let server_info = ServerInfo::new_with_ip(bad_server, conn_udp, conn_tcp); let name_servers = vec![server_info]; config.set_name_servers(name_servers); let mut resolver = AsyncResolver::new(config); let result = resolver.lookup("dfasdfsda.com", "TCP", "A", "IN").await; - + match result { Ok(_) => { - panic!("Timeout limit exceeded error was expected."); + panic!("Timeout limit exceeded error was expected."); } Err(_) => { assert!(true); @@ -929,14 +997,16 @@ mod async_resolver_test { } } - #[tokio::test] async fn use_udp() { let mut resolver = AsyncResolver::new(ResolverConfig::default()); let domain_name = "example.com"; let transport_protocol = "UDP"; let rclass = "IN"; - let ip_addresses = resolver.lookup_ip(domain_name, transport_protocol,rclass).await.unwrap(); + let ip_addresses = resolver + .lookup_ip(domain_name, transport_protocol, rclass) + .await + .unwrap(); println!("RESPONSE : {:?}", ip_addresses); assert!(ip_addresses[0].is_ipv4()); @@ -949,7 +1019,10 @@ mod async_resolver_test { let domain_name = "example.com"; let transport_protocol = "TCP"; let rclass = "IN"; - let ip_addresses = resolver.lookup_ip(domain_name, transport_protocol,rclass).await.unwrap(); + let ip_addresses = resolver + .lookup_ip(domain_name, transport_protocol, rclass) + .await + .unwrap(); println!("RESPONSE : {:?}", ip_addresses); assert!(ip_addresses[0].is_ipv4()); @@ -964,29 +1037,32 @@ mod async_resolver_test { let transport_protocol_udp = "UDP"; let transport_protocol_tcp = "TCP"; let rclass = "IN"; - let udp_result = resolver.lookup_ip(domain_name, transport_protocol_udp,rclass).await; + let udp_result = resolver + .lookup_ip(domain_name, transport_protocol_udp, rclass) + .await; match udp_result { - Ok(_) => { - panic!("UDP client error expected"); + Ok(_) => { + panic!("UDP client error expected"); } - Err(_err) => { - assert!(true); + Err(_err) => { + assert!(true); } } - let tcp_result = resolver.lookup_ip(domain_name, transport_protocol_tcp, rclass).await; + let tcp_result = resolver + .lookup_ip(domain_name, transport_protocol_tcp, rclass) + .await; match tcp_result { Ok(_) => { assert!(true); } - Err(_err) => { - panic!("unexpected TCP client error"); + Err(_err) => { + panic!("unexpected TCP client error"); } } } - //TODO: diferent types of errors #[tokio::test] async fn resolver_with_client_error_io() { @@ -994,12 +1070,12 @@ mod async_resolver_test { let result = ClientError::Io(io_error); match result { - ClientError::Io(_) => { - // La operación generó un error de I/O simulado, la prueba es exitosa - } - _ => { - panic!("Se esperaba un error de I/O simulado"); - } + ClientError::Io(_) => { + // La operación generó un error de I/O simulado, la prueba es exitosa + } + _ => { + panic!("Se esperaba un error de I/O simulado"); + } } } @@ -1015,14 +1091,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::A, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1039,10 +1115,12 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - if let Err(ClientError::FormatError("The name server was unable to interpret the query.")) = result_lookup { + if let Err(ClientError::FormatError( + "The name server was unable to interpret the query.", + )) = result_lookup + { assert!(true); - } - else { + } else { panic!("Error parsing response"); } } @@ -1060,14 +1138,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::A, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1106,14 +1184,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::A, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1130,10 +1208,12 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - if let Err(ClientError::NameError("The domain name referenced in the query does not exist.")) = result_lookup { + if let Err(ClientError::NameError( + "The domain name referenced in the query does not exist.", + )) = result_lookup + { assert!(true); - } - else { + } else { panic!("Error parsing response"); } } @@ -1151,14 +1231,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::A, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1175,10 +1255,12 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - if let Err(ClientError::NotImplemented("The name server does not support the requested kind of query.")) = result_lookup { + if let Err(ClientError::NotImplemented( + "The name server does not support the requested kind of query.", + )) = result_lookup + { assert!(true); - } - else { + } else { panic!("Error parsing response"); } } @@ -1196,14 +1278,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::A, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1220,10 +1302,12 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - if let Err(ClientError::Refused("The name server refuses to perform the specified operation for policy reasons.")) = result_lookup { + if let Err(ClientError::Refused( + "The name server refuses to perform the specified operation for policy reasons.", + )) = result_lookup + { assert!(true); - } - else { + } else { panic!("Error parsing response"); } } @@ -1242,14 +1326,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::A, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1265,9 +1349,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1282,14 +1365,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::NS, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::NS, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1305,9 +1388,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1322,14 +1404,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::CNAME, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::CNAME, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1345,9 +1427,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1362,14 +1443,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::SOA, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::SOA, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1385,12 +1466,10 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } - #[tokio::test] async fn rrtypes_ptr() { let resolver = AsyncResolver::new(ResolverConfig::default()); @@ -1403,14 +1482,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::PTR, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::PTR, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1426,9 +1505,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1443,14 +1521,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::HINFO, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::HINFO, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1466,9 +1544,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1483,19 +1560,19 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::MINFO, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::MINFO, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); dns_response.set_header(header); - let lookup_response = LookupResponse::new(dns_response); + let lookup_response = LookupResponse::new(dns_response); let result_vec_rr = resolver.check_error_from_msg(Ok(lookup_response)); if let Ok(lookup_response) = result_vec_rr { @@ -1506,9 +1583,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1523,14 +1599,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::WKS, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::WKS, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1546,9 +1622,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1563,14 +1638,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::TXT, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::TXT, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1586,9 +1661,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1603,14 +1677,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::DNAME, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::DNAME, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1626,9 +1700,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1643,14 +1716,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::ANY, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::ANY, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1666,9 +1739,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1683,14 +1755,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::TSIG, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::TSIG, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1706,9 +1778,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1723,14 +1794,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::AXFR, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::AXFR, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1746,9 +1817,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1763,19 +1833,19 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::MAILB, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::MAILB, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); dns_response.set_header(header); - let lookup_response = LookupResponse::new(dns_response); + let lookup_response = LookupResponse::new(dns_response); let result_vec_rr = resolver.check_error_from_msg(Ok(lookup_response)); if let Ok(lookup_response) = result_vec_rr { @@ -1786,9 +1856,8 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[tokio::test] @@ -1803,14 +1872,14 @@ mod async_resolver_test { let resource_record = ResourceRecord::new(rdata); answer.push(resource_record); - let mut dns_response = - DnsMessage::new_query_message( - DomainName::new_from_string("example.com".to_string()), - Rrtype::MAILA, - Rclass::IN, - 0, - false, - 1); + let mut dns_response = DnsMessage::new_query_message( + DomainName::new_from_string("example.com".to_string()), + Rrtype::MAILA, + Rclass::IN, + 0, + false, + 1, + ); dns_response.set_answer(answer); let mut header = dns_response.get_header(); header.set_qr(true); @@ -1826,54 +1895,57 @@ mod async_resolver_test { panic!("Error parsing response"); } } else { - - panic!("Error parsing response"); - } + panic!("Error parsing response"); + } } #[test] fn not_store_data_in_cache_if_truncated() { let resolver = AsyncResolver::new(ResolverConfig::default()); - resolver.cache.lock().unwrap().set_max_size(NonZeroUsize::new(10).unwrap()); - + resolver + .cache + .lock() + .unwrap() + .set_max_size(NonZeroUsize::new(10).unwrap()); let domain_name = DomainName::new_from_string("example.com".to_string()); // Create truncated dns response let mut dns_response = - DnsMessage::new_query_message( - domain_name, - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + DnsMessage::new_query_message(domain_name, Rrtype::A, Rclass::IN, 0, false, 1); let mut truncated_header = dns_response.get_header(); truncated_header.set_tc(true); dns_response.set_header(truncated_header); resolver.store_data_cache(dns_response); - - assert_eq!(resolver.cache.lock().unwrap().get_cache_answer().get_cache().len(), 0); + + assert_eq!( + resolver + .cache + .lock() + .unwrap() + .get_cache_answer() + .get_cache() + .len(), + 0 + ); } #[test] fn not_store_cero_ttl_data_in_cache() { let resolver = AsyncResolver::new(ResolverConfig::default()); - resolver.cache.lock().unwrap().set_max_size(NonZeroUsize::new(10).unwrap()); + resolver + .cache + .lock() + .unwrap() + .set_max_size(NonZeroUsize::new(10).unwrap()); let domain_name = DomainName::new_from_string("example.com".to_string()); // Create dns response with ttl = 0 let mut dns_response = - DnsMessage::new_query_message( - domain_name, - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + DnsMessage::new_query_message(domain_name, Rrtype::A, Rclass::IN, 0, false, 1); // let mut truncated_header = dns_response.get_header(); // truncated_header.set_tc(false); // dns_response.set_header(truncated_header); @@ -1897,16 +1969,38 @@ mod async_resolver_test { dns_response.set_answer(answer); assert_eq!(dns_response.get_answer().len(), 3); - assert_eq!(resolver.cache.lock().unwrap().get_cache_answer().get_cache().len(), 0); + assert_eq!( + resolver + .cache + .lock() + .unwrap() + .get_cache_answer() + .get_cache() + .len(), + 0 + ); resolver.store_data_cache(dns_response); - assert_eq!(resolver.cache.lock().unwrap().get_cache_answer().get_cache().len(), 2); + assert_eq!( + resolver + .cache + .lock() + .unwrap() + .get_cache_answer() + .get_cache() + .len(), + 2 + ); } #[test] - fn save_cache_negative_answer(){ + fn save_cache_negative_answer() { let resolver = AsyncResolver::new(ResolverConfig::default()); - resolver.cache.lock().unwrap().set_max_size(NonZeroUsize::new(1).unwrap()); + resolver + .cache + .lock() + .unwrap() + .set_max_size(NonZeroUsize::new(1).unwrap()); let domain_name = DomainName::new_from_string("banana.exaple".to_string()); let mname = DomainName::new_from_string("a.root-servers.net.".to_string()); @@ -1927,20 +2021,13 @@ mod async_resolver_test { soa_rdata.set_expire(expire); soa_rdata.set_minimum(minimum); - let rdata = Rdata::SOA(soa_rdata); let mut rr = ResourceRecord::new(rdata); rr.set_name(domain_name.clone()); // Create dns response let mut dns_response = - DnsMessage::new_query_message( - domain_name, - Rrtype::A, - Rclass::IN, - 0, - false, - 1); + DnsMessage::new_query_message(domain_name, Rrtype::A, Rclass::IN, 0, false, 1); let mut new_header = dns_response.get_header(); new_header.set_aa(true); dns_response.set_header(new_header); @@ -1953,12 +2040,20 @@ mod async_resolver_test { let rrtype_search = Rrtype::A; assert_eq!(dns_response.get_answer().len(), 0); assert_eq!(dns_response.get_additional().len(), 1); - assert_eq!(resolver.cache.lock().unwrap().get_cache_answer().get_cache().len(), 1); + assert_eq!( + resolver + .cache + .lock() + .unwrap() + .get_cache_answer() + .get_cache() + .len(), + 1 + ); // assert!(resolver.cache.lock().unwrap().get_cache_answer().get(dns_response.get_question().get_qname().clone(), qtype_search, Qclass::IN).is_some()) - } - /* #[ignore = "Optional, not implemented"] + /* #[ignore = "Optional, not implemented"] #[tokio::test] async fn inner_lookup_negative_answer_in_cache(){ let resolver = AsyncResolver::new(ResolverConfig::default()); @@ -2016,7 +2111,7 @@ mod async_resolver_test { // TODO: Finish tests, it shoudl verify that we can send several asynchroneous queries concurrently #[tokio::test] - async fn test3(){ + async fn test3() { let resolver = Arc::new(AsyncResolver::new(ResolverConfig::default())); let rrtype = Rrtype::A; let rclass = Rclass::IN; @@ -2025,11 +2120,12 @@ mod async_resolver_test { let resolver_1 = resolver.clone(); let resolver_2 = resolver.clone(); - let _result: (Result, Result) = tokio::join!( + let _result: ( + Result, + Result, + ) = tokio::join!( resolver_1.inner_lookup(domain_name.clone(), rrtype.clone(), rclass.clone()), resolver_2.inner_lookup(domain_name.clone(), rrtype.clone(), rclass.clone()) ); } - - -} \ No newline at end of file +}