1
1
use log:: { debug, error} ;
2
2
use std:: collections:: { HashMap , HashSet } ;
3
+ use std:: io;
3
4
use std:: net:: IpAddr ;
4
5
use std:: sync:: Arc ;
5
6
use std:: sync:: RwLock ;
6
- use std:: io;
7
7
use tokio:: time:: { sleep, Duration } ;
8
8
use trust_dns_resolver:: lookup_ip:: LookupIp ;
9
9
use trust_dns_resolver:: TokioAsyncResolver ;
@@ -55,7 +55,7 @@ impl From<LookupIp> for AddrSet {
55
55
// // calls will be returned from cache.
56
56
// resolver.has_changed("www.example.com.", addrset)
57
57
// ```
58
- #[ derive( Clone ) ]
58
+ #[ derive( Clone , Debug ) ]
59
59
pub struct CachedResolver {
60
60
// The configuration of the cached_resolver.
61
61
pub config : CachedResolverConfig ,
@@ -91,7 +91,7 @@ impl CachedResolver {
91
91
//
92
92
pub fn new ( config : CachedResolverConfig ) -> io:: Result < Self > {
93
93
// Construct a new Resolver with default configuration options
94
- let resolver = Arc :: new ( TokioAsyncResolver :: tokio_from_system_conf ( ) ?) ;
94
+ let resolver = Arc :: new ( TokioAsyncResolver :: tokio_from_system_conf ( ) ?) ;
95
95
let data = Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ;
96
96
97
97
Ok ( Self {
@@ -103,46 +103,53 @@ impl CachedResolver {
103
103
104
104
// Schedules the refresher
105
105
pub async fn refresh_dns_entries_loop ( & mut self ) {
106
- let data = self . data . clone ( ) ;
107
- let resolver = TokioAsyncResolver :: tokio_from_system_conf ( ) . unwrap ( ) ;
106
+ let data = self . data . clone ( ) ;
107
+ let resolver = TokioAsyncResolver :: tokio_from_system_conf ( ) . unwrap ( ) ;
108
108
let interval = Duration :: from_secs ( self . config . dns_max_ttl ) ;
109
109
loop {
110
- debug ! ( "Begin refreshing cached DNS addresses." ) ;
111
- // To minimize the time we hold the lock, we first create
112
- // an array with keys.
113
- let mut hostnames: Vec < String > = Vec :: new ( ) ;
114
- {
110
+ debug ! ( "Begin refreshing cached DNS addresses." ) ;
111
+ // To minimize the time we hold the lock, we first create
112
+ // an array with keys.
113
+ let mut hostnames: Vec < String > = Vec :: new ( ) ;
114
+ {
115
115
for hostname in data. read ( ) . unwrap ( ) . keys ( ) {
116
- hostnames. push ( hostname. clone ( ) ) ;
116
+ hostnames. push ( hostname. clone ( ) ) ;
117
117
}
118
- }
118
+ }
119
119
120
- for hostname in hostnames. iter ( ) {
120
+ for hostname in hostnames. iter ( ) {
121
121
match CachedResolver :: fetch_from_data_cache ( data. clone ( ) , hostname. as_str ( ) ) {
122
- Some ( addrset) => {
123
- match resolver. lookup_ip ( hostname) . await {
124
- Ok ( lookup_ip) => {
125
- let new_addrset = AddrSet :: from ( lookup_ip) ;
126
- debug ! ( "Obtained address for host ({}) -> ({:?})" , hostname, new_addrset) ;
122
+ Some ( addrset) => match resolver. lookup_ip ( hostname) . await {
123
+ Ok ( lookup_ip) => {
124
+ let new_addrset = AddrSet :: from ( lookup_ip) ;
125
+ debug ! (
126
+ "Obtained address for host ({}) -> ({:?})" ,
127
+ hostname, new_addrset
128
+ ) ;
127
129
128
- if addrset != new_addrset {
129
- debug ! ( "Addr changed from {:?} to {:?} updating cache." , addrset, new_addrset) ;
130
- CachedResolver :: store_in_cache ( data. clone ( ) , hostname, new_addrset) ;
131
- }
132
- } ,
133
- Err ( err) => {
134
- error ! ( "There was an error trying to resolv {}: ({})." , hostname, err) ;
135
- }
130
+ if addrset != new_addrset {
131
+ debug ! (
132
+ "Addr changed from {:?} to {:?} updating cache." ,
133
+ addrset, new_addrset
134
+ ) ;
135
+ CachedResolver :: store_in_cache ( data. clone ( ) , hostname, new_addrset) ;
136
+ }
137
+ }
138
+ Err ( err) => {
139
+ error ! (
140
+ "There was an error trying to resolv {}: ({})." ,
141
+ hostname, err
142
+ ) ;
136
143
}
137
- }
138
- None => {
144
+ } ,
145
+ None => {
139
146
error ! ( "Could not obtain expected address from cache, this should not happen, \
140
147
as this cache does not allow deleting addresses.") ;
141
- }
148
+ }
142
149
}
143
- }
144
- debug ! ( "Finished refreshing cached DNS addresses." ) ;
145
- sleep ( interval) . await ;
150
+ }
151
+ debug ! ( "Finished refreshing cached DNS addresses." ) ;
152
+ sleep ( interval) . await ;
146
153
}
147
154
}
148
155
@@ -166,16 +173,16 @@ impl CachedResolver {
166
173
// ```
167
174
//
168
175
pub async fn lookup_ip ( & mut self , host : & str ) -> ResolveResult < AddrSet > {
169
- debug ! ( "Lookup up {} in cache" , host) ;
176
+ debug ! ( "Lookup up {} in cache" , host) ;
170
177
match self . fetch_from_cache ( host) {
171
178
Some ( addr_set) => {
172
- debug ! ( "Cache hit!" ) ;
173
- Ok ( addr_set)
174
- } ,
179
+ debug ! ( "Cache hit!" ) ;
180
+ Ok ( addr_set)
181
+ }
175
182
None => {
176
- debug ! ( "Not found, executing a dns query!" ) ;
183
+ debug ! ( "Not found, executing a dns query!" ) ;
177
184
let addr_set = AddrSet :: from ( self . resolver . clone ( ) . lookup_ip ( host) . await ?) ;
178
- debug ! ( "Obtained: {:?}" , addr_set) ;
185
+ debug ! ( "Obtained: {:?}" , addr_set) ;
179
186
CachedResolver :: store_in_cache ( self . data . clone ( ) , host, addr_set. clone ( ) ) ;
180
187
Ok ( addr_set)
181
188
}
@@ -247,7 +254,7 @@ mod tests {
247
254
let mut resolver = CachedResolver :: new ( config) . unwrap ( ) ;
248
255
let hostname = "www.idontexists." ;
249
256
let response = resolver. lookup_ip ( hostname) . await ;
250
- assert ! ( matches!( response, Err ( ResolveError { .. } ) ) ) ;
257
+ assert ! ( matches!( response, Err ( ResolveError { .. } ) ) ) ;
251
258
}
252
259
253
260
#[ tokio:: test]
@@ -256,26 +263,26 @@ mod tests {
256
263
let mut resolver = CachedResolver :: new ( config) . unwrap ( ) ;
257
264
let hostname = "w ww.idontexists." ;
258
265
let response = resolver. lookup_ip ( hostname) . await ;
259
- assert ! ( matches!( response, Err ( ResolveError { .. } ) ) ) ;
260
- assert ! ( !resolver. has_changed( hostname, & AddrSet :: new( ) ) ) ;
266
+ assert ! ( matches!( response, Err ( ResolveError { .. } ) ) ) ;
267
+ assert ! ( !resolver. has_changed( hostname, & AddrSet :: new( ) ) ) ;
261
268
}
262
269
263
270
#[ tokio:: test]
264
271
// Ok, this test is based on the fact that google does DNS RR
265
272
// and does not responds with every available ip everytime, so
266
273
// if I cache here, it will miss after one cache iteration or two.
267
274
async fn thread ( ) {
268
- env_logger:: init ( ) ;
275
+ env_logger:: init ( ) ;
269
276
let config = CachedResolverConfig { dns_max_ttl : 10 } ;
270
277
let mut resolver = CachedResolver :: new ( config) . unwrap ( ) ;
271
278
let hostname = "www.google.com." ;
272
279
let response = resolver. lookup_ip ( hostname) . await ;
273
280
let addr_set = response. unwrap ( ) ;
274
281
assert ! ( !resolver. has_changed( hostname, & addr_set) ) ;
275
- let mut resolver_for_refresher = resolver. clone ( ) ;
276
- let _thread_handle = tokio:: task:: spawn ( async move {
277
- resolver_for_refresher. refresh_dns_entries_loop ( ) . await ;
278
- } ) ;
279
- assert ! ( !resolver. has_changed( hostname, & addr_set) ) ;
282
+ let mut resolver_for_refresher = resolver. clone ( ) ;
283
+ let _thread_handle = tokio:: task:: spawn ( async move {
284
+ resolver_for_refresher. refresh_dns_entries_loop ( ) . await ;
285
+ } ) ;
286
+ assert ! ( !resolver. has_changed( hostname, & addr_set) ) ;
280
287
}
281
288
}
0 commit comments