1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
extern crate base64;
extern crate byteorder;
mod dnscrypt;
mod doh;
pub use self::dnscrypt::*;
pub use self::doh::*;
use std::io::{self, Write};
#[derive(Copy, Clone, Debug)]
pub enum Protocol {
Plain = 0x00,
DNSCrypt = 0x01,
DoH = 0x02,
DoT = 0x03,
}
pub enum InformalProperty {
DNSSEC,
NoLogs,
NoFilters,
}
impl From<InformalProperty> for u64 {
fn from(informal_property: InformalProperty) -> u64 {
match informal_property {
InformalProperty::DNSSEC => 0x01,
InformalProperty::NoLogs => 0x02,
InformalProperty::NoFilters => 0x04,
}
}
}
pub trait WithInformalProperty {
fn with_informal_property(self, informal_property: InformalProperty) -> Self;
}
fn lp_encode<W: Write>(writer: &mut W, string: &[u8]) -> io::Result<()> {
let mut encoded = vec![];
let len = string.len();
assert!(len <= 0xff);
encoded.push(len as u8);
encoded.extend(&string[..]);
writer.write_all(&encoded)
}
fn vlp_encode<W: Write>(writer: &mut W, strings: &[Vec<u8>]) -> io::Result<()> {
if strings.is_empty() {
return writer.write_all(&[0u8]);
}
let mut encoded = vec![];
let mut it = strings.iter();
let mut next = it.next();
while let Some(string) = next {
next = it.next();
let len = string.len();
assert!(len < 0x80);
match next {
None => encoded.push(len as u8),
_ => encoded.push(0x80 | len as u8),
};
encoded.extend(&string[..]);
}
writer.write_all(&encoded)
}
#[test]
fn test_doh() {
let b = DoHBuilder::new("example.com".to_owned(), "/dns".to_owned())
.with_address("127.0.0.1:443".to_string())
.with_informal_property(InformalProperty::DNSSEC)
.serialize()
.unwrap();
assert_eq!(
b,
"sdns://AgEAAAAAAAAADTEyNy4wLjAuMTo0NDMAC2V4YW1wbGUuY29tBC9kbnM",
)
}