1#![warn(rust_2018_idioms)]
2#![warn(clippy::all)]
3
4pub mod buffer_pool;
5pub mod config;
6pub mod connection;
7pub mod copy_pump;
8pub mod handshake;
9pub mod helpers;
10pub mod request;
11
12use tokio::net::TcpListener;
13use tracing::{info, warn};
14
15use crate::buffer_pool::BufferPool;
16use crate::config::Config;
17use crate::connection::Connection;
18use crate::helpers::{Helpers, Res};
19
20pub async fn run(config: Config) -> Res<()> {
22 let listen_ip = config.listen_ip()?;
23
24 info!("Version: {}", env!("CARGO_PKG_VERSION"));
25 info!("Listen IP: {}", listen_ip);
26 info!("Endpoint IP: {}", config.endpoint_ip()?);
27 info!("Port: {}", config.port);
28 info!("Buffer Size: {}", config.buffer_size);
29 info!("Read Timeout: {}", config.read_timeout);
30 info!("Accept CIDR: {}", config.accept_cidr);
31
32 let listener = TcpListener::bind(format!("{}:{}", listen_ip, config.port)).await?;
33 info!("Listening on tcp://{}:{} ...", listen_ip, config.port);
34
35 serve(listener, config).await
36}
37
38pub async fn serve(listener: TcpListener, config: Config) -> Res<()> {
41 let endpoint_ip = config.endpoint_ip()?;
42 let cidr = Helpers::parse_cidr(&config.accept_cidr)?;
43 let cidr_is_trivial = cidr.is_trivial();
44
45 let mut pool = BufferPool::new(2 * config.buffer_size);
47
48 loop {
49 let (stream, _) = listener.accept().await?;
50 let remote_ip = stream.peer_addr()?.ip();
51
52 if !cidr_is_trivial && !Helpers::is_ip_in_cidr(&remote_ip, &cidr)? {
54 warn!("Request from {} does not match {}: dropping connection.", remote_ip, config.accept_cidr);
55 drop(stream);
56 continue;
57 }
58
59 Connection::from(stream, endpoint_ip.clone(), pool.lease(), config.read_timeout).handle();
60 }
61}