/
pushamp
/
PACman
Обзор
Документация
Войти
/
pushamp
/
PACman
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
src/pac_server.rs
101 строка
3 KB
Dmitry Zhiltsov
feat(core): Init commit
19 фев 2026, 18:01
19 фев 2026, 18:01
1fadda9
Код
Авторство
О чём код?
use crate::settings::SharedConfig; use std::sync::atomic::{AtomicU16, Ordering}; use std::sync::{Arc, Mutex}; static ACTUAL_PORT: AtomicU16 = AtomicU16::new(0); static CURRENT_SERVER: Mutex<Option<Arc<tiny_http::Server>>> = Mutex::new(None); pub fn actual_port() -> u16 { ACTUAL_PORT.load(Ordering::Relaxed) } fn bind_server(base_port: u16) -> Option<(tiny_http::Server, u16)> { for offset in 0..=10 { let port = base_port + offset; match tiny_http::Server::http(format!("{}:{port}", crate::PAC_HOST)) { Ok(s) => return Some((s, port)), Err(e) => { if offset == 10 { crate::logging::log_error(&format!( "Failed to bind HTTP server after 10 attempts: {e}" )); } } } } None } fn spawn_server_thread(server: Arc<tiny_http::Server>, config: SharedConfig) { std::thread::Builder::new() .name("pac-server".into()) .spawn(move || { loop { let request = match server.recv() { Ok(r) => r, Err(_) => break, }; if request.url() == crate::PAC_PATH { let pac = config.read().unwrap().pac_content.clone(); let response = tiny_http::Response::from_string(pac).with_header( tiny_http::Header::from_bytes( b"Content-Type" as &[u8], b"application/x-ns-proxy-autoconfig" as &[u8], ) .unwrap(), ); let _ = request.respond(response); } else { let response = tiny_http::Response::from_string("Not Found") .with_status_code(tiny_http::StatusCode(404)); let _ = request.respond(response); } } }) .expect("Failed to spawn PAC server thread"); } pub fn start_pac_server(config: SharedConfig) -> u16 { let base_port = config.read().unwrap().http_port; let (server, port) = match bind_server(base_port) { Some(pair) => pair, None => return 0, }; let server = Arc::new(server); ACTUAL_PORT.store(port, Ordering::Relaxed); *CURRENT_SERVER.lock().unwrap() = Some(server.clone()); crate::logging::log_info(&format!("PAC server listening on {}:{port}", crate::PAC_HOST)); spawn_server_thread(server, config); port } /// Restart PAC server on new port. Returns the new actual port (0 on failure). pub fn restart_pac_server(config: SharedConfig) -> u16 { // Stop the old server — unblock causes recv() to return Err, breaking the loop if let Some(old_server) = CURRENT_SERVER.lock().unwrap().take() { old_server.unblock(); } let base_port = config.read().unwrap().http_port; let (server, port) = match bind_server(base_port) { Some(pair) => pair, None => return 0, }; let server = Arc::new(server); ACTUAL_PORT.store(port, Ordering::Relaxed); *CURRENT_SERVER.lock().unwrap() = Some(server.clone()); crate::logging::log_info(&format!("PAC server restarted on {}:{port}", crate::PAC_HOST)); spawn_server_thread(server, config); port }