• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Provides the ability to query DNS for a specific network configuration
18 
19 use crate::boot_time::{BootTime, Duration};
20 use crate::config::Config;
21 use crate::dispatcher::{QueryError, Response};
22 use anyhow::Result;
23 use futures::future::BoxFuture;
24 use log::warn;
25 use std::net::SocketAddr;
26 use std::sync::Arc;
27 use tokio::sync::{mpsc, oneshot, watch};
28 use tokio::task;
29 use url::Url;
30 
31 mod driver;
32 
33 use driver::{Command, Driver};
34 
35 pub use driver::Status;
36 
37 /// Closure to signal validation status to outside world
38 pub type ValidationReporter = Arc<dyn Fn(&ServerInfo, bool) -> BoxFuture<()> + Send + Sync>;
39 /// Closure to tag socket during connection construction
40 pub type SocketTagger = Arc<dyn Fn(&std::net::UdpSocket) -> BoxFuture<()> + Send + Sync>;
41 
42 #[derive(Eq, PartialEq, Debug, Clone)]
43 pub struct ServerInfo {
44     pub net_id: u32,
45     pub url: Url,
46     pub peer_addr: SocketAddr,
47     pub domain: Option<String>,
48     pub sk_mark: u32,
49     pub cert_path: Option<String>,
50     pub idle_timeout_ms: u64,
51     pub use_session_resumption: bool,
52 }
53 
54 #[derive(Debug)]
55 /// DNS resolution query
56 pub struct Query {
57     /// Raw DNS query, base64 encoded
58     pub query: String,
59     /// Place to send the answer
60     pub response: oneshot::Sender<Response>,
61     /// When this request is considered stale (will be ignored if not serviced by that point)
62     pub expiry: BootTime,
63 }
64 
65 /// Handle to a particular network's DNS resolution
66 pub struct Network {
67     info: ServerInfo,
68     status_rx: watch::Receiver<Status>,
69     command_tx: mpsc::Sender<Command>,
70 }
71 
72 impl Network {
new( info: ServerInfo, config: Config, validation: ValidationReporter, tagger: SocketTagger, ) -> Result<Network>73     pub async fn new(
74         info: ServerInfo,
75         config: Config,
76         validation: ValidationReporter,
77         tagger: SocketTagger,
78     ) -> Result<Network> {
79         let (driver, command_tx, status_rx) =
80             Driver::new(info.clone(), config, validation, tagger).await?;
81         task::spawn(driver.drive());
82         Ok(Network { info, command_tx, status_rx })
83     }
84 
probe(&mut self, timeout: Duration) -> Result<()>85     pub async fn probe(&mut self, timeout: Duration) -> Result<()> {
86         self.command_tx.send(Command::Probe(timeout)).await?;
87         Ok(())
88     }
89 
query(&mut self, query: Query) -> Result<()>90     pub async fn query(&mut self, query: Query) -> Result<()> {
91         // The clone is used to prevent status_rx from being held across an await
92         let status: Status = self.status_rx.borrow().clone();
93         match status {
94             Status::Failed(_) => query
95                 .response
96                 .send(Response::Error { error: QueryError::BrokenServer })
97                 .unwrap_or_else(|_| {
98                     warn!("Query result listener went away before receiving a response")
99                 }),
100             Status::Unprobed => query
101                 .response
102                 .send(Response::Error { error: QueryError::ServerNotReady })
103                 .unwrap_or_else(|_| {
104                     warn!("Query result listener went away before receiving a response")
105                 }),
106             Status::Live => self.command_tx.try_send(Command::Query(query))?,
107         }
108         Ok(())
109     }
110 
get_info(&self) -> &ServerInfo111     pub fn get_info(&self) -> &ServerInfo {
112         &self.info
113     }
114 }
115