1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
use async_std::os::unix::net::UnixListener;
use std::error::Error;
use std::fs::Permissions;
use std::path::PathBuf;
use std::os::unix::fs::PermissionsExt;
use tempfile::TempDir;

const TEMP_DIR_PREFIX: &'static str = "rect-socket.";
const TEMP_DIR_MODE: u32 = 0o700;

pub struct SocketPool {
    pub mount_args: Vec<String>,
    dir: TempDir,
}

pub struct Socket {
    pub socket_path: PathBuf,
    pub listener: UnixListener,
}

impl SocketPool {
    pub fn new() -> Result<SocketPool, Box<dyn Error>> {
        let dir = tempfile::Builder::new().prefix(TEMP_DIR_PREFIX).tempdir()?;
        std::fs::set_permissions(&dir, Permissions::from_mode(TEMP_DIR_MODE))?;
        Ok(SocketPool {
            mount_args: vec![],
            dir
        })
    }

    pub async fn bind(&mut self, path_in_container: &str) -> Result<Socket, Box<dyn Error>> {
        let arbitrary_id = self.mount_args.len().to_string();
        let socket_path = self.dir.path().join(arbitrary_id);
        let socket_path_str = socket_path.to_str().unwrap();
        self.mount_args.push(format!("-v={}:{}", socket_path_str, path_in_container));
        let listener = UnixListener::bind(&socket_path).await?;
        Ok(Socket{ listener, socket_path })
    }
}