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     pub enable_early_data: bool,
53     pub network_type: u32,
54     pub private_dns_mode: u32,
55 }
56 
57 #[derive(Debug)]
58 /// DNS resolution query
59 pub struct Query {
60     /// Raw DNS query, base64 encoded
61     pub query: String,
62     /// Place to send the answer
63     pub response: oneshot::Sender<Response>,
64     /// When this request is considered stale (will be ignored if not serviced by that point)
65     pub expiry: BootTime,
66 }
67 
68 /// Handle to a particular network's DNS resolution
69 pub struct Network {
70     info: ServerInfo,
71     status_rx: watch::Receiver<Status>,
72     command_tx: mpsc::Sender<Command>,
73 }
74 
75 impl Network {
new( info: ServerInfo, config: Config, validation: ValidationReporter, tagger: SocketTagger, ) -> Result<Network>76     pub async fn new(
77         info: ServerInfo,
78         config: Config,
79         validation: ValidationReporter,
80         tagger: SocketTagger,
81     ) -> Result<Network> {
82         let (driver, command_tx, status_rx) =
83             Driver::new(info.clone(), config, validation, tagger).await?;
84         task::spawn(driver.drive());
85         Ok(Network { info, command_tx, status_rx })
86     }
87 
probe(&mut self, timeout: Duration) -> Result<()>88     pub async fn probe(&mut self, timeout: Duration) -> Result<()> {
89         self.command_tx.send(Command::Probe(timeout)).await?;
90         Ok(())
91     }
92 
query(&mut self, query: Query) -> Result<()>93     pub async fn query(&mut self, query: Query) -> Result<()> {
94         // The clone is used to prevent status_rx from being held across an await
95         let status: Status = self.status_rx.borrow().clone();
96         match status {
97             Status::Failed(_) => query
98                 .response
99                 .send(Response::Error { error: QueryError::BrokenServer })
100                 .unwrap_or_else(|_| {
101                     warn!("Query result listener went away before receiving a response")
102                 }),
103             Status::Unprobed => query
104                 .response
105                 .send(Response::Error { error: QueryError::ServerNotReady })
106                 .unwrap_or_else(|_| {
107                     warn!("Query result listener went away before receiving a response")
108                 }),
109             Status::Live => self.command_tx.try_send(Command::Query(query))?,
110         }
111         Ok(())
112     }
113 
get_info(&self) -> &ServerInfo114     pub fn get_info(&self) -> &ServerInfo {
115         &self.info
116     }
117 }
118