87 lines
2.6 KiB
Rust
87 lines
2.6 KiB
Rust
use std::env;
|
|
use std::fs;
|
|
use std::os::unix::fs::PermissionsExt;
|
|
use std::path::PathBuf;
|
|
use std::process;
|
|
|
|
use bxcore::instance;
|
|
use inferproxy::{Limits, serve};
|
|
|
|
fn main() {
|
|
// `args_os`, because `args` panics on an argument that is not UTF-8.
|
|
let args: Vec<String> = match env::args_os().map(|a| a.into_string()).collect() {
|
|
Ok(args) => args,
|
|
Err(_) => usage(),
|
|
};
|
|
let mut listen: Option<String> = None;
|
|
let mut upstream: Option<String> = None;
|
|
let mut i = 1;
|
|
while i < args.len() {
|
|
match args[i].as_str() {
|
|
"--listen" => {
|
|
i += 1;
|
|
listen = args.get(i).cloned();
|
|
}
|
|
"--upstream" => {
|
|
i += 1;
|
|
upstream = args.get(i).cloned();
|
|
}
|
|
_ => usage(),
|
|
}
|
|
i += 1;
|
|
}
|
|
let listen = match listen {
|
|
Some(p) => p,
|
|
None => usage(),
|
|
};
|
|
let upstream = match upstream {
|
|
Some(p) => p,
|
|
None => usage(),
|
|
};
|
|
|
|
let path: PathBuf = listen.into();
|
|
// One inferproxy per socket (M5b spec, section 9a): the lock beside the socket comes before
|
|
// the stale socket is removed, so a second copy never takes the socket of the one that runs.
|
|
// Held until the process ends; `process::exit` leaves it to the system to release.
|
|
let mut lock_path = path.clone().into_os_string();
|
|
lock_path.push(".lock");
|
|
let lock_path = PathBuf::from(lock_path);
|
|
let _instance = match instance::lock(&lock_path) {
|
|
Ok(held) => held,
|
|
Err(e) => {
|
|
eprintln!("{}", e.line("inferproxy", &lock_path));
|
|
process::exit(1);
|
|
}
|
|
};
|
|
match fs::remove_file(&path) {
|
|
Ok(()) => {}
|
|
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
|
|
Err(e) => {
|
|
eprintln!("inferproxy: cannot remove stale socket: {e}");
|
|
process::exit(1);
|
|
}
|
|
}
|
|
let listener = match std::os::unix::net::UnixListener::bind(&path) {
|
|
Ok(l) => l,
|
|
Err(e) => {
|
|
eprintln!("inferproxy: bind failed: {e}");
|
|
process::exit(1);
|
|
}
|
|
};
|
|
let perms = fs::Permissions::from_mode(0o600);
|
|
if let Err(e) = fs::set_permissions(&path, perms) {
|
|
eprintln!("inferproxy: chmod failed: {e}");
|
|
process::exit(1);
|
|
}
|
|
eprintln!("inferproxy: {} -> {}", path.display(), upstream);
|
|
if let Err(e) = serve(listener, upstream, Limits::default()) {
|
|
eprintln!("inferproxy: {e}");
|
|
process::exit(1);
|
|
}
|
|
}
|
|
|
|
fn usage() -> ! {
|
|
eprintln!("usage: inferproxy --listen <socket path> --upstream <host:port>");
|
|
process::exit(2);
|
|
}
|