1use std::time::{Duration, Instant};
7
8use futu_core::error::{FutuError, Result};
9use prost::Message;
10
11use crate::conn::BackendConn;
12use crate::proto_handler::nn_cmd;
13use crate::proto_internal::ft_conn_ping;
14
15const CONN_PING_SUCC: i32 = 0;
16
17pub async fn measure_one_way_net_delay(
26 backend: &BackendConn,
27 user_id: u64,
28 device_id: &str,
29) -> Result<Duration> {
30 let req = build_conn_ping_req(user_id, device_id, 0);
31 let body = req.encode_to_vec();
32 let begin = Instant::now();
33 let frame = backend.request(nn_cmd::PING, body).await?;
34 let rtt = begin.elapsed();
35
36 let rsp = ft_conn_ping::ConnPingRsp::decode(frame.body.as_ref())?;
37 let result_code = rsp.result_code.unwrap_or(-1);
38 if result_code != CONN_PING_SUCC {
39 return Err(FutuError::ServerError {
40 ret_type: result_code,
41 msg: "ConnPing failed".to_string(),
42 });
43 }
44
45 Ok(rtt / 2)
46}
47
48fn build_conn_ping_req(
49 user_id: u64,
50 device_id: &str,
51 data_len: usize,
52) -> ft_conn_ping::ConnPingReq {
53 ft_conn_ping::ConnPingReq {
54 device_id: Some(device_id.to_string()),
55 user_id: Some(user_id),
56 net_type: None,
57 data: Some(vec![0; data_len]),
58 }
59}
60
61#[cfg(test)]
62mod tests;