dynamic_tcp_proxy 0.1.0

Dynamic proxy implementation in Rust. This crate is designed to allow you to start a proxy that can be reconfigured at runtime.
Documentation
use std::net::SocketAddr;
use tokio::net::{TcpListener, TcpStream};
use tokio::runtime::Runtime;
use tokio::sync::mpsc::Receiver;
use tokio::task::JoinHandle;

pub(super) fn create_proxy(
    runtime: &Runtime,
    listen_port: u16,
    kill_rx: Receiver<()>,
) -> JoinHandle<()> {
    let addr = SocketAddr::from(([127, 0, 0, 1], listen_port));

    runtime.spawn(async move {
        let listener = TcpListener::bind(addr).await.unwrap();

        let kill_signal = create_kill_signal(kill_rx);
        let mut kill_signal = std::pin::pin!(kill_signal);

        let target_port = super::get_target_port();
        let forward_addr = SocketAddr::from(([127, 0, 0, 1], target_port));

        loop {
            tokio::select! {
                Ok((mut inbound, _addr)) = listener.accept() => {
                    tokio::spawn(async move {
                        match TcpStream::connect(forward_addr).await {
                            Ok(mut outbound) => {
                                let (from_client, from_server) = tokio::io::copy_bidirectional(&mut inbound, &mut outbound).await.unwrap();

                                println!(
                                    "client wrote {} bytes and received {} bytes",
                                    from_client, from_server
                                );
                            }
                            Err(e) => {
                                eprintln!("Failed to connect to forward address: {}", e);
                            }
                        }
                    });
                },

                _ = &mut kill_signal => {
                    eprintln!("Graceful shutdown signal received");
                    break;
                }
            }
        }
        println!("All connections Closed");
    })
}

async fn create_kill_signal(mut kill_rx: Receiver<()>) {
    kill_rx.recv().await.expect("Kill signal issue")
}