diff --git a/Cargo.lock b/Cargo.lock index 172ca06..4b3ad37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -845,6 +845,24 @@ dependencies = [ "tokio-tungstenite", ] +[[package]] +name = "kble-tcp" +version = "0.3.0" +dependencies = [ + "anyhow", + "bytes", + "clap", + "futures", + "kble-socket", + "notalawyer", + "notalawyer-build", + "notalawyer-clap", + "tokio", + "tokio-util", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lazy_static" version = "1.4.0" diff --git a/Cargo.toml b/Cargo.toml index 643787e..6dab281 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ "kble-socket", "kble-c2a", "kble-eb90", + "kble-tcp", ] [workspace.dependencies] diff --git a/kble-tcp/Cargo.toml b/kble-tcp/Cargo.toml new file mode 100644 index 0000000..8d9e5fe --- /dev/null +++ b/kble-tcp/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "kble-tcp" +version.workspace = true +repository.workspace = true +license.workspace = true +edition.workspace = true +readme.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[build-dependencies] +notalawyer-build.workspace = true + +[dependencies] +anyhow.workspace = true +futures.workspace = true +tokio = { workspace = true, features = ["full"] } +kble-socket = { workspace = true, features = ["stdio", "tungstenite"] } +tokio-util.workspace = true +bytes.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +clap.workspace = true +notalawyer.workspace = true +notalawyer-clap.workspace = true diff --git a/kble-tcp/src/main.rs b/kble-tcp/src/main.rs new file mode 100644 index 0000000..361ddd9 --- /dev/null +++ b/kble-tcp/src/main.rs @@ -0,0 +1,55 @@ +use std::net::SocketAddr; + +use anyhow::Result; +use clap::Parser; +use futures::{SinkExt, StreamExt}; +use tokio::io::{AsyncReadExt, AsyncWriteExt}; +use tokio::net::TcpStream; +use tracing_subscriber::{prelude::*, EnvFilter}; + +#[derive(Debug, Parser)] +#[clap(author, version, about, long_about = None)] +struct Args { + addr: SocketAddr, +} + +#[tokio::main] +async fn main() -> Result<()> { + tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .with_ansi(false) + .with_writer(std::io::stderr), + ) + .with(EnvFilter::from_default_env()) + .init(); + let args = Args::parse(); + + let tcp_stream = TcpStream::connect(args.addr).await?; + let (mut tcp_upstream, mut tcp_downstream) = tokio::io::split(tcp_stream); + let (mut tx, mut rx) = kble_socket::from_stdio().await; + let to_tcp = async { + while let Some(body) = rx.next().await { + let body = body?; + tcp_downstream.write_all(&body).await?; + } + anyhow::Ok(()) + }; + let from_tcp = async { + let mut buffer = [0; 8192]; + loop { + match tcp_upstream.read(&mut buffer).await? { + 0 => break, + n => { + tx.send(buffer[..n].to_vec().into()).await?; + } + } + } + anyhow::Ok(()) + }; + + tokio::select! { + _ = to_tcp => Ok(()), + _ = from_tcp => Ok(()) + } +}