Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 29 additions & 37 deletions src/clients/json.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::bail;
use crate::clients::mime::content_type_equal;
use crate::clients::stats::StatsBuilder;
use crate::clients::AsyncExchanger;
use crate::clients::ToUrls;
use crate::errors::ParseError;
Expand All @@ -9,7 +10,6 @@ use crate::Message;
use crate::Question;
use crate::Record;
use crate::Resource;
use crate::clients::stats::StatsBuilder;
use async_trait::async_trait;
use core::convert::TryInto;
use http::header::*;
Expand Down Expand Up @@ -42,19 +42,19 @@ struct MessageJson {
pub status: u32, // NOERROR - Standard DNS response code (32 bit integer).

#[serde(rename = "TC")]
pub tc: bool, // Whether the response is truncated
pub tc: bool, // Whether the response is truncated

#[serde(rename = "RD")]
pub rd: bool, // Always true for Google Public DNS
pub rd: bool, // Always true for Google Public DNS

#[serde(rename = "RA")]
pub ra: bool, // Always true for Google Public DNS
pub ra: bool, // Always true for Google Public DNS

#[serde(rename = "AD")]
pub ad: bool, // Whether all response data was validated with DNSSEC
pub ad: bool, // Whether all response data was validated with DNSSEC

#[serde(rename = "CD")]
pub cd: bool, // Whether the client asked to disable DNSSEC
pub cd: bool, // Whether the client asked to disable DNSSEC

pub question: Vec<QuestionJson>,

Expand Down Expand Up @@ -142,8 +142,8 @@ impl TryInto<Record> for RecordJson {
let r#type =
FromPrimitive::from_u16(self.r#type).ok_or(ParseError::InvalidType(self.r#type))?;

let resource =
Resource::from_str(r#type, &self.data).map_err(|x| ParseError::InvalidResource(r#type, x))?;
let resource = Resource::from_str(r#type, &self.data)
.map_err(|x| ParseError::InvalidResource(r#type, x))?;

Ok(Record {
name: self.name, // TODO Do I need to remove the trailing dot?
Expand Down Expand Up @@ -181,18 +181,11 @@ impl TryInto<Record> for RecordJson {
/// See <https://developers.google.com/speed/public-dns/docs/doh/json> and
/// <https://developers.cloudflare.com/1.1.1.1/encrypted-dns/dns-over-https/make-api-requests/dns-json>
// TODO Document all the options.
#[derive(Default)]
pub struct Client {
servers: Vec<Url>,
}

impl Default for Client {
fn default() -> Self {
Client {
servers: Vec::default(),
}
}
}

impl Client {
/// Creates a new Client bound to the specific servers.
///
Expand Down Expand Up @@ -290,7 +283,7 @@ impl AsyncExchanger for Client {
// Read the full body
let body = hyper::body::to_bytes(resp.into_body()).await?;

println!("{:?}", body);
println!("{body:?}");

let m: MessageJson = serde_json::from_slice(&body).map_err(ParseError::JsonError)?;
let mut m: Message = m.try_into()?;
Expand All @@ -308,19 +301,19 @@ impl AsyncExchanger for Client {
}
}


#[cfg(test)]
mod tests {
use std::io::Read;
use std::convert::TryInto;
use crate::clients::json::MessageJson;
use json_comments::StripComments;
use crate::Message;
use json_comments::StripComments;
use std::convert::TryInto;
use std::io::Read;

#[test]
fn test_parse_response() {
// From https://developers.google.com/speed/public-dns/docs/doh/json
let tests = [r#"{
let tests = [
r#"{
"Status": 0, // NOERROR - Standard DNS response code (32 bit integer).
"TC": false, // Whether the response is truncated
"RD": true, // Always true for Google Public DNS
Expand Down Expand Up @@ -356,9 +349,8 @@ mod tests {
}
],
"edns_client_subnet": "12.34.56.78/0" // IP address / scope prefix-length
}"#
,
r#"
}"#,
r#"
{
"Status": 2, // SERVFAIL - Standard DNS response code (32 bit integer).
"TC": false, // Whether the response is truncated
Expand All @@ -375,9 +367,8 @@ mod tests {
],
"Comment": "DNSSEC validation failure. Please check http://dnsviz.net/d/dnssec-failed.org/dnssec/."
}
"#
,
r#"
"#,
r#"
{
"Status": 0, // NOERROR - Standard DNS response code (32 bit integer).
"TC": false, // Whether the response is truncated
Expand All @@ -401,9 +392,8 @@ mod tests {
],
"Comment": "Response from 216.239.38.110"
// Uncached responses are attributed to the authoritative name server
}"#
,
r#"{
}"#,
r#"{
"Status": 0, // NOERROR - Standard DNS response code (32 bit integer).
"TC": false, // Whether the response is truncated
"RD": true, // Always true for Google Public DNS
Expand All @@ -426,9 +416,8 @@ mod tests {
}
]
}"#,

// From https://developers.cloudflare.com/1.1.1.1/encrypted-dns/dns-over-https/make-api-requests/dns-json
r#"{
// From https://developers.cloudflare.com/1.1.1.1/encrypted-dns/dns-over-https/make-api-requests/dns-json
r#"{
"Status": 0,
"TC": false,
"RD": true,
Expand All @@ -449,7 +438,8 @@ mod tests {
"data": "2606:2800:220:1:248:1893:25c8:1946"
}
]
}"#];
}"#,
];

for test in tests {
// Strip comments in the test, as a easy way to keep this test data annotated.
Expand All @@ -462,8 +452,10 @@ mod tests {
Ok(m) => m,
Err(err) => panic!("failed to parse JSON: {}\n{}", err, stripped),
};
let _m: Message = m.try_into().expect("failed to turn MessageJson into a Message");
let _m: Message = m
.try_into()
.expect("failed to turn MessageJson into a Message");
// TODO Check this is what we expect
}
}
}
}
9 changes: 5 additions & 4 deletions src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
//! in `dig` style.
// Refer to https://github.com/tigeli/bind-utils/blob/master/bin/dig/dig.c for reference.

use crate::resource::TXT;
use crate::resource::MX;
use crate::resource::SOA;
use crate::resource::SRV;
use crate::resource::TXT;
use crate::Message;
use crate::Question;
use crate::Record;
Expand Down Expand Up @@ -237,7 +237,8 @@ impl fmt::Display for SRV {

impl fmt::Display for TXT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let output = self.0
let output = self
.0
.iter()
.map(|txt| {
match std::str::from_utf8(txt) {
Expand All @@ -252,17 +253,17 @@ impl fmt::Display for TXT {
.collect::<Vec<String>>()
.join(" ");

write!(f, "{}", output)
write!(f, "{output}")
}
}

#[cfg(test)]
mod tests {
use crate::TXT;
use crate::Resource;
use crate::MX;
use crate::SOA;
use crate::SRV;
use crate::TXT;
use core::time::Duration;
use pretty_assertions::assert_eq;

Expand Down
6 changes: 3 additions & 3 deletions src/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,14 @@ impl Message {
pub fn to_vec(&self) -> io::Result<Vec<u8>> {
let mut req = Vec::<u8>::with_capacity(512);

req.extend_from_slice(&(self.id as u16).to_be_bytes());
req.extend_from_slice(&(self.id).to_be_bytes());

let mut b = 0_u8;
b |= if self.qr.to_bool() { 0b1000_0000 } else { 0 };
b |= ((self.opcode as u8) << 3) & 0b0111_1000;
b |= if self.aa { 0b0000_0100 } else { 0 };
b |= if self.tc { 0b0000_0010 } else { 0 };
b |= if self.rd { 0b0000_0001 } else { 0 };
b |= u8::from(self.rd);
req.push(b);

let mut b = 0_u8;
Expand Down Expand Up @@ -349,7 +349,7 @@ impl Extension {
pub fn write(&self, buf: &mut Vec<u8>) -> io::Result<()> {
buf.push(0); // A single "." domain name // 0-1
buf.extend_from_slice(&(Type::OPT as u16).to_be_bytes()); // 1-3
buf.extend_from_slice(&(self.payload_size as u16).to_be_bytes()); // 3-5
buf.extend_from_slice(&(self.payload_size).to_be_bytes()); // 3-5

buf.push(self.extend_rcode); // 5-6
buf.push(self.version); // 6-7
Expand Down
2 changes: 1 addition & 1 deletion src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub trait SeekExt: io::Seek {
impl<'a> SeekExt for Cursor<&'a [u8]> {
fn remaining(self: &mut std::io::Cursor<&'a [u8]>) -> io::Result<u64> {
let pos = self.position() as usize;
let len = self.get_ref().len() as usize;
let len = self.get_ref().len();

Ok((len - pos).try_into().unwrap())
}
Expand Down