xref: /webrtc/util/src/vnet/resolver.rs (revision ffe74184)
1 #[cfg(test)]
2 mod resolver_test;
3 
4 use crate::error::*;
5 
6 use std::collections::HashMap;
7 use std::future::Future;
8 use std::net::IpAddr;
9 use std::pin::Pin;
10 use std::str::FromStr;
11 use std::sync::Arc;
12 use tokio::sync::Mutex;
13 
14 #[derive(Default)]
15 pub(crate) struct Resolver {
16     parent: Option<Arc<Mutex<Resolver>>>,
17     hosts: HashMap<String, IpAddr>,
18 }
19 
20 impl Resolver {
new() -> Self21     pub(crate) fn new() -> Self {
22         let mut r = Resolver {
23             parent: None,
24             hosts: HashMap::new(),
25         };
26 
27         if let Err(err) = r.add_host("localhost".to_owned(), "127.0.0.1".to_owned()) {
28             log::warn!("failed to add localhost to Resolver: {}", err);
29         }
30         r
31     }
32 
set_parent(&mut self, p: Arc<Mutex<Resolver>>)33     pub(crate) fn set_parent(&mut self, p: Arc<Mutex<Resolver>>) {
34         self.parent = Some(p);
35     }
36 
add_host(&mut self, name: String, ip_addr: String) -> Result<()>37     pub(crate) fn add_host(&mut self, name: String, ip_addr: String) -> Result<()> {
38         if name.is_empty() {
39             return Err(Error::ErrHostnameEmpty);
40         }
41         let ip = IpAddr::from_str(&ip_addr)?;
42         self.hosts.insert(name, ip);
43 
44         Ok(())
45     }
46 
lookup( &self, host_name: String, ) -> Pin<Box<dyn Future<Output = Option<IpAddr>> + Send + 'static>>47     pub(crate) fn lookup(
48         &self,
49         host_name: String,
50     ) -> Pin<Box<dyn Future<Output = Option<IpAddr>> + Send + 'static>> {
51         if let Some(ip) = self.hosts.get(&host_name) {
52             let ip2 = *ip;
53             return Box::pin(async move { Some(ip2) });
54         }
55 
56         // mutex must be unlocked before calling into parent Resolver
57         if let Some(parent) = &self.parent {
58             let parent2 = Arc::clone(parent);
59             Box::pin(async move {
60                 let p = parent2.lock().await;
61                 p.lookup(host_name).await
62             })
63         } else {
64             Box::pin(async move { None })
65         }
66     }
67 }
68