Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba0cd174 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 7947225 from 9e7dcc46 to mainline-mediaprovider-release

Change-Id: I57337f9355d8be8a7eebed50cdd2c7d273c2c3d4
parents dd7eee2e 9e7dcc46
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -17,6 +17,12 @@ static const uintptr_t DNS_HEADER_SIZE = 12;

static const uintptr_t MAX_UDP_PAYLOAD_SIZE = 1350;

/// Default value for max_idle_timeout transport parameter.
static const uint64_t QUICHE_IDLE_TIMEOUT_MS = 10000;

/// Default value for initial_max_streams_bidi transport parameter.
static const uint64_t MAX_STREAMS_BIDI = 100;

/// Frontend object.
struct DohFrontend;

@@ -72,6 +78,23 @@ bool frontend_set_private_key(DohFrontend *doh, const char *private_key);
/// are received. This function works even in the middle of the worker thread.
bool frontend_set_delay_queries(DohFrontend *doh, int32_t count);

/// Configures the `DohFrontend` to use the given value for max_idle_timeout transport parameter.
bool frontend_set_max_idle_timeout(DohFrontend *doh, uint64_t value);

/// Configures the `DohFrontend` to use the given value for these transport parameters.
/// - initial_max_data
/// - initial_max_stream_data_bidi_local
/// - initial_max_stream_data_bidi_remote
/// - initial_max_stream_data_uni
bool frontend_set_max_buffer_size(DohFrontend *doh, uint64_t value);

/// Configures the `DohFrontend` to use the given value for initial_max_streams_bidi transport
/// parameter.
bool frontend_set_max_streams_bidi(DohFrontend *doh, uint64_t value);

/// Sets the `DohFrontend` to block or unblock sending any data.
bool frontend_block_sending(DohFrontend *doh, bool block);

/// Gets the statistics of the `DohFrontend` and writes the result to |out|.
void frontend_stats(const DohFrontend *doh, Stats *out);

+11 −11
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
//! Client management, including the communication with quiche I/O.

use anyhow::{anyhow, bail, ensure, Result};
use log::{debug, info, warn};
use log::{debug, error, info, warn};
use quiche::h3::NameValue;
use ring::hmac;
use ring::rand::SystemRandom;
@@ -170,16 +170,16 @@ impl Client {
    pub fn flush_egress(&mut self) -> Result<Vec<u8>> {
        let mut ret = vec![];
        let mut buf = [0; MAX_UDP_PAYLOAD_SIZE];
        loop {

        let (write, _) = match self.conn.send(&mut buf) {
            Ok(v) => v,
                Err(quiche::Error::Done) => break,

                // Maybe close the connection?
                Err(e) => bail!(e),
            Err(quiche::Error::Done) => bail!(quiche::Error::Done),
            Err(e) => {
                error!("flush_egress failed: {}", e);
                bail!(e)
            }
        };
        ret.append(&mut buf[..write].to_vec());
        }

        Ok(ret)
    }
+23 −1
Original line number Diff line number Diff line
@@ -18,13 +18,35 @@

use std::default::Default;

/// Default value for max_idle_timeout transport parameter.
pub const QUICHE_IDLE_TIMEOUT_MS: u64 = 10_000;

/// Default value for these transport parameters:
/// - initial_max_data
/// - initial_max_stream_data_bidi_local
/// - initial_max_stream_data_bidi_remote
/// - initial_max_stream_data_uni
const MAX_BUFFER_SIZE: u64 = 1_000_000;

/// Default value for initial_max_streams_bidi transport parameter.
pub const MAX_STREAMS_BIDI: u64 = 100;

#[derive(Debug, Default)]
pub struct Config {
    pub delay_queries: i32,
    pub block_sending: bool,
    pub max_idle_timeout: u64,
    pub max_buffer_size: u64,
    pub max_streams_bidi: u64,
}

impl Config {
    pub fn new() -> Self {
        Default::default()
        Self {
            max_idle_timeout: QUICHE_IDLE_TIMEOUT_MS,
            max_buffer_size: MAX_BUFFER_SIZE,
            max_streams_bidi: MAX_STREAMS_BIDI,
            ..Default::default()
        }
    }
}
+45 −25
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
//! DoH server frontend.

use crate::client::{ClientMap, ConnectionID, DNS_HEADER_SIZE, MAX_UDP_PAYLOAD_SIZE};
use crate::config::Config;
use crate::config::{Config, QUICHE_IDLE_TIMEOUT_MS};
use crate::stats::Stats;
use anyhow::{bail, ensure, Result};
use lazy_static::lazy_static;
@@ -44,8 +44,6 @@ lazy_static! {
    );
}

const QUICHE_IDLE_TIMEOUT_MS: u64 = 10_000;

#[derive(Debug)]
enum Command {
    MaybeWrite { connection_id: ConnectionID },
@@ -72,10 +70,12 @@ pub struct DohFrontend {

    // Custom runtime configuration to control the behavior of the worker thread.
    // It's shared with the worker thread.
    // TODO: use channel to update worker_thread configuration.
    config: Arc<Mutex<Config>>,

    // Stores some statistic to check DohFrontend status.
    // It's shared with the worker thread.
    // TODO: use channel to retrieve the stats from worker_thread.
    stats: Arc<Mutex<Stats>>,
}

@@ -145,6 +145,26 @@ impl DohFrontend {
        Ok(())
    }

    pub fn set_max_idle_timeout(&self, value: u64) -> Result<()> {
        self.config.lock().unwrap().max_idle_timeout = value;
        Ok(())
    }

    pub fn set_max_buffer_size(&self, value: u64) -> Result<()> {
        self.config.lock().unwrap().max_buffer_size = value;
        Ok(())
    }

    pub fn set_max_streams_bidi(&self, value: u64) -> Result<()> {
        self.config.lock().unwrap().max_streams_bidi = value;
        Ok(())
    }

    pub fn block_sending(&self, value: bool) -> Result<()> {
        self.config.lock().unwrap().block_sending = value;
        Ok(())
    }

    pub fn stats(&self) -> Stats {
        self.stats.lock().unwrap().clone()
    }
@@ -167,6 +187,7 @@ impl DohFrontend {
        let clients = ClientMap::new(create_quiche_config(
            self.certificate.to_string(),
            self.private_key.to_string(),
            self.config.clone(),
        )?)?;

        Ok(WorkerParams {
@@ -279,26 +300,18 @@ async fn worker_thread(params: WorkerParams) -> Result<()> {
                }
            }

            Some(command) = event_rx.recv() => {
            Some(command) = event_rx.recv(), if !config.lock().unwrap().block_sending => {
                match command {
                    Command::MaybeWrite {connection_id} => {
                        if let Some(client) = clients.get_mut(&connection_id) {
                            match client.flush_egress() {
                                Ok(v) => {
                                    // The DoH engine in DnsResolver can't handle empty response.
                                    if !v.is_empty() {
                            while let Ok(v) = client.flush_egress() {
                                let addr = client.addr();
                                debug!("Sending {} bytes to client {}", v.len(), addr);
                                if let Err(e) = frontend_socket.send_to(&v, addr).await {
                                    error!("Failed to send packet to {:?}: {:?}", client, e);
                                }
                            }
                                }
                                Err(e) => {
                                    error!("flush_egress failed: {}", e);
                                }
                            }
                            client.process_pending_answers().unwrap();
                            client.process_pending_answers()?;
                        }
                    }
                }
@@ -307,7 +320,11 @@ async fn worker_thread(params: WorkerParams) -> Result<()> {
    }
}

fn create_quiche_config(certificate: String, private_key: String) -> Result<quiche::Config> {
fn create_quiche_config(
    certificate: String,
    private_key: String,
    config: Arc<Mutex<Config>>,
) -> Result<quiche::Config> {
    let mut quiche_config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;

    // Use pipe as a file path for Quiche to read the certificate and the private key.
@@ -328,13 +345,16 @@ fn create_quiche_config(certificate: String, private_key: String) -> Result<quic
    handle.join().unwrap();

    quiche_config.set_application_protos(quiche::h3::APPLICATION_PROTOCOL)?;
    quiche_config.set_max_idle_timeout(QUICHE_IDLE_TIMEOUT_MS);
    quiche_config.set_max_idle_timeout(config.lock().unwrap().max_idle_timeout);
    quiche_config.set_max_recv_udp_payload_size(MAX_UDP_PAYLOAD_SIZE);
    quiche_config.set_initial_max_data(10000000);
    quiche_config.set_initial_max_stream_data_bidi_local(1000000);
    quiche_config.set_initial_max_stream_data_bidi_remote(1000000);
    quiche_config.set_initial_max_stream_data_uni(1000000);
    quiche_config.set_initial_max_streams_bidi(100);

    let max_buffer_size = config.lock().unwrap().max_buffer_size;
    quiche_config.set_initial_max_data(max_buffer_size);
    quiche_config.set_initial_max_stream_data_bidi_local(max_buffer_size);
    quiche_config.set_initial_max_stream_data_bidi_remote(max_buffer_size);
    quiche_config.set_initial_max_stream_data_uni(max_buffer_size);

    quiche_config.set_initial_max_streams_bidi(config.lock().unwrap().max_streams_bidi);
    quiche_config.set_initial_max_streams_uni(100);
    quiche_config.set_disable_active_migration(true);

+29 −0
Original line number Diff line number Diff line
@@ -124,6 +124,35 @@ pub extern "C" fn frontend_set_delay_queries(doh: &mut DohFrontend, count: i32)
    doh.set_delay_queries(count).or_else(logging_and_return_err).is_ok()
}

/// Configures the `DohFrontend` to use the given value for max_idle_timeout transport parameter.
#[no_mangle]
pub extern "C" fn frontend_set_max_idle_timeout(doh: &mut DohFrontend, value: u64) -> bool {
    doh.set_max_idle_timeout(value).or_else(logging_and_return_err).is_ok()
}

/// Configures the `DohFrontend` to use the given value for these transport parameters.
/// - initial_max_data
/// - initial_max_stream_data_bidi_local
/// - initial_max_stream_data_bidi_remote
/// - initial_max_stream_data_uni
#[no_mangle]
pub extern "C" fn frontend_set_max_buffer_size(doh: &mut DohFrontend, value: u64) -> bool {
    doh.set_max_buffer_size(value).or_else(logging_and_return_err).is_ok()
}

/// Configures the `DohFrontend` to use the given value for initial_max_streams_bidi transport
/// parameter.
#[no_mangle]
pub extern "C" fn frontend_set_max_streams_bidi(doh: &mut DohFrontend, value: u64) -> bool {
    doh.set_max_streams_bidi(value).or_else(logging_and_return_err).is_ok()
}

/// Sets the `DohFrontend` to block or unblock sending any data.
#[no_mangle]
pub extern "C" fn frontend_block_sending(doh: &mut DohFrontend, block: bool) -> bool {
    doh.block_sending(block).or_else(logging_and_return_err).is_ok()
}

/// Gets the statistics of the `DohFrontend` and writes the result to |out|.
#[no_mangle]
pub extern "C" fn frontend_stats(doh: &DohFrontend, out: &mut Stats) {
Loading