From b8aef96f1dbe447bb984cbb836fa7fb902fbc71c Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Sun, 27 Jul 2025 21:59:51 -0400 Subject: [PATCH 1/2] Implement --recv-only This option causes the sending side to not send any data and instead immeditally send an EOF. This can be useful when you are only interested in sending data in one direction. Closes #10 --- src/main.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1de688e..35aa035 100644 --- a/src/main.rs +++ b/src/main.rs @@ -124,6 +124,10 @@ fn parse_alpn(alpn: &str) -> Result> { #[derive(Parser, Debug)] pub struct ListenArgs { + /// Immediately close our sending side, indicating that we will not transmit any data + #[clap(long)] + pub recv_only: bool, + #[clap(flatten)] pub common: CommonArgs, } @@ -157,6 +161,10 @@ pub struct ConnectArgs { /// The node to connect to pub ticket: NodeTicket, + /// Immediately close our sending side, indicating that we will not transmit any data + #[clap(long)] + pub recv_only: bool, + #[clap(flatten)] pub common: CommonArgs, } @@ -323,7 +331,11 @@ async fn listen_stdio(args: ListenArgs) -> Result<()> { snafu::ensure_whatever!(buf == dumbpipe::HANDSHAKE, "invalid handshake"); } tracing::info!("forwarding stdin/stdout to {}", remote_node_id); - forward_bidi(tokio::io::stdin(), tokio::io::stdout(), r, s).await?; + if args.recv_only { + forward_bidi(tokio::io::empty(), tokio::io::stdout(), r, s).await?; + } else { + forward_bidi(tokio::io::stdin(), tokio::io::stdout(), r, s).await?; + } // stop accepting connections after the first successful one break; } @@ -357,7 +369,11 @@ async fn connect_stdio(args: ConnectArgs) -> Result<()> { s.write_all(&dumbpipe::HANDSHAKE).await.e()?; } tracing::info!("forwarding stdin/stdout to {}", remote_node_id); - forward_bidi(tokio::io::stdin(), tokio::io::stdout(), r, s).await?; + if args.recv_only { + forward_bidi(tokio::io::empty(), tokio::io::stdout(), r, s).await?; + } else { + forward_bidi(tokio::io::stdin(), tokio::io::stdout(), r, s).await?; + } tokio::io::stdout().flush().await.e()?; Ok(()) } From 60e11630d2e1bb190c665008c04cec2ff9a1f273 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Wed, 30 Jul 2025 23:32:38 -0400 Subject: [PATCH 2/2] Update tracing messages when --recv-only is used --- src/main.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 35aa035..b19ab5e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -330,10 +330,11 @@ async fn listen_stdio(args: ListenArgs) -> Result<()> { r.read_exact(&mut buf).await.e()?; snafu::ensure_whatever!(buf == dumbpipe::HANDSHAKE, "invalid handshake"); } - tracing::info!("forwarding stdin/stdout to {}", remote_node_id); if args.recv_only { + tracing::info!("forwarding stdout to {} (ignoring stdin)", remote_node_id); forward_bidi(tokio::io::empty(), tokio::io::stdout(), r, s).await?; } else { + tracing::info!("forwarding stdin/stdout to {}", remote_node_id); forward_bidi(tokio::io::stdin(), tokio::io::stdout(), r, s).await?; } // stop accepting connections after the first successful one @@ -368,10 +369,11 @@ async fn connect_stdio(args: ConnectArgs) -> Result<()> { // on stdin, so just write a handshake. s.write_all(&dumbpipe::HANDSHAKE).await.e()?; } - tracing::info!("forwarding stdin/stdout to {}", remote_node_id); if args.recv_only { + tracing::info!("forwarding stdout to {} (ignoring stdin)", remote_node_id); forward_bidi(tokio::io::empty(), tokio::io::stdout(), r, s).await?; } else { + tracing::info!("forwarding stdin/stdout to {}", remote_node_id); forward_bidi(tokio::io::stdin(), tokio::io::stdout(), r, s).await?; } tokio::io::stdout().flush().await.e()?;