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
|
|
|
|
|
//!
|
|
|
|
|
//! cargo run --example echo
|
|
|
|
|
//!
|
|
|
|
|
//! And finally this in another terminal
|
|
|
|
|
//!
|
|
|
|
|
//! cargo run --example connect 127.0.0.1:8081
|
|
|
|
|
//!
|
|
|
|
|
//! 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 futures::FutureExt;
|
|
|
|
|
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
|
|
|
|
|
|
|
|
println!("Listening on: {}", listen_addr);
|
|
|
|
|
println!("Proxying to: {}", server_addr);
|
|
|
|
|
|
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 {
|
|
|
|
|
let mut outbound = TcpStream::connect(server_addr.clone()).await?;
|
|
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
copy_bidirectional(&mut inbound, &mut outbound)
|
|
|
|
|
.map(|r| {
|
|
|
|
|
if let Err(e) = r {
|
|
|
|
|
println!("Failed to transfer; error={}", e);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.await
|
2019-08-01 23:03:34 -04:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|