rotor_dns/
resolver.rs

1use std::io;
2use std::sync::{Arc, Mutex};
3
4use rotor::GenericScope;
5
6use {Query, Resolver, CacheEntry, Request, TimeEntry};
7
8quick_error! {
9    /// Error when creating a query
10    ///
11    /// Errors here are purely theoretical, should not happen in practice.
12    /// It's okay to assert/unwrap on the errors, unless you pass
13    /// user-generated data here.
14    #[derive(Debug)]
15    pub enum QueryError {
16        /// Your query is too long so it doesn't fit in 512 bytes.
17        /// Should not happen in practice
18        TruncatedPacket {
19            description("query results in packet truncation")
20        }
21        Net(err: io::Error) {
22            description(err.description())
23            display("{}", err)
24            cause(err)
25            from()
26        }
27    }
28}
29
30impl Resolver {
31    pub fn query<S>(&self, query: Query, scope: &mut GenericScope)
32        -> Result<Arc<Mutex<Option<Arc<CacheEntry>>>>, QueryError>
33        where S: GenericScope
34    {
35        let ref mut res = *self.0.lock().unwrap();
36        if let Some(cache) =  res.cache.get(&query).map(|x| x.clone()) {
37            if scope.now() > cache.expire {
38                res.cache.remove(&query);
39            } else {
40                // TODO(tailhook) should we trade off possible bugs for
41                //                performance?
42                scope.notifier().wakeup().unwrap();
43                return Ok(Arc::new(Mutex::new(Some(cache.clone()))));
44            }
45        }
46        // TODO(tailhook) implement round-robin/random server selection
47        let server = 0;
48        let id = try!(res.send_request(&query, server));
49
50        let result = Arc::new(Mutex::new(None));
51        let deadline = scope.now() + res.config.timeout;
52        res.running.insert(id, Request {
53            id: id,
54            query: query,
55            nameserver_index: server,
56            attempts: 1,
57            server: res.config.nameservers[server],
58            deadline: deadline,
59            notifiers: vec![(result.clone(), scope.notifier())],
60        });
61        res.timeouts.push(TimeEntry(deadline, id));
62        res.notifier.wakeup().unwrap();  // to schedule a timeout
63        Ok(result)
64    }
65}