2019-08-01 23:03:34 -04:00
|
|
|
//! A proxy that forwards data to another server and forwards that server's
|
|
|
|
|
//! responses back to clients.
|
|
|
|
|
//!
|
|
|
|
|
//! Because the Tokio runtime uses a thread pool, each TCP connection is
|
|
|
|
|
//! processed concurrently with all other TCP connections across multiple
|
|
|
|
|
//! threads.
|
|
|
|
|
//!
|
|
|
|
|
//! You can showcase this by running this in one terminal:
|
|
|
|
|
//!
|
|
|
|
|
//! cargo run --example proxy
|
|
|
|
|
//!
|
|
|
|
|
//! This in another terminal
|
|
|
|
|
//!
|
2025-04-18 10:32:25 -04:00
|
|
|
//! cargo run --example echo-tcp
|
2019-08-01 23:03:34 -04:00
|
|
|
//!
|
|
|
|
|
//! And finally this in another terminal
|
|
|
|
|
//!
|
2025-04-18 10:32:25 -04:00
|
|
|
//! cargo run --example connect-tcp 127.0.0.1:8081
|
2019-08-01 23:03:34 -04:00
|
|
|
//!
|
|
|
|
|
//! This final terminal will connect to our proxy, which will in turn connect to
|
|
|
|
|
//! the echo server, and you'll be able to see data flowing between them.
|
|
|
|
|
|
2019-08-10 00:07:57 +09:00
|
|
|
#![warn(rust_2018_idioms)]
|
2019-08-01 23:03:34 -04:00
|
|
|
|
2023-07-28 18:06:44 +08:00
|
|
|
use tokio::io::copy_bidirectional;
|
2019-11-23 08:24:03 -08:00
|
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
|
|
|
|
|
|
|
|
use std::env;
|
|
|
|
|
use std::error::Error;
|
2019-08-01 23:03:34 -04:00
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
|
async fn main() -> Result<(), Box<dyn Error>> {
|
2019-12-14 09:01:47 +03:00
|
|
|
let listen_addr = env::args()
|
|
|
|
|
.nth(1)
|
|
|
|
|
.unwrap_or_else(|| "127.0.0.1:8081".to_string());
|
|
|
|
|
let server_addr = env::args()
|
|
|
|
|
.nth(2)
|
|
|
|
|
.unwrap_or_else(|| "127.0.0.1:8080".to_string());
|
2019-08-01 23:03:34 -04:00
|
|
|
|
2024-11-18 04:50:58 -08:00
|
|
|
println!("Listening on: {listen_addr}");
|
|
|
|
|
println!("Proxying to: {server_addr}");
|
2019-08-01 23:03:34 -04:00
|
|
|
|
2020-10-08 12:12:56 -07:00
|
|
|
let listener = TcpListener::bind(listen_addr).await?;
|
2019-08-01 23:03:34 -04:00
|
|
|
|
2023-07-28 18:06:44 +08:00
|
|
|
while let Ok((mut inbound, _)) = listener.accept().await {
|
2026-06-23 09:49:33 +02:00
|
|
|
let server_addr = server_addr.clone();
|
2023-07-28 18:06:44 +08:00
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
2026-06-23 09:49:33 +02:00
|
|
|
let mut outbound = match TcpStream::connect(server_addr).await {
|
|
|
|
|
Ok(outbound) => outbound,
|
|
|
|
|
Err(e) => {
|
|
|
|
|
println!("Failed to connect; error={e}");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if let Err(e) = copy_bidirectional(&mut inbound, &mut outbound).await {
|
|
|
|
|
println!("Failed to transfer; error={e}");
|
|
|
|
|
}
|
2019-08-01 23:03:34 -04:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|