diff --git a/Cargo.toml b/Cargo.toml index 6b516f2..6cf2ec4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fwd" -version = "0.9" +version = "0.8.1" edition = "2021" license = "MIT" description = "Automatically forward ports to a remote server over ssh" @@ -22,7 +22,7 @@ indoc = "1" log = { version = "0.4", features = ["std"] } open = "3" thiserror = "1.0" -tokio = { version = "1", features = ["io-std", "io-util", "macros", "net", "process", "rt", "rt-multi-thread", "fs"] } +tokio = { version = "1", features = ["io-std", "io-util", "macros", "net", "process", "rt", "rt-multi-thread"] } tokio-stream = "0.1" toml = "0.5" tui = "0.19" diff --git a/src/bin/fwd-browse.rs b/src/bin/fwd-browse.rs index 9899597..bbebcdf 100644 --- a/src/bin/fwd-browse.rs +++ b/src/bin/fwd-browse.rs @@ -9,10 +9,5 @@ async fn main() { std::process::exit(1); } - let url = &args[1]; - if let Err(e) = fwd::browse_url(url).await { - eprintln!("Unable to open {url}"); - eprintln!("{}", e); - std::process::exit(1); - } + fwd::browse_url(&args[1]).await; } diff --git a/src/reverse/unix.rs b/src/browse/browse_unix.rs similarity index 90% rename from src/reverse/unix.rs rename to src/browse/browse_unix.rs index 92025ce..54cca9c 100644 --- a/src/reverse/unix.rs +++ b/src/browse/browse_unix.rs @@ -1,15 +1,14 @@ -// The reverse client connects to the server via a local connection to send -// commands back to the client. +use crate::message::{Message, MessageReader, MessageWriter}; use anyhow::{bail, Context, Result}; use log::warn; use std::os::unix::fs::DirBuilderExt; use std::path::PathBuf; use tokio::net::{UnixListener, UnixStream}; use tokio::sync::mpsc; +use users; +use xdg; -use crate::message::{Message, MessageReader, MessageWriter}; - -pub async fn send_reverse_message(message: Message) -> Result<()> { +pub async fn browse_url_impl(url: &String) -> Result<()> { let path = socket_path().context("Error getting socket path")?; let stream = match UnixStream::connect(&path).await { Ok(s) => s, @@ -19,48 +18,20 @@ pub async fn send_reverse_message(message: Message) -> Result<()> { }; let mut writer = MessageWriter::new(stream); writer - .write(message) + .write(Message::Browse(url.clone())) .await .context("Error sending browse message")?; Ok(()) } -fn socket_directory() -> Result { - let base_directories = xdg::BaseDirectories::new() - .context("Error creating BaseDirectories")?; - match base_directories.place_runtime_file("fwd") { - Ok(path) => Ok(path), - Err(_) => { - let mut path = std::env::temp_dir(); - path.push(format!("fwd{}", users::get_current_uid())); - Ok(path) - } - } -} - -pub fn socket_path() -> Result { - let mut socket_path = socket_directory()?; - - std::fs::DirBuilder::new() - .recursive(true) - .mode(0o700) - .create(&socket_path) - .context("Error creating socket directory")?; - - // TODO: check mode of directory - - socket_path.push("browser"); - Ok(socket_path) -} - -pub async fn handle_reverse_connections( +pub async fn handle_browser_open_impl( messages: mpsc::Sender, ) -> Result<()> { let path = socket_path().context("Error getting socket path")?; - handle_reverse_connections_with_path(messages, path).await + handle_browser_open_with_path(messages, path).await } -async fn handle_reverse_connections_with_path( +async fn handle_browser_open_with_path( messages: mpsc::Sender, path: PathBuf, ) -> Result<()> { @@ -82,6 +53,34 @@ async fn handle_reverse_connections_with_path( } } +pub fn socket_path() -> Result { + let mut socket_path = socket_directory()?; + + std::fs::DirBuilder::new() + .recursive(true) + .mode(0o700) + .create(&socket_path) + .context("Error creating socket directory")?; + + // TODO: check mode of directory + + socket_path.push("browser"); + Ok(socket_path) +} + +fn socket_directory() -> Result { + let base_directories = xdg::BaseDirectories::new() + .context("Error creating BaseDirectories")?; + match base_directories.place_runtime_file("fwd") { + Ok(path) => Ok(path), + Err(_) => { + let mut path = std::env::temp_dir(); + path.push(format!("fwd{}", users::get_current_uid())); + Ok(path) + } + } +} + async fn handle_connection( socket: UnixStream, sender: mpsc::Sender, @@ -120,7 +119,7 @@ mod tests { let path_override = path.clone(); tokio::spawn(async move { - handle_reverse_connections_with_path(sender, path_override) + handle_browser_open_with_path(sender, path_override) .await .expect("Error in server!"); }); diff --git a/src/browse/mod.rs b/src/browse/mod.rs new file mode 100644 index 0000000..cf83858 --- /dev/null +++ b/src/browse/mod.rs @@ -0,0 +1,40 @@ +use crate::message::Message; +use anyhow::Result; +use tokio::sync::mpsc; + +#[cfg(target_family = "unix")] +mod browse_unix; + +#[cfg(target_family = "unix")] +use browse_unix::{browse_url_impl, handle_browser_open_impl}; + +#[inline] +pub async fn browse_url(url: &String) { + if let Err(e) = browse_url_impl(url).await { + eprintln!("Unable to open {url}"); + eprintln!("{}", e); + std::process::exit(1); + } +} + +#[cfg(not(target_family = "unix"))] +pub async fn browse_url_impl(_url: &String) -> Result<()> { + use anyhow::anyhow; + Err(anyhow!( + "Opening a browser is not supported on this platform" + )) +} + +#[inline] +pub async fn handle_browser_open( + messages: mpsc::Sender, +) -> Result<()> { + handle_browser_open_impl(messages).await +} + +#[cfg(not(target_family = "unix"))] +async fn handle_browser_open_impl( + _messages: mpsc::Sender, +) -> Result<()> { + std::future::pending().await +} diff --git a/src/lib.rs b/src/lib.rs index 6143ba3..5eaba0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,8 @@ +mod browse; mod client; mod message; -mod reverse; mod server; +pub use browse::browse_url; pub use client::run_client; -pub use reverse::browse_url; pub use server::run_server; diff --git a/src/main.rs b/src/main.rs index cf033ba..667ff1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ const VERSION: &str = env!("CARGO_PKG_VERSION"); fn usage() { println!(indoc! {" -usage: fwd [options] ( | browse | clip []) +usage: fwd [options] ( | browse ) To connect a client to a server that has an `fwd` installed in its path, run `fwd ` on the client, where is the name of the server to @@ -60,13 +60,9 @@ fn parse_args(args: Vec) -> Args { } else { Args::Error } - } else if rest.len() > 1 { - if rest[0] == "browse" { - if rest.len() == 2 { - Args::Browse(rest[1].to_string()) - } else { - Args::Error - } + } else if rest.len() > 1 && rest[0] == "browse" { + if rest.len() == 2 { + Args::Browse(rest[1].to_string()) } else { Args::Error } @@ -77,14 +73,6 @@ fn parse_args(args: Vec) -> Args { } } -async fn browse_url(url: &str) { - if let Err(e) = fwd::browse_url(&url).await { - eprintln!("Unable to open {url}"); - eprintln!("{}", e); - std::process::exit(1); - } -} - #[tokio::main] async fn main() { match parse_args(std::env::args().collect()) { @@ -98,7 +86,7 @@ async fn main() { fwd::run_server().await; } Args::Browse(url) => { - browse_url(&url).await; + fwd::browse_url(&url).await; } Args::Client(server, sudo) => { fwd::run_client(&server, sudo).await; diff --git a/src/reverse.rs b/src/reverse.rs deleted file mode 100644 index bca8c1c..0000000 --- a/src/reverse.rs +++ /dev/null @@ -1,29 +0,0 @@ -use anyhow::Result; - -#[cfg(target_family = "unix")] -mod unix; - -#[cfg(target_family = "unix")] -pub use unix::{handle_reverse_connections, send_reverse_message}; - -use crate::message::Message; - -#[cfg(not(target_family = "unix"))] -pub async fn send_reverse_message(_message: Message) -> Result<()> { - use anyhow::anyhow; - Err(anyhow!( - "Server-side operations are not supported on this platform" - )) -} - -#[cfg(not(target_family = "unix"))] -pub async fn handle_reverse_connections( - _messages: mpsc::Sender, -) -> Result<()> { - std::future::pending().await -} - -#[inline] -pub async fn browse_url(url: &str) -> Result<()> { - send_reverse_message(Message::Browse(url.to_string())).await -} diff --git a/src/server/mod.rs b/src/server/mod.rs index 86e1ef7..1b1f1b2 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,5 +1,5 @@ +use crate::browse::handle_browser_open; use crate::message::{Message, MessageReader, MessageWriter}; -use crate::reverse::handle_reverse_connections; use anyhow::Result; use log::{error, warn}; use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufReader, BufWriter}; @@ -13,7 +13,7 @@ mod refresh; async fn write_driver( messages: &mut mpsc::Receiver, writer: &mut MessageWriter, -) { +) -> () { while let Some(m) = messages.recv().await { writer.write(m).await.expect("Failed to write the message") } @@ -77,7 +77,7 @@ async fn server_main< tokio::select! { _ = write_driver(&mut receiver, &mut writer) => Ok(()), r = server_loop(&mut reader, &mut sender) => r, - r = handle_reverse_connections(browse_sender) => r, + r = handle_browser_open(browse_sender) => r, } } diff --git a/src/server/refresh.rs b/src/server/refresh.rs index a62dfa7..e21cf6f 100644 --- a/src/server/refresh.rs +++ b/src/server/refresh.rs @@ -18,15 +18,19 @@ pub fn get_entries() -> Result> { // error we encounter as it probably means we have no access to that // process or something. let mut map: HashMap = HashMap::new(); - for process in all_procs.flatten() { - if !process.is_alive() { - continue; // Ignore zombies. - } + for p in all_procs { + if let Ok(process) = p { + if !process.is_alive() { + continue; // Ignore zombies. + } - if let (Ok(fds), Ok(cmd)) = (process.fd(), process.cmdline()) { - for fd in fds.flatten() { - if let FDTarget::Socket(inode) = fd.target { - map.insert(inode, cmd.join(" ")); + if let (Ok(fds), Ok(cmd)) = (process.fd(), process.cmdline()) { + for fd in fds { + if let Ok(fd) = fd { + if let FDTarget::Socket(inode) = fd.target { + map.insert(inode, cmd.join(" ")); + } + } } } }