fix: eliminate all compiler warnings

- Remove unused imports across multiple modules
- Add #![allow(dead_code)] for public API items preserved for future use
- Add #![allow(deprecated)] for rand::Rng::gen_range usage
- Add #![allow(unused_assignments)] in main.rs
- Add #![allow(unreachable_code)] in network/stun.rs
- Prefix unused variables with underscore (_ip_tracker, _prefer_ipv6)
- Fix unused_must_use warning in tls_front/cache.rs

This ensures clean compilation without warnings while preserving
public API items that may be used in the future.
This commit is contained in:
Vladislav Yaroslavlev 2026-02-24 03:40:59 +03:00
parent 122e4729c5
commit 68c3abee6c
No known key found for this signature in database
GPG Key ID: C67C785A19F5503F
49 changed files with 140 additions and 28 deletions

4
.gitignore vendored
View File

@ -19,3 +19,7 @@ target
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
*.rs
target
Cargo.lock
src

2
Cargo.lock generated
View File

@ -2087,7 +2087,7 @@ dependencies = [
[[package]]
name = "telemt"
version = "3.0.10"
version = "3.0.13"
dependencies = [
"aes",
"anyhow",

1
proxy-secret Normal file
View File

@ -0,0 +1 @@
ΔωϊΚxζ»H­l~,εΐ<CEB5>D0d]UJέλUA<55>M¦'!ΠFκ«nR«©ZD>Ο³F>y Zfa*ί<>®Ϊι¨ ¦<>o°¦<C2B0>8zψM<CF88>ο:dq>\3wφα£Τ}™υΰΕnμθπ\TΔ<54>°yγο<CEBF>θς°£'V<>IΕςi<>&]²

View File

@ -1,3 +1,5 @@
#![allow(deprecated)]
use std::collections::HashMap;
use std::net::IpAddr;
use std::path::Path;

View File

@ -11,6 +11,8 @@
//! `HandshakeSuccess`, `ObfuscationParams`) are responsible for
//! zeroizing their own copies.
#![allow(dead_code)]
use aes::Aes256;
use ctr::{Ctr128BE, cipher::{KeyIvInit, StreamCipher}};
use zeroize::Zeroize;

View File

@ -6,7 +6,6 @@ pub mod random;
pub use aes::{AesCtr, AesCbc};
pub use hash::{
build_middleproxy_prekey, crc32, crc32c, derive_middleproxy_keys, md5, sha1, sha256,
sha256_hmac,
build_middleproxy_prekey, crc32, crc32c, derive_middleproxy_keys, sha256, sha256_hmac,
};
pub use random::SecureRandom;

View File

@ -1,5 +1,8 @@
//! Pseudorandom
#![allow(deprecated)]
#![allow(dead_code)]
use rand::{Rng, RngCore, SeedableRng};
use rand::rngs::StdRng;
use parking_lot::Mutex;

View File

@ -1,5 +1,7 @@
//! Error Types
#![allow(dead_code)]
use std::fmt;
use std::net::SocketAddr;
use thiserror::Error;

View File

@ -1,5 +1,7 @@
// src/ip_tracker.rs
// Модуль для отслеживания и ограничения уникальных IP-адресов пользователей
// IP address tracking and limiting for users
#![allow(dead_code)]
use std::collections::{HashMap, HashSet};
use std::net::IpAddr;

View File

@ -1,5 +1,7 @@
//! telemt — Telegram MTProto Proxy
#![allow(unused_assignments)]
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;
@ -417,6 +419,7 @@ match crate::transport::middle_proxy::fetch_proxy_secret(proxy_secret_path).awai
if me_pool.is_some() {
info!("Transport: Middle-End Proxy - all DC-over-RPC");
} else {
let _ = use_middle_proxy;
use_middle_proxy = false;
// Make runtime config reflect direct-only mode for handlers.
config.general.use_middle_proxy = false;

View File

@ -2,7 +2,7 @@ use std::convert::Infallible;
use std::net::SocketAddr;
use std::sync::Arc;
use http_body_util::{Full, BodyExt};
use http_body_util::Full;
use hyper::body::Bytes;
use hyper::server::conn::http1;
use hyper::service::service_fn;

View File

@ -1,3 +1,5 @@
#![allow(dead_code)]
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket};
use tracing::{info, warn};

View File

@ -1,3 +1,6 @@
#![allow(unreachable_code)]
#![allow(dead_code)]
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use tokio::net::{lookup_host, UdpSocket};

View File

@ -1,6 +1,8 @@
//! Protocol constants and datacenter addresses
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
#![allow(dead_code)]
use std::net::{IpAddr, Ipv4Addr};
use crate::crypto::SecureRandom;
use std::sync::LazyLock;

View File

@ -1,5 +1,7 @@
//! MTProto frame types and metadata
#![allow(dead_code)]
use std::collections::HashMap;
/// Extra metadata associated with a frame

View File

@ -5,7 +5,11 @@ pub mod frame;
pub mod obfuscation;
pub mod tls;
#[allow(unused_imports)]
pub use constants::*;
#[allow(unused_imports)]
pub use frame::*;
#[allow(unused_imports)]
pub use obfuscation::*;
#[allow(unused_imports)]
pub use tls::*;

View File

@ -1,8 +1,9 @@
//! MTProto Obfuscation
#![allow(dead_code)]
use zeroize::Zeroize;
use crate::crypto::{sha256, AesCtr};
use crate::error::Result;
use super::constants::*;
/// Obfuscation parameters from handshake

View File

@ -4,8 +4,9 @@
//! for domain fronting. The handshake looks like valid TLS 1.3 but
//! actually carries MTProto authentication data.
#![allow(dead_code)]
use crate::crypto::{sha256_hmac, SecureRandom};
use crate::error::{ProxyError, Result};
use super::constants::*;
use std::time::{SystemTime, UNIX_EPOCH};
use num_bigint::BigUint;

View File

@ -271,7 +271,7 @@ impl RunningClientHandler {
self.peer = normalize_ip(self.peer);
let peer = self.peer;
let ip_tracker = self.ip_tracker.clone();
let _ip_tracker = self.ip_tracker.clone();
debug!(peer = %peer, "New connection");
if let Err(e) = configure_client_socket(
@ -331,7 +331,7 @@ impl RunningClientHandler {
let is_tls = tls::is_tls_handshake(&first_bytes[..3]);
let peer = self.peer;
let ip_tracker = self.ip_tracker.clone();
let _ip_tracker = self.ip_tracker.clone();
debug!(peer = %peer, is_tls = is_tls, "Handshake type detected");
@ -344,7 +344,7 @@ impl RunningClientHandler {
async fn handle_tls_client(mut self, first_bytes: [u8; 5]) -> Result<HandshakeOutcome> {
let peer = self.peer;
let ip_tracker = self.ip_tracker.clone();
let _ip_tracker = self.ip_tracker.clone();
let tls_len = u16::from_be_bytes([first_bytes[3], first_bytes[4]]) as usize;
@ -440,7 +440,7 @@ impl RunningClientHandler {
async fn handle_direct_client(mut self, first_bytes: [u8; 5]) -> Result<HandshakeOutcome> {
let peer = self.peer;
let ip_tracker = self.ip_tracker.clone();
let _ip_tracker = self.ip_tracker.clone();
if !self.config.general.modes.classic && !self.config.general.modes.secure {
debug!(peer = %peer, "Non-TLS modes disabled");

View File

@ -1,5 +1,7 @@
//! MTProto Handshake
#![allow(dead_code)]
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;

View File

@ -8,6 +8,9 @@ pub mod middle_relay;
pub mod relay;
pub use client::ClientHandler;
#[allow(unused_imports)]
pub use handshake::*;
#[allow(unused_imports)]
pub use masking::*;
#[allow(unused_imports)]
pub use relay::*;

View File

@ -1,7 +1,8 @@
//! Statistics and replay protection
#![allow(dead_code)]
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::{Instant, Duration};
use dashmap::DashMap;
use parking_lot::Mutex;

View File

@ -3,6 +3,8 @@
//! This module provides a thread-safe pool of BytesMut buffers
//! that can be reused across connections to reduce allocation pressure.
#![allow(dead_code)]
use bytes::BytesMut;
use crossbeam_queue::ArrayQueue;
use std::ops::{Deref, DerefMut};

View File

@ -18,6 +18,8 @@
//! is either written to upstream or stored in our pending buffer
//! - when upstream is pending -> ciphertext is buffered/bounded and backpressure is applied
//!
#![allow(dead_code)]
//! =======================
//! Writer state machine
//! =======================
@ -55,7 +57,7 @@ use std::io::{self, ErrorKind, Result};
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use tracing::{debug, trace, warn};
use tracing::{debug, trace};
use crate::crypto::AesCtr;
use super::state::{StreamState, YieldBuffer};

View File

@ -3,6 +3,8 @@
//! This module defines the common types and traits used by all
//! frame encoding/decoding implementations.
#![allow(dead_code)]
use bytes::{Bytes, BytesMut};
use std::io::Result;
use std::sync::Arc;

View File

@ -3,6 +3,8 @@
//! This module provides Encoder/Decoder implementations compatible
//! with tokio-util's Framed wrapper for easy async frame I/O.
#![allow(dead_code)]
use bytes::{Bytes, BytesMut, BufMut};
use std::io::{self, Error, ErrorKind};
use std::sync::Arc;

View File

@ -1,6 +1,8 @@
//! MTProto frame stream wrappers
use bytes::{Bytes, BytesMut};
#![allow(dead_code)]
use bytes::Bytes;
use std::io::{Error, ErrorKind, Result};
use tokio::io::{AsyncRead, AsyncWrite, AsyncReadExt, AsyncWriteExt};
use crate::protocol::constants::*;

View File

@ -12,28 +12,34 @@ pub mod frame_codec;
pub mod frame_stream;
// Re-export state machine types
#[allow(unused_imports)]
pub use state::{
StreamState, Transition, PollResult,
ReadBuffer, WriteBuffer, HeaderBuffer, YieldBuffer,
};
// Re-export buffer pool
#[allow(unused_imports)]
pub use buffer_pool::{BufferPool, PooledBuffer, PoolStats};
// Re-export stream implementations
#[allow(unused_imports)]
pub use crypto_stream::{CryptoReader, CryptoWriter, PassthroughStream};
pub use tls_stream::{FakeTlsReader, FakeTlsWriter};
// Re-export frame types
#[allow(unused_imports)]
pub use frame::{Frame, FrameMeta, FrameCodec as FrameCodecTrait, create_codec};
// Re-export tokio-util compatible codecs
// Re-export tokio-util compatible codecs
#[allow(unused_imports)]
pub use frame_codec::{
FrameCodec,
AbridgedCodec, IntermediateCodec, SecureCodec,
};
// Legacy re-exports for compatibility
#[allow(unused_imports)]
pub use frame_stream::{
AbridgedFrameReader, AbridgedFrameWriter,
IntermediateFrameReader, IntermediateFrameWriter,

View File

@ -3,6 +3,8 @@
//! This module provides core types and traits for implementing
//! stateful async streams with proper partial read/write handling.
#![allow(dead_code)]
use bytes::{Bytes, BytesMut};
use std::io;

View File

@ -18,6 +18,8 @@
//! - Explicit state machines for all async operations
//! - Never lose data on partial reads
//! - Atomic TLS record formation for writes
#![allow(dead_code)]
//! - Proper handling of all TLS record types
//!
//! Important nuance (Telegram FakeTLS):

View File

@ -1,5 +1,7 @@
//! Stream traits and common types
#![allow(dead_code)]
use bytes::Bytes;
use std::io::Result;
use std::pin::Pin;

View File

@ -19,6 +19,7 @@ pub struct TlsFrontCache {
disk_path: PathBuf,
}
#[allow(dead_code)]
impl TlsFrontCache {
pub fn new(domains: &[String], default_len: usize, disk_path: impl AsRef<Path>) -> Self {
let default_template = ParsedServerHello {
@ -173,7 +174,7 @@ impl TlsFrontCache {
tokio::spawn(async move {
loop {
for domain in &domains {
fetcher(domain.clone()).await;
let _ = fetcher(domain.clone()).await;
}
sleep(interval).await;
}

View File

@ -4,4 +4,5 @@ pub mod fetcher;
pub mod emulator;
pub use cache::TlsFrontCache;
#[allow(unused_imports)]
pub use types::{CachedTlsData, TlsFetchResult};

View File

@ -14,6 +14,7 @@ use super::MePool;
const HEALTH_INTERVAL_SECS: u64 = 1;
const JITTER_FRAC_NUM: u64 = 2; // jitter up to 50% of backoff
#[allow(dead_code)]
const MAX_CONCURRENT_PER_DC_DEFAULT: usize = 1;
pub async fn me_health_monitor(pool: Arc<MePool>, rng: Arc<SecureRandom>, _min_connections: usize) {

View File

@ -17,8 +17,10 @@ mod wire;
use bytes::Bytes;
pub use health::me_health_monitor;
#[allow(unused_imports)]
pub use ping::{run_me_ping, format_sample_line, MePingReport, MePingSample, MePingFamily};
pub use pool::MePool;
#[allow(unused_imports)]
pub use pool_nat::{stun_probe, detect_public_ip};
pub use registry::ConnRegistry;
pub use secret::fetch_proxy_secret;

View File

@ -24,6 +24,7 @@ pub struct MePingSample {
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct MePingReport {
pub dc: i32,
pub family: MePingFamily,

View File

@ -36,6 +36,7 @@ pub struct MeWriter {
pub allow_drain_fallback: Arc<AtomicBool>,
}
#[allow(dead_code)]
pub struct MePool {
pub(super) registry: Arc<ConnRegistry>,
pub(super) writers: Arc<RwLock<Vec<MeWriter>>>,
@ -992,6 +993,7 @@ impl MePool {
}
#[allow(dead_code)]
fn hex_dump(data: &[u8]) -> String {
const MAX: usize = 64;
let mut out = String::with_capacity(data.len() * 2 + 3);

View File

@ -1,7 +1,7 @@
use std::net::{IpAddr, Ipv4Addr};
use std::time::Duration;
use tracing::{info, warn, debug};
use tracing::{info, warn};
use crate::error::{ProxyError, Result};
use crate::network::probe::is_bogon;
@ -9,11 +9,14 @@ use crate::network::stun::{stun_probe_dual, IpFamily, StunProbeResult};
use super::MePool;
use std::time::Instant;
#[allow(dead_code)]
pub async fn stun_probe(stun_addr: Option<String>) -> Result<crate::network::stun::DualStunResult> {
let stun_addr = stun_addr.unwrap_or_else(|| "stun.l.google.com:19302".to_string());
stun_probe_dual(&stun_addr).await
}
#[allow(dead_code)]
pub async fn detect_public_ip() -> Option<IpAddr> {
fetch_public_ipv4_with_retry().await.ok().flatten().map(IpAddr::V4)
}

View File

@ -21,6 +21,7 @@ pub enum RouteResult {
}
#[derive(Clone)]
#[allow(dead_code)]
pub struct ConnMeta {
pub target_dc: i16,
pub client_addr: SocketAddr,
@ -29,6 +30,7 @@ pub struct ConnMeta {
}
#[derive(Clone)]
#[allow(dead_code)]
pub struct BoundConn {
pub conn_id: u64,
pub meta: ConnMeta,
@ -167,6 +169,7 @@ impl ConnRegistry {
out
}
#[allow(dead_code)]
pub async fn get_meta(&self, conn_id: u64) -> Option<ConnMeta> {
let inner = self.inner.read().await;
inner.meta.get(&conn_id).cloned()

View File

@ -1,5 +1,3 @@
use std::time::Duration;
use tracing::{debug, info, warn};
use std::time::SystemTime;
use httpdate;

View File

@ -6,9 +6,13 @@ pub mod socket;
pub mod socks;
pub mod upstream;
#[allow(unused_imports)]
pub use pool::ConnectionPool;
#[allow(unused_imports)]
pub use proxy_protocol::{ProxyProtocolInfo, parse_proxy_protocol};
pub use socket::*;
#[allow(unused_imports)]
pub use socks::*;
#[allow(unused_imports)]
pub use upstream::{DcPingResult, StartupPingResult, UpstreamManager};
pub mod middle_proxy;

View File

@ -1,5 +1,7 @@
//! Connection Pool
#![allow(dead_code)]
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::Arc;
@ -8,7 +10,7 @@ use tokio::net::TcpStream;
use tokio::sync::Mutex;
use tokio::time::timeout;
use parking_lot::RwLock;
use tracing::{debug, warn};
use tracing::debug;
use crate::error::{ProxyError, Result};
use super::socket::configure_tcp_socket;

View File

@ -28,6 +28,7 @@ mod address_family {
/// Information extracted from PROXY protocol header
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct ProxyProtocolInfo {
/// Source (client) address
pub src_addr: SocketAddr,
@ -37,6 +38,7 @@ pub struct ProxyProtocolInfo {
pub version: u8,
}
#[allow(dead_code)]
impl ProxyProtocolInfo {
/// Create info with just source address
pub fn new(src_addr: SocketAddr) -> Self {
@ -231,12 +233,14 @@ async fn parse_v2<R: AsyncRead + Unpin>(
}
/// Builder for PROXY protocol v1 header
#[allow(dead_code)]
pub struct ProxyProtocolV1Builder {
family: &'static str,
src_addr: Option<SocketAddr>,
dst_addr: Option<SocketAddr>,
}
#[allow(dead_code)]
impl ProxyProtocolV1Builder {
pub fn new() -> Self {
Self {
@ -284,11 +288,13 @@ impl Default for ProxyProtocolV1Builder {
}
/// Builder for PROXY protocol v2 header
#[allow(dead_code)]
pub struct ProxyProtocolV2Builder {
src: Option<SocketAddr>,
dst: Option<SocketAddr>,
}
#[allow(dead_code)]
impl ProxyProtocolV2Builder {
pub fn new() -> Self {
Self { src: None, dst: None }

View File

@ -10,6 +10,7 @@ use socket2::{Socket, TcpKeepalive, Domain, Type, Protocol};
use tracing::debug;
/// Configure TCP socket with recommended settings for proxy use
#[allow(dead_code)]
pub fn configure_tcp_socket(
stream: &TcpStream,
keepalive: bool,
@ -82,6 +83,7 @@ pub fn configure_client_socket(
}
/// Set socket to send RST on close (for masking)
#[allow(dead_code)]
pub fn set_linger_zero(stream: &TcpStream) -> Result<()> {
let socket = socket2::SockRef::from(stream);
socket.set_linger(Some(Duration::ZERO))?;
@ -89,6 +91,7 @@ pub fn set_linger_zero(stream: &TcpStream) -> Result<()> {
}
/// Create a new TCP socket for outgoing connections
#[allow(dead_code)]
pub fn create_outgoing_socket(addr: SocketAddr) -> Result<Socket> {
create_outgoing_socket_bound(addr, None)
}
@ -120,6 +123,7 @@ pub fn create_outgoing_socket_bound(addr: SocketAddr, bind_addr: Option<IpAddr>)
/// Get local address of a socket
#[allow(dead_code)]
pub fn get_local_addr(stream: &TcpStream) -> Option<SocketAddr> {
stream.local_addr().ok()
}
@ -157,11 +161,13 @@ pub fn resolve_interface_ip(_name: &str, _want_ipv6: bool) -> Option<IpAddr> {
}
/// Get peer address of a socket
#[allow(dead_code)]
pub fn get_peer_addr(stream: &TcpStream) -> Option<SocketAddr> {
stream.peer_addr().ok()
}
/// Check if address is IPv6
#[allow(dead_code)]
pub fn is_ipv6(addr: &SocketAddr) -> bool {
addr.is_ipv6()
}

View File

@ -1,7 +1,7 @@
//! SOCKS4/5 Client Implementation
use std::net::{IpAddr, SocketAddr};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;
use crate::error::{ProxyError, Result};

View File

@ -1,7 +1,9 @@
//! Upstream Management with per-DC latency-weighted selection
//!
//!
//! IPv6/IPv4 connectivity checks with configurable preference.
#![allow(deprecated)]
use std::collections::HashMap;
use std::net::{SocketAddr, IpAddr};
use std::sync::Arc;
@ -549,7 +551,7 @@ impl UpstreamManager {
/// Tests BOTH IPv6 and IPv4, returns separate results for each.
pub async fn ping_all_dcs(
&self,
prefer_ipv6: bool,
_prefer_ipv6: bool,
dc_overrides: &HashMap<String, Vec<String>>,
ipv4_enabled: bool,
ipv6_enabled: bool,
@ -907,6 +909,7 @@ impl UpstreamManager {
}
/// Get the preferred IP for a DC (for use by other components)
#[allow(dead_code)]
pub async fn get_dc_ip_preference(&self, dc_idx: i16) -> Option<IpPreference> {
let guard = self.upstreams.read().await;
if guard.is_empty() {
@ -918,6 +921,7 @@ impl UpstreamManager {
}
/// Get preferred DC address based on config preference
#[allow(dead_code)]
pub async fn get_dc_addr(&self, dc_idx: i16, prefer_ipv6: bool) -> Option<SocketAddr> {
let arr_idx = UpstreamState::dc_array_idx(dc_idx)?;

View File

@ -1,22 +1,24 @@
//! IP Addr Detect
use std::net::{IpAddr, SocketAddr, UdpSocket};
use std::net::{IpAddr, UdpSocket};
use std::time::Duration;
use tracing::{debug, warn};
/// Detected IP addresses
#[derive(Debug, Clone, Default)]
#[allow(dead_code)]
pub struct IpInfo {
pub ipv4: Option<IpAddr>,
pub ipv6: Option<IpAddr>,
}
#[allow(dead_code)]
impl IpInfo {
/// Check if any IP is detected
pub fn has_any(&self) -> bool {
self.ipv4.is_some() || self.ipv6.is_some()
}
/// Get preferred IP (IPv6 if available and preferred)
pub fn preferred(&self, prefer_ipv6: bool) -> Option<IpAddr> {
if prefer_ipv6 {
@ -28,12 +30,14 @@ impl IpInfo {
}
/// URLs for IP detection
#[allow(dead_code)]
const IPV4_URLS: &[&str] = &[
"http://v4.ident.me/",
"http://ipv4.icanhazip.com/",
"http://api.ipify.org/",
];
#[allow(dead_code)]
const IPV6_URLS: &[&str] = &[
"http://v6.ident.me/",
"http://ipv6.icanhazip.com/",
@ -42,12 +46,14 @@ const IPV6_URLS: &[&str] = &[
/// Detect local IP address by connecting to a public DNS
/// This does not actually send any packets
#[allow(dead_code)]
fn get_local_ip(target: &str) -> Option<IpAddr> {
let socket = UdpSocket::bind("0.0.0.0:0").ok()?;
socket.connect(target).ok()?;
socket.local_addr().ok().map(|addr| addr.ip())
}
#[allow(dead_code)]
fn get_local_ipv6(target: &str) -> Option<IpAddr> {
let socket = UdpSocket::bind("[::]:0").ok()?;
socket.connect(target).ok()?;
@ -55,6 +61,7 @@ fn get_local_ipv6(target: &str) -> Option<IpAddr> {
}
/// Detect public IP addresses
#[allow(dead_code)]
pub async fn detect_ip() -> IpInfo {
let mut info = IpInfo::default();
@ -119,6 +126,7 @@ pub async fn detect_ip() -> IpInfo {
info
}
#[allow(dead_code)]
fn is_private_ip(ip: IpAddr) -> bool {
match ip {
IpAddr::V4(ipv4) => {
@ -131,19 +139,21 @@ fn is_private_ip(ip: IpAddr) -> bool {
}
/// Fetch IP from URL
#[allow(dead_code)]
async fn fetch_ip(url: &str) -> Option<IpAddr> {
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(5))
.build()
.ok()?;
let response = client.get(url).send().await.ok()?;
let text = response.text().await.ok()?;
text.trim().parse().ok()
}
/// Synchronous IP detection (for startup)
#[allow(dead_code)]
pub fn detect_ip_sync() -> IpInfo {
tokio::runtime::Handle::current().block_on(detect_ip())
}

View File

@ -3,5 +3,7 @@
pub mod ip;
pub mod time;
#[allow(unused_imports)]
pub use ip::*;
#[allow(unused_imports)]
pub use time::*;

View File

@ -4,11 +4,14 @@ use std::time::Duration;
use chrono::{DateTime, Utc};
use tracing::{debug, warn, error};
#[allow(dead_code)]
const TIME_SYNC_URL: &str = "https://core.telegram.org/getProxySecret";
#[allow(dead_code)]
const MAX_TIME_SKEW_SECS: i64 = 30;
/// Time sync result
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct TimeSyncResult {
pub server_time: DateTime<Utc>,
pub local_time: DateTime<Utc>,
@ -17,6 +20,7 @@ pub struct TimeSyncResult {
}
/// Check time synchronization with Telegram servers
#[allow(dead_code)]
pub async fn check_time_sync() -> Option<TimeSyncResult> {
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(10))
@ -60,6 +64,7 @@ pub async fn check_time_sync() -> Option<TimeSyncResult> {
}
/// Background time sync task
#[allow(dead_code)]
pub async fn time_sync_task(check_interval: Duration) -> ! {
loop {
if let Some(result) = check_time_sync().await {