feat: complete wgcloak v1 transports

This commit is contained in:
h3cx committed 2026-09-19 19:47:16 +02:00
1 parent 49ec9d8c33
commit cedab4910e
47 files changed
+2849 -400

No files matched your search

+91
View File
@@ -2,6 +2,9 @@ use wgcloak::control;
use std::os::unix::fs::PermissionsExt;
use tempfile::tempdir;
use tokio::io::AsyncReadExt;
use tokio::net::UnixStream;
use tokio::time::{sleep, timeout, Duration};
#[tokio::test]
async fn control_commands_and_socket_permissions() {
@@ -98,3 +101,91 @@ fn default_socket_path_never_targets_the_shared_tmp_socket() {
assert_eq!(path.file_name().unwrap(), "wgcloak.sock");
assert_ne!(path.parent().unwrap(), std::path::Path::new("/tmp"));
}
#[tokio::test]
async fn control_serializes_unusual_status_and_stats_keys_as_json() {
let dir = tempdir().unwrap();
let path = dir.path().join("runtime/control.sock");
let state = control::ControlState::default();
state.set_status("ready\"\n\t\0").await;
let mut clients = std::collections::BTreeMap::new();
clients.insert("client\"\n\t\0".to_owned(), 1);
state
.set_transport_stats_by_client_id("transport\"\n\t\0", 1, Default::default(), clients)
.await;
let server = control::ControlServer::bind(&path, state.clone())
.await
.unwrap();
let task = tokio::spawn(server.run());
let status: serde_json::Value =
serde_json::from_str(&control::send_command(&path, "status").await.unwrap()).unwrap();
assert_eq!(status["status"], "ready\"\n\t\0");
let stats: serde_json::Value =
serde_json::from_str(&control::send_command(&path, "stats").await.unwrap()).unwrap();
assert_eq!(
stats["stats"]["active_sessions_by_client_id"]["client\"\n\t\0"],
1
);
assert_eq!(
stats["stats"]["active_sessions_by_transport"]["transport\"\n\t\0"],
1
);
state.shutdown.cancel();
task.await.unwrap().unwrap();
}
#[tokio::test]
async fn idle_control_clients_are_closed_and_do_not_pin_shutdown() {
let dir = tempdir().unwrap();
let path = dir.path().join("runtime/control.sock");
let state = control::ControlState::default();
let server = control::ControlServer::bind(&path, state.clone())
.await
.unwrap();
let task = tokio::spawn(server.run());
let mut idle = UnixStream::connect(&path).await.unwrap();
let mut response = Vec::new();
timeout(
control::CONTROL_REQUEST_TIMEOUT + Duration::from_secs(1),
idle.read_to_end(&mut response),
)
.await
.expect("idle control client must be closed")
.unwrap();
assert!(response.is_empty());
state.shutdown.cancel();
timeout(Duration::from_secs(1), task)
.await
.unwrap()
.unwrap()
.unwrap();
}
#[tokio::test]
async fn control_rejects_clients_beyond_the_concurrency_bound() {
let dir = tempdir().unwrap();
let path = dir.path().join("runtime/control.sock");
let state = control::ControlState::default();
let server = control::ControlServer::bind(&path, state.clone())
.await
.unwrap();
let task = tokio::spawn(server.run());
let mut held = Vec::new();
for _ in 0..control::CONTROL_MAX_CLIENTS {
held.push(UnixStream::connect(&path).await.unwrap());
}
sleep(Duration::from_millis(25)).await;
let mut extra = UnixStream::connect(&path).await.unwrap();
let mut response = Vec::new();
timeout(Duration::from_secs(1), extra.read_to_end(&mut response))
.await
.expect("connection over the bound must be closed")
.unwrap();
assert!(response.is_empty());
drop(held);
state.shutdown.cancel();
task.await.unwrap().unwrap();
}