diff --git a/crates/bh_agent_server/Cargo.toml b/crates/bh_agent_server/Cargo.toml index c6b0432..4fe1199 100644 --- a/crates/bh_agent_server/Cargo.toml +++ b/crates/bh_agent_server/Cargo.toml @@ -17,3 +17,6 @@ log = "0.4.20" env_logger = { version = "0.10.0", default-features = false, features = ["auto-color", "humantime"] } bimap = "0.6.3" clap = { version = "4.4.11", features = ["derive"] } + +[target.'cfg(not(target_os = "windows"))'.dependencies] +daemonize = "0.5.0" diff --git a/crates/bh_agent_server/src/main.rs b/crates/bh_agent_server/src/main.rs index 70ed864..c3afa66 100644 --- a/crates/bh_agent_server/src/main.rs +++ b/crates/bh_agent_server/src/main.rs @@ -1,4 +1,4 @@ -use std::net::IpAddr; +use std::{any, net::IpAddr}; use clap::Parser; use futures::{future, prelude::*}; @@ -6,6 +6,7 @@ use tarpc::{ server::{self, Channel}, tokio_serde::formats::Json, }; +use tokio::runtime; use bh_agent_common::BhAgentService; use bh_agent_server::BhAgentServer; @@ -13,32 +14,57 @@ use bh_agent_server::BhAgentServer; #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Args { + /// The address to listen on address: IpAddr, + /// The port to listen on port: u16, + #[cfg(not(target_os = "windows"))] + #[arg(short, long, default_value = "false", help = "Daemonize the process")] + daemonize: bool, } -#[tokio::main] -async fn main() -> anyhow::Result<()> { +fn main() -> anyhow::Result<()> { env_logger::init(); - let args = Args::parse(); - let mut listener = tarpc::serde_transport::tcp::listen(&(args.address, args.port), Json::default).await?; + // Setup runtime + let rt = runtime::Builder::new_multi_thread() + .enable_all() + .build() + .unwrap(); + + // Setup listener + let mut listener = rt.block_on(async { + return tarpc::serde_transport::tcp::listen(&(args.address, args.port), Json::default).await; + })?; listener.config_mut().max_frame_length(usize::MAX); - listener - // Ignore accept errors. - .filter_map(|r| future::ready(r.ok())) - .map(server::BaseChannel::with_defaults) - // serve is generated by the service attribute. It takes as input any type implementing - // the generated World trait. - .map(|channel| { - let server = BhAgentServer::new(channel.transport().peer_addr().unwrap()); - channel.execute(server.serve()) - }) - // Max 10 channels. - .buffer_unordered(10) - .for_each(|_| async {}) - .await; + + // Daemonize + #[cfg(not(target_os = "windows"))] + if args.daemonize { + daemonize::Daemonize::new() + .pid_file("/tmp/bh_agent_server.pid") + .start() + .unwrap(); + } + + // Run the listener + rt.block_on(async { + listener + // Ignore accept errors. + .filter_map(|r| future::ready(r.ok())) + .map(server::BaseChannel::with_defaults) + // serve is generated by the service attribute. It takes as input any type implementing + // the generated World trait. + .map(|channel| { + let server = BhAgentServer::new(channel.transport().peer_addr().unwrap()); + channel.execute(server.serve()) + }) + // Max 10 channels. + .buffer_unordered(10) + .for_each(|_| async {}) + .await; + }); Ok(()) }