lighty_core/
hosts.rs

1use std::env;
2use std::time::Duration;
3use once_cell::sync::Lazy;
4use reqwest::Client;
5use tokio::fs;
6use thiserror::Error;
7
8/// User-Agent global pour ton launcher
9static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
10
11/// HTTP client unique et optimisé
12pub static HTTP_CLIENT: Lazy<Client> = Lazy::new(|| {
13    Client::builder()
14        // Connection pooling - balance between performance and OS limits
15        .pool_max_idle_per_host(100)
16        .pool_idle_timeout(Some(Duration::from_secs(90)))
17
18        // HTTP/2 optimisations
19        .http2_initial_stream_window_size(Some(2 * 1024 * 1024))
20        .http2_initial_connection_window_size(Some(4 * 1024 * 1024))
21        .http2_adaptive_window(true)
22        .http2_max_frame_size(Some(16 * 1024))
23
24        // TCP optimisations
25        .tcp_keepalive(Some(Duration::from_secs(60)))
26        .tcp_nodelay(true)
27
28        // Timeouts - prevent stuck connections
29        .timeout(Duration::from_secs(60))
30        .connect_timeout(Duration::from_secs(5))
31
32        // Compression
33        .zstd(true)
34        .gzip(true)
35        .brotli(true)
36
37        .build()
38        .expect("Failed to build HTTP client with default configuration - this should never fail")
39});
40
41
42/// Chemin du fichier hosts (dépend de l'OS)
43#[cfg(target_os = "windows")]
44const HOSTS_PATH: &str = "System32\\drivers\\etc\\hosts";
45
46#[cfg(not(target_os = "windows"))]
47const HOSTS_PATH: &str = "etc/hosts";
48
49/// Domaines critiques à vérifier
50const HOSTS: [&str; 3] = [
51    "mojang.com",
52    "minecraft.net",
53    "lightylauncher.fr",
54];
55
56/// Erreurs possibles liées au fichier hosts
57#[derive(Debug, Error)]
58pub enum HostsError {
59    #[error("Failed to read hosts file at {0}")]
60    HostsReadError(String),
61
62    #[error("Hosts file contains blocked entries: {0}")]
63    HostsBlocked(String),
64
65    #[error("I/O error: {0}")]
66    IoError(#[from] std::io::Error),
67}
68
69pub type HostsResult<T> = std::result::Result<T, HostsError>;
70
71/// Vérifie si le fichier hosts a été modifié pour bloquer l'auth Mojang
72pub async fn check_hosts_file() -> HostsResult<()> {
73    let hosts_path = if cfg!(target_os = "windows") {
74        let system_drive = env::var("SystemDrive").unwrap_or("C:".to_string());
75        format!("{}\\{}", system_drive, HOSTS_PATH)
76    } else {
77        format!("/{}", HOSTS_PATH)
78    };
79
80    if !fs::try_exists(&hosts_path).await? {
81        return Ok(());
82    }
83
84    let hosts_file = fs::read_to_string(&hosts_path)
85        .await
86        .map_err(|_| HostsError::HostsReadError(hosts_path.clone()))?;
87
88    let flagged_entries: Vec<_> = hosts_file
89        .lines()
90        .filter(|line| !line.trim_start().starts_with('#'))
91        .flat_map(|line| {
92            let mut parts = line.split_whitespace();
93            let _ip = parts.next();
94            parts.filter(|domain| HOSTS.iter().any(|&entry| domain.contains(entry)))
95        })
96        .map(|s| s.to_string())
97        .collect();
98
99    if !flagged_entries.is_empty() {
100        return Err(HostsError::HostsBlocked(flagged_entries.join("\n")));
101    }
102
103    Ok(())
104}