Skip to main content

a3s_box_runtime/network/
mod.rs

1//! Network management for container-to-container communication.
2//!
3//! Provides `NetworkStore` for persisting network state and
4//! platform-specific network backend managers for bridge networking:
5//! - Linux: `PasstManager` (passt Unix stream socket)
6//! - macOS: `NetProxyManager` (pure-Rust vfkit server, no external binary)
7
8#[cfg(any(target_os = "linux", all(test, unix)))]
9mod passt;
10mod store;
11
12#[cfg(target_os = "macos")]
13pub use a3s_box_netproxy::NetProxyManager;
14#[cfg(any(target_os = "linux", all(test, unix)))]
15pub use passt::{terminate_passt, PasstManager};
16pub use store::NetworkStore;
17
18/// Stable per-user switch directory for one logical bridge network.
19#[cfg(unix)]
20pub fn bridge_socket_dir(home: &std::path::Path, network_name: &str) -> std::path::PathBuf {
21    use sha2::{Digest, Sha256};
22
23    let mut digest = Sha256::new();
24    digest.update(home.as_os_str().as_encoded_bytes());
25    digest.update([0]);
26    digest.update(network_name.as_bytes());
27    let key = hex::encode(digest.finalize());
28    let uid = unsafe { libc::getuid() };
29    let temporary = if cfg!(target_os = "macos") {
30        std::path::PathBuf::from("/private/tmp")
31    } else {
32        std::path::PathBuf::from("/tmp")
33    };
34    temporary
35        .join("a3s-box-switches")
36        .join(uid.to_string())
37        .join(&key[..24])
38}
39
40#[cfg(unix)]
41fn cleanup_bridge_socket_dir(home: &std::path::Path, network_name: &str) {
42    let directory = bridge_socket_dir(home, network_name);
43    match std::fs::remove_dir_all(&directory) {
44        Ok(()) => {}
45        Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}
46        Err(error) => tracing::warn!(
47            path = %directory.display(),
48            %error,
49            "Failed to remove bridge switch directory"
50        ),
51    }
52}
53
54/// Platform-agnostic handle to a running network backend process or thread.
55pub trait NetworkBackend: Send + Sync {
56    /// Path to the Unix socket used to communicate with this backend.
57    fn socket_path(&self) -> &std::path::Path;
58    /// Stop the backend and clean up the socket.
59    fn stop(&mut self);
60}
61
62#[cfg(target_os = "macos")]
63impl NetworkBackend for NetProxyManager {
64    fn socket_path(&self) -> &std::path::Path {
65        self.socket_path()
66    }
67
68    fn stop(&mut self) {
69        self.stop();
70    }
71}