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

Commit 34fbb71d authored by Wayne Ma's avatar Wayne Ma Committed by Automerger Merge Worker
Browse files

Revert "Revert "Injecting handshake relevant statistics into statsd."" am:...

Revert "Revert "Injecting handshake relevant statistics into statsd."" am: 930b664a am: 6a415dc9

Original change: https://android-review.googlesource.com/c/platform/packages/modules/DnsResolver/+/2646330



Change-Id: Ic5044ad2760072ad4f56d9615c07d671622141e4
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents c8802322 6a415dc9
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -249,15 +249,11 @@ cc_library {
        "libcrypto",
        "liblog", //Used by libstatslog_resolv
        "libssl",
        "libstatssocket",
    ],
    header_libs: [
        "libnetdbinder_utils_headers",
    ],
    runtime_libs: [
        // Causes the linkerconfig to create a namespace link from resolv to the
        // libstatssocket library within the statsd apex
        "libstatssocket",
    ],
    export_include_dirs: ["include"],

    product_variables: {
@@ -362,6 +358,7 @@ doh_rust_deps = [
    "liblibc",
    "liblog_rust",
    "libring",
    "libstatslog_rust",
    "libthiserror",
    "libtokio",
    "liburl",
@@ -408,6 +405,11 @@ rust_ffi_static {

    rlibs: doh_rust_deps + ["libquiche_static"],
    prefer_rlib: true,

    shared_libs: [
        "libstatssocket",
    ],

    // TODO(b/194022174), for unit tests to run on the Android 10 platform,
    // libunwind must be statically linked.
    whole_static_libs: ["libunwind"],
@@ -438,6 +440,7 @@ rust_ffi_static {
        "liblog_rust",
        "libquiche_static",
        "libring",
        "libstatslog_rust",
        "libthiserror",
        "libtokio",
        "liburl",
+6 −1
Original line number Diff line number Diff line
@@ -602,6 +602,9 @@ int PrivateDnsConfiguration::setDoh(int32_t netId, uint32_t mark,
        return 0;
    }

    const NetworkType networkType = resolv_get_network_types_for_net(netId);
    const PrivateDnsStatus status = getStatusLocked(netId);

    // Sort the input servers to prefer IPv6.
    const std::vector<std::string> sortedServers = sortServers(servers);

@@ -632,8 +635,10 @@ int PrivateDnsConfiguration::setDoh(int32_t netId, uint32_t mark,
    const FeatureFlags flags = makeDohFeatureFlags();
    LOG(DEBUG) << __func__ << ": " << toString(flags);

    const PrivateDnsModes privateDnsMode = convertEnumType(status.mode);
    return doh_net_new(mDohDispatcher, netId, dohId.httpsTemplate.c_str(), dohId.host.c_str(),
                       dohId.ipAddr.c_str(), mark, caCert.c_str(), &flags);
                       dohId.ipAddr.c_str(), mark, caCert.c_str(), &flags, networkType,
                       privateDnsMode);
}

void PrivateDnsConfiguration::clearDoh(unsigned netId) {
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ void doh_dispatcher_delete(DohDispatcher* doh);
/// `url`, `domain`, `ip_addr`, `cert_path` are null terminated strings.
int32_t doh_net_new(DohDispatcher* doh, uint32_t net_id, const char* url, const char* domain,
                    const char* ip_addr, uint32_t sk_mark, const char* cert_path,
                    const FeatureFlags* flags);
                    const FeatureFlags* flags, uint32_t network_type, uint32_t private_dns_mode);

/// Sends a DNS query via the network associated to the given |net_id| and waits for the response.
/// The return code should be either one of the public constant RESULT_* to indicate the error or
+76 −2
Original line number Diff line number Diff line
@@ -17,12 +17,14 @@

use crate::boot_time;
use crate::boot_time::BootTime;
use crate::metrics::log_handshake_event_stats;
use log::{debug, info, warn};
use quiche::h3;
use std::collections::HashMap;
use std::default::Default;
use std::future;
use std::io;
use std::time::Instant;
use thiserror::Error;
use tokio::net::UdpSocket;
use tokio::select;
@@ -30,6 +32,50 @@ use tokio::sync::{mpsc, oneshot, watch};

use super::Status;

#[derive(Copy, Clone, Debug)]
pub enum Cause {
    Probe,
    Reconnect,
    Retry,
}

#[derive(Clone)]
#[allow(dead_code)]
pub enum HandshakeResult {
    Unknown,
    Success,
    Timeout,
    TlsFail,
    ServerUnreachable,
}

#[derive(Copy, Clone, Debug)]
pub struct HandshakeInfo {
    pub cause: Cause,
    pub sent_bytes: u64,
    pub recv_bytes: u64,
    pub elapsed: u128,
    pub quic_version: u32,
    pub network_type: u32,
    pub private_dns_mode: u32,
    pub session_hit_checker: bool,
}

impl std::fmt::Display for HandshakeInfo {
    #[inline]
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(
            f,
            "cause={:?}, sent_bytes={}, recv_bytes={}, quic_version={}, session_hit_checker={}",
            self.cause,
            self.sent_bytes,
            self.recv_bytes,
            self.quic_version,
            self.session_hit_checker
        )
    }
}

#[derive(Error, Debug)]
pub enum Error {
    #[error("network IO error: {0}")]
@@ -92,6 +138,8 @@ struct Driver {
    // if we poll on a dead receiver in a select! it will immediately return None. As a result, we
    // need this to gate whether or not to include .recv() in our select!
    closing: bool,
    handshake_info: HandshakeInfo,
    connection_start: Instant,
}

struct H3Driver {
@@ -121,8 +169,9 @@ pub async fn drive(
    quiche_conn: quiche::Connection,
    socket: UdpSocket,
    net_id: u32,
    handshake_info: HandshakeInfo,
) -> Result<()> {
    Driver::new(request_rx, status_tx, quiche_conn, socket, net_id).drive().await
    Driver::new(request_rx, status_tx, quiche_conn, socket, net_id, handshake_info).drive().await
}

impl Driver {
@@ -132,6 +181,7 @@ impl Driver {
        quiche_conn: quiche::Connection,
        socket: UdpSocket,
        net_id: u32,
        handshake_info: HandshakeInfo,
    ) -> Self {
        Self {
            request_rx,
@@ -141,10 +191,13 @@ impl Driver {
            buffer: Box::new([0; MAX_UDP_PACKET_SIZE]),
            net_id,
            closing: false,
            handshake_info,
            connection_start: Instant::now(),
        }
    }

    async fn drive(mut self) -> Result<()> {
        self.connection_start = Instant::now();
        // Prime connection
        self.flush_tx().await?;
        loop {
@@ -202,6 +255,13 @@ impl Driver {
                self.quiche_conn.trace_id(),
                self.net_id
            );
            self.handshake_info.elapsed = self.connection_start.elapsed().as_micros();
            // In Stats, sent_bytes implements the way that omits the length of padding data
            // append to the datagram.
            self.handshake_info.sent_bytes = self.quiche_conn.stats().sent_bytes;
            self.handshake_info.recv_bytes = self.quiche_conn.stats().recv_bytes;
            self.handshake_info.quic_version = quiche::PROTOCOL_VERSION;
            log_handshake_event_stats(HandshakeResult::Success, self.handshake_info);
            let h3_config = h3::Config::new()?;
            let h3_conn = h3::Connection::with_transport(&mut self.quiche_conn, &h3_config)?;
            self = H3Driver::new(self, h3_conn).drive().await?;
@@ -213,7 +273,20 @@ impl Driver {
            // If a quiche timer would fire, call their callback
            _ = timer => {
                info!("Driver: Timer expired on network {}", self.net_id);
                self.quiche_conn.on_timeout()
                self.quiche_conn.on_timeout();

                if !self.quiche_conn.is_established() && self.quiche_conn.is_closed() {
                    info!(
                        "Connection {} timeouted on network {}",
                        self.quiche_conn.trace_id(),
                        self.net_id
                    );
                    self.handshake_info.elapsed = self.connection_start.elapsed().as_micros();
                    log_handshake_event_stats(
                        HandshakeResult::Timeout,
                        self.handshake_info,
                    );
                }
            }
            // If we got packets from our peer, pass them to quiche
            Ok((size, from)) = self.socket.recv_from(self.buffer.as_mut()) => {
@@ -222,6 +295,7 @@ impl Driver {
                debug!("Received {} bytes on network {}", size, self.net_id);
            }
        };

        // Any of the actions in the select could require us to send packets to the peer
        self.flush_tx().await?;

+23 −6
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@
//! Module providing an async abstraction around a quiche HTTP/3 connection

use crate::boot_time::BootTime;
use crate::connection::driver::Cause;
use crate::connection::driver::HandshakeInfo;
use crate::network::ServerInfo;
use crate::network::SocketTagger;
use log::{debug, error, warn};
use quiche::h3;
@@ -27,7 +30,7 @@ use tokio::net::UdpSocket;
use tokio::sync::{mpsc, oneshot, watch};
use tokio::task;

mod driver;
pub mod driver;

pub use driver::Stream;
use driver::{drive, Request};
@@ -129,14 +132,16 @@ impl Connection {
    const MAX_PENDING_REQUESTS: usize = 10;
    /// Create a new connection with a background task handling IO.
    pub async fn new(
        server_name: Option<&str>,
        to: SocketAddr,
        socket_mark: u32,
        net_id: u32,
        info: &ServerInfo,
        tag_socket: &SocketTagger,
        config: &mut quiche::Config,
        session: Option<Vec<u8>>,
        cause: Cause,
    ) -> Result<Self> {
        let server_name = info.domain.as_deref();
        let to = info.peer_addr;
        let socket_mark = info.sk_mark;
        let net_id = info.net_id;
        let (request_tx, request_rx) = mpsc::channel(Self::MAX_PENDING_REQUESTS);
        let (status_tx, status_rx) = watch::channel(Status::QUIC);
        let scid = new_scid();
@@ -152,8 +157,20 @@ impl Connection {
            quiche_conn.set_session(&session)?;
        }

        let handshake_info = HandshakeInfo {
            cause,
            sent_bytes: 0,
            recv_bytes: 0,
            elapsed: 0,
            quic_version: 0,
            network_type: info.network_type,
            private_dns_mode: info.private_dns_mode,
            session_hit_checker: quiche_conn.session().is_some(),
        };

        let driver = async move {
            let result = drive(request_rx, status_tx, quiche_conn, socket, net_id).await;
            let result =
                drive(request_rx, status_tx, quiche_conn, socket, net_id, handshake_info).await;
            if let Err(ref e) = result {
                warn!("Connection driver returns some Err: {:?}", e);
            }
Loading