feat(rust-core): add adaptive keepalive telemetry, MTU handling, and per-client rate limiting APIs
This commit is contained in:
@@ -285,6 +285,39 @@ async fn handle_client_request(
|
||||
let stats = vpn_client.get_statistics().await;
|
||||
ManagementResponse::ok(id, stats)
|
||||
}
|
||||
"getConnectionQuality" => {
|
||||
match vpn_client.get_connection_quality() {
|
||||
Some(quality) => {
|
||||
let health = vpn_client.get_link_health().await;
|
||||
let interval_secs = match health {
|
||||
crate::keepalive::LinkHealth::Healthy => 60,
|
||||
crate::keepalive::LinkHealth::Degraded => 30,
|
||||
crate::keepalive::LinkHealth::Critical => 10,
|
||||
};
|
||||
ManagementResponse::ok(id, serde_json::json!({
|
||||
"srttMs": quality.srtt_ms,
|
||||
"jitterMs": quality.jitter_ms,
|
||||
"minRttMs": quality.min_rtt_ms,
|
||||
"maxRttMs": quality.max_rtt_ms,
|
||||
"lossRatio": quality.loss_ratio,
|
||||
"consecutiveTimeouts": quality.consecutive_timeouts,
|
||||
"linkHealth": format!("{}", health),
|
||||
"currentKeepaliveIntervalSecs": interval_secs,
|
||||
}))
|
||||
}
|
||||
None => ManagementResponse::ok(id, serde_json::json!(null)),
|
||||
}
|
||||
}
|
||||
"getMtuInfo" => {
|
||||
ManagementResponse::ok(id, serde_json::json!({
|
||||
"tunMtu": 1420,
|
||||
"effectiveMtu": crate::mtu::TunnelOverhead::default_overhead().effective_tun_mtu(1500),
|
||||
"linkMtu": 1500,
|
||||
"overheadBytes": crate::mtu::TunnelOverhead::default_overhead().total(),
|
||||
"oversizedPacketsDropped": 0,
|
||||
"icmpTooBigSent": 0,
|
||||
}))
|
||||
}
|
||||
_ => ManagementResponse::err(id, format!("Unknown client method: {}", request.method)),
|
||||
}
|
||||
}
|
||||
@@ -349,6 +382,50 @@ async fn handle_server_request(
|
||||
Err(e) => ManagementResponse::err(id, format!("Disconnect client failed: {}", e)),
|
||||
}
|
||||
}
|
||||
"setClientRateLimit" => {
|
||||
let client_id = match request.params.get("clientId").and_then(|v| v.as_str()) {
|
||||
Some(id) => id.to_string(),
|
||||
None => return ManagementResponse::err(id, "Missing clientId".to_string()),
|
||||
};
|
||||
let rate = match request.params.get("rateBytesPerSec").and_then(|v| v.as_u64()) {
|
||||
Some(r) => r,
|
||||
None => return ManagementResponse::err(id, "Missing rateBytesPerSec".to_string()),
|
||||
};
|
||||
let burst = match request.params.get("burstBytes").and_then(|v| v.as_u64()) {
|
||||
Some(b) => b,
|
||||
None => return ManagementResponse::err(id, "Missing burstBytes".to_string()),
|
||||
};
|
||||
match vpn_server.set_client_rate_limit(&client_id, rate, burst).await {
|
||||
Ok(()) => ManagementResponse::ok(id, serde_json::json!({})),
|
||||
Err(e) => ManagementResponse::err(id, format!("Failed: {}", e)),
|
||||
}
|
||||
}
|
||||
"removeClientRateLimit" => {
|
||||
let client_id = match request.params.get("clientId").and_then(|v| v.as_str()) {
|
||||
Some(id) => id.to_string(),
|
||||
None => return ManagementResponse::err(id, "Missing clientId".to_string()),
|
||||
};
|
||||
match vpn_server.remove_client_rate_limit(&client_id).await {
|
||||
Ok(()) => ManagementResponse::ok(id, serde_json::json!({})),
|
||||
Err(e) => ManagementResponse::err(id, format!("Failed: {}", e)),
|
||||
}
|
||||
}
|
||||
"getClientTelemetry" => {
|
||||
let client_id = match request.params.get("clientId").and_then(|v| v.as_str()) {
|
||||
Some(cid) => cid.to_string(),
|
||||
None => return ManagementResponse::err(id, "Missing clientId".to_string()),
|
||||
};
|
||||
let clients = vpn_server.list_clients().await;
|
||||
match clients.into_iter().find(|c| c.client_id == client_id) {
|
||||
Some(info) => {
|
||||
match serde_json::to_value(&info) {
|
||||
Ok(v) => ManagementResponse::ok(id, v),
|
||||
Err(e) => ManagementResponse::err(id, format!("Serialize error: {}", e)),
|
||||
}
|
||||
}
|
||||
None => ManagementResponse::err(id, format!("Client {} not found", client_id)),
|
||||
}
|
||||
}
|
||||
"generateKeypair" => match crypto::generate_keypair() {
|
||||
Ok((public_key, private_key)) => ManagementResponse::ok(
|
||||
id,
|
||||
|
||||
Reference in New Issue
Block a user