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

Commit 930b664a authored by Wayne Ma's avatar Wayne Ma
Browse files

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

This reverts commit 103bf63f.

Resolved merge conflict without any changes to the functionality.

Reason for revert: Mainline removes the MTS support for Q platform so it won't break MTS on Android Q devices.

Change-Id: I8f44fa31034087e02058857db8a8ebfe54febd03
parent 3f761f34
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