localtunnel_server/
lib.rs1#[macro_use]
6extern crate lazy_static;
7
8use std::time::Duration;
9use std::{net::SocketAddr, sync::Arc};
10
11use actix_web::{web, App, HttpServer};
12use anyhow::Result;
13use dotenv::dotenv;
14use hyper::{server::conn::http1, service::service_fn};
15use tokio::{net::TcpListener, sync::Mutex, time::timeout};
16
17use crate::api::{api_status, request_endpoint};
18use crate::config::Config;
19use crate::proxy::proxy_handler;
20use crate::state::{ClientManager, State};
21
22mod api;
23mod auth;
24mod config;
25mod error;
26mod proxy;
27mod state;
28
29const CLEANUP_CHECK_INTERVAL: Duration = Duration::from_secs(60);
31
32lazy_static! {
33 static ref CONFIG: Config = {
34 dotenv().ok();
35 envy::from_env::<Config>().unwrap_or_default()
36 };
37}
38
39pub struct ServerConfig {
40 pub domain: String,
41 pub api_port: u16,
42 pub secure: bool,
43 pub max_sockets: u8,
44 pub proxy_port: u16,
45 pub require_auth: bool,
46}
47
48pub async fn start(config: ServerConfig) -> Result<()> {
51 let ServerConfig {
52 domain,
53 api_port,
54 secure,
55 max_sockets,
56 proxy_port,
57 require_auth,
58 } = config;
59 log::info!("Api server listens at {} {}", &domain, api_port);
60 log::info!(
61 "Start proxy server at {} {}, options: {} {}, require auth: {}",
62 &domain,
63 proxy_port,
64 secure,
65 max_sockets,
66 require_auth
67 );
68
69 let manager = Arc::new(Mutex::new(ClientManager::new(max_sockets)));
70 let api_state = web::Data::new(State {
71 manager: manager.clone(),
72 max_sockets,
73 require_auth,
74 secure,
75 domain,
76 });
77
78 let proxy_addr: SocketAddr = ([0, 0, 0, 0], proxy_port).into();
79 let listener = TcpListener::bind(proxy_addr).await?;
80 tokio::spawn(async move {
81 loop {
82 match timeout(CLEANUP_CHECK_INTERVAL, listener.accept()).await {
83 Ok(Ok((stream, _))) => {
84 log::info!("Accepted a new proxy request");
85
86 let proxy_manager = manager.clone();
87 let service = service_fn(move |req| proxy_handler(req, proxy_manager.clone()));
88
89 tokio::spawn(async move {
90 if let Err(err) = http1::Builder::new()
91 .serve_connection(hyper_util::rt::TokioIo::new(stream), service)
92 .with_upgrades()
93 .await
94 {
95 log::error!("Failed to serve connection: {:?}", err);
96 }
97 });
98 }
99 Ok(Err(e)) => log::error!("Failed to accept the request: {:?}", e),
100 Err(_) => {
101 let mut manager = manager.lock().await;
103 manager.cleanup().await;
104 }
105 }
106 }
107 });
108
109 HttpServer::new(move || {
110 App::new()
111 .app_data(api_state.clone())
112 .service(api_status)
113 .service(request_endpoint)
114 })
115 .bind(("0.0.0.0", api_port))?
116 .run()
117 .await?;
118
119 Ok(())
120}