feat(windows): hook WSAConnect and enrich probe summary

This commit is contained in:
tianrking committed 2026-03-20 15:56:37 +08:00
1 parent e3dfb03da1
commit 301b69a480
3 files changed
+88 -4

No files matched your search

+34 -3
View File
@@ -286,6 +286,21 @@ fn build_probe_report(results: Vec<ProbeNode>, timeout: Duration, group: String)
let total = results.len();
let ok = results.iter().filter(|r| r.ok).count();
let fail = total.saturating_sub(ok);
let success_rate = if total == 0 {
0.0
} else {
(ok as f64) * 100.0 / (total as f64)
};
let best_latency_ms = results
.iter()
.filter(|r| r.ok)
.map(|r| r.latency_ms)
.min();
let worst_latency_ms = results
.iter()
.filter(|r| r.ok)
.map(|r| r.latency_ms)
.max();
let mut stats = ProbeFailureStats::default();
for r in &results {
if r.ok {
@@ -310,7 +325,14 @@ fn build_probe_report(results: Vec<ProbeNode>, timeout: Duration, group: String)
generated_at_iso8601: format_unix_ts_iso8601(generated_at),
timeout_ms: timeout.as_millis(),
selected_group: group,
summary: ProbeSummary { total, ok, fail },
summary: ProbeSummary {
total,
ok,
fail,
success_rate,
best_latency_ms,
worst_latency_ms,
},
failure_stats: stats,
nodes: results,
}
@@ -346,9 +368,15 @@ fn print_probe_report(report: &ProbeReport) {
}
}
println!(
"Probe summary: total={}, ok={}, fail={}",
report.summary.total, report.summary.ok, report.summary.fail
"Probe summary: total={}, ok={}, fail={}, success_rate={:.2}%",
report.summary.total, report.summary.ok, report.summary.fail, report.summary.success_rate
);
if let Some(best) = report.summary.best_latency_ms {
println!("Latency: best={} ms", best);
}
if let Some(worst) = report.summary.worst_latency_ms {
println!("Latency: worst={} ms", worst);
}
println!(
"Failure stats: timeout={}, refused={}, reset={}, net_unreach={}, addr_unavail={}, not_connected={}, other={}",
report.failure_stats.timeout,
@@ -378,6 +406,9 @@ struct ProbeSummary {
total: usize,
ok: usize,
fail: usize,
success_rate: f64,
best_latency_ms: Option<u128>,
worst_latency_ms: Option<u128>,
}
#[derive(Debug, Serialize, Default)]
+14
View File
@@ -403,6 +403,20 @@ pub unsafe extern "system" fn hook_connect_impl(
SOCKET_ERROR
}
/// Windows WSAConnect hook implementation.
#[cfg(windows)]
pub unsafe extern "system" fn hook_wsa_connect_impl(
sock: usize,
name: *const c_void,
namelen: i32,
_caller_data: *const c_void,
_callee_data: *const c_void,
_sqos: *const c_void,
_gqos: *const c_void,
) -> i32 {
hook_connect_impl(sock, name, namelen)
}
/// Windows getaddrinfo hook implementation.
#[cfg(windows)]
pub unsafe extern "system" fn hook_getaddrinfo_impl(
+40 -1
View File
@@ -15,10 +15,19 @@ use crate::error::{Error, Result};
use super::hooks_windows::{
hook_connect_impl, hook_freeaddrinfo_impl, hook_getaddrinfo_impl, hook_gethostbyname_impl,
hook_getnameinfo_impl,
hook_getnameinfo_impl, hook_wsa_connect_impl,
};
type ConnectFn = unsafe extern "system" fn(usize, *const c_void, i32) -> i32;
type WsaConnectFn = unsafe extern "system" fn(
usize,
*const c_void,
i32,
*const c_void,
*const c_void,
*const c_void,
*const c_void,
) -> i32;
type GetAddrInfoFn =
unsafe extern "system" fn(*const i8, *const i8, *const c_void, *mut *mut c_void) -> i32;
type FreeAddrInfoFn = unsafe extern "system" fn(*mut c_void);
@@ -27,6 +36,7 @@ type GetNameInfoFn =
unsafe extern "system" fn(*const c_void, i32, *mut i8, u32, *mut i8, u32, i32) -> i32;
static ORIGINAL_CONNECT: OnceLock<ConnectFn> = OnceLock::new();
static ORIGINAL_WSA_CONNECT: OnceLock<WsaConnectFn> = OnceLock::new();
static ORIGINAL_GETADDRINFO: OnceLock<GetAddrInfoFn> = OnceLock::new();
static ORIGINAL_FREEADDRINFO: OnceLock<FreeAddrInfoFn> = OnceLock::new();
static ORIGINAL_GETHOSTBYNAME: OnceLock<GetHostByNameFn> = OnceLock::new();
@@ -56,6 +66,8 @@ impl OriginalFunctions {
unsafe {
let connect_fn: ConnectFn =
install_api_hook("connect", hook_connect_impl as *const () as *mut c_void)?;
let wsa_connect_fn: WsaConnectFn =
install_api_hook("WSAConnect", hook_wsa_connect_impl as *const () as *mut c_void)?;
let getaddrinfo_fn: GetAddrInfoFn = install_api_hook(
"getaddrinfo",
hook_getaddrinfo_impl as *const () as *mut c_void,
@@ -74,6 +86,7 @@ impl OriginalFunctions {
)?;
let _ = ORIGINAL_CONNECT.set(connect_fn);
let _ = ORIGINAL_WSA_CONNECT.set(wsa_connect_fn);
let _ = ORIGINAL_GETADDRINFO.set(getaddrinfo_fn);
let _ = ORIGINAL_FREEADDRINFO.set(freeaddrinfo_fn);
let _ = ORIGINAL_GETHOSTBYNAME.set(gethostbyname_fn);
@@ -115,6 +128,32 @@ pub unsafe fn original_connect(sock: usize, addr: *const c_void, len: i32) -> i3
}
}
/// Call the original WSAConnect function.
pub unsafe fn original_wsa_connect(
sock: usize,
name: *const c_void,
namelen: i32,
caller_data: *const c_void,
callee_data: *const c_void,
sqos: *const c_void,
gqos: *const c_void,
) -> i32 {
if let Some(f) = ORIGINAL_WSA_CONNECT.get() {
f(
sock,
name,
namelen,
caller_data,
callee_data,
sqos,
gqos,
)
} else {
WSASetLastError(WSAECONNREFUSED.0);
-1
}
}
/// Call the original getaddrinfo function.
pub unsafe fn original_getaddrinfo(
node: *const i8,