mirror of
https://github.com/danbulant/ctf-tcp-server
synced 2026-05-24 12:22:02 +00:00
Initial commit
This commit is contained in:
parent
57721d6a31
commit
03bbbbddc4
3 changed files with 76 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/target
|
||||||
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "tcp-spawner"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
tokio-stream = "0.1"
|
||||||
|
os_pipe = "1.1.4"
|
||||||
|
tokio-util = { version = "0.7.8", features = ["compat"] }
|
||||||
|
futures-util = { version = "0.3.28", features = ["io"] }
|
||||||
62
src/main.rs
Normal file
62
src/main.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
use std::env::args;
|
||||||
|
use std::net::TcpListener;
|
||||||
|
use tokio::process::Command;
|
||||||
|
use tokio::io;
|
||||||
|
use futures_util::io::AllowStdIo;
|
||||||
|
|
||||||
|
|
||||||
|
fn build_command_from_args(args: &[String]) -> Command {
|
||||||
|
let mut command = Command::new(args.get(0).unwrap());
|
||||||
|
|
||||||
|
command.stdout(std::process::Stdio::piped());
|
||||||
|
command.stderr(std::process::Stdio::piped());
|
||||||
|
|
||||||
|
for arg in args.iter().skip(1) {
|
||||||
|
command.arg(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
command
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
/// This is a simple TCP server that will spawn a process for each connection
|
||||||
|
/// and pipe the connection to the process stdin and stdout.
|
||||||
|
/// The first argument is the port to listen on.
|
||||||
|
/// The second argument (and later arguments) is the command to run.
|
||||||
|
async fn main() -> io::Result<()> {
|
||||||
|
let args = args().collect::<Vec<String>>();
|
||||||
|
let listener = TcpListener::bind(args.get(1).unwrap())?;
|
||||||
|
let listener = tokio::net::TcpListener::from_std(listener)?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let (mut stream, _) = listener.accept().await.unwrap();
|
||||||
|
let mut command = build_command_from_args(args.get(2..).unwrap());
|
||||||
|
|
||||||
|
println!("Got connection from {:?}", stream.peer_addr());
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let (mut stream_reader, mut stream_writer) = stream.split();
|
||||||
|
|
||||||
|
let (child_reader, child_writer) = os_pipe::pipe().unwrap();
|
||||||
|
let writer_clone = child_writer.try_clone().unwrap();
|
||||||
|
command.stdout(child_writer);
|
||||||
|
command.stderr(writer_clone);
|
||||||
|
|
||||||
|
let child_reader = AllowStdIo::new(child_reader);
|
||||||
|
let mut child_reader = tokio_util::compat::FuturesAsyncReadCompatExt::compat(child_reader);
|
||||||
|
|
||||||
|
let mut child = command.spawn().unwrap();
|
||||||
|
|
||||||
|
let mut stdin = child.stdin.take().unwrap();
|
||||||
|
|
||||||
|
let copy_stdin = io::copy(&mut stream_reader, &mut stdin);
|
||||||
|
let copy_output = io::copy(&mut child_reader, &mut stream_writer);
|
||||||
|
|
||||||
|
drop(command);
|
||||||
|
|
||||||
|
tokio::try_join!(copy_stdin, copy_output).unwrap();
|
||||||
|
|
||||||
|
child.wait().await.unwrap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue