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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
extern crate rotor;
extern crate rand;
extern crate dns_parser;
extern crate resolv_conf;
#[macro_use] extern crate quick_error;
mod config;
mod fsm;
mod resolver;
mod time_util;
use std::marker::PhantomData;
use std::collections::{HashMap, BinaryHeap};
use std::sync::{Arc, Mutex};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use rotor::{EarlyScope, PollOpt, EventSet, Notifier, Time, Response, Void};
use rotor::mio::udp::UdpSocket;
pub use config::Config;
pub use resolver::QueryError;
pub use dns_parser::QueryType;
type Id = u16;
#[derive(Debug)]
struct TimeEntry(Time, Id);
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum Query {
LookupIpv4(String),
LookupSrv(String),
LookupMx(String),
}
#[derive(Debug)]
pub enum Answer {
ServerUnavailable,
Ipv4(Vec<Ipv4Addr>),
Srv(Vec<SrvRecord>),
Mx(Vec<MxRecord>),
}
#[derive(Debug, Clone)]
pub struct SrvRecord {
pub priority: u16,
pub weight: u16,
pub port: u16,
pub target: String,
}
#[derive(Debug, Clone)]
pub struct MxRecord {
pub preference: u16,
pub exchange: String,
}
struct Request {
id: Id,
query: Query,
nameserver_index: usize,
attempts: u32,
server: SocketAddr,
deadline: Time,
notifiers: Vec<(Arc<Mutex<Option<Arc<CacheEntry>>>>, Notifier)>,
}
#[derive(Debug)]
pub struct CacheEntry {
pub value: Answer,
pub expire: Time,
}
struct DnsMachine {
config: Config,
running: HashMap<Id, Request>,
cache: HashMap<Query, Arc<CacheEntry>>,
sock: UdpSocket,
timeouts: BinaryHeap<TimeEntry>,
notifier: Notifier,
}
pub struct Fsm<C>(Arc<Mutex<DnsMachine>>, PhantomData<*const C>);
pub struct Resolver(Arc<Mutex<DnsMachine>>);
pub fn create_resolver<C>(scope: &mut EarlyScope, config: Config)
-> Response<(Fsm<C>, Resolver), Void>
{
let machine = DnsMachine {
config: config,
running: HashMap::new(),
cache: HashMap::new(),
sock: match UdpSocket::bound(&SocketAddr::V4(
SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0))) {
Ok(sock) => sock,
Err(e) => return Response::error(Box::new(e)),
},
timeouts: BinaryHeap::new(),
notifier: scope.notifier(),
};
match scope.register(&machine.sock,
EventSet::readable(), PollOpt::level())
{
Ok(()) => {}
Err(e) => return Response::error(Box::new(e)),
}
let arc = Arc::new(Mutex::new(machine));
Response::ok((Fsm(arc.clone(), PhantomData), Resolver(arc.clone())))
}