remove comments & rewrite client connection
This commit is contained in:
@@ -109,10 +109,8 @@ impl TcpConnection {
|
||||
while socket.can_recv() {
|
||||
let mut full = false;
|
||||
|
||||
// Используем recv_slice для контроля размера чанка
|
||||
let mut temp = [0u8; TCP_CHUNK_SIZE];
|
||||
|
||||
// Peek, чтобы проверить, сможем ли мы отправить данные, прежде чем извлечь их
|
||||
if let Ok(n) = socket.peek_slice(&mut temp) {
|
||||
if n == 0 {
|
||||
break;
|
||||
@@ -121,11 +119,10 @@ impl TcpConnection {
|
||||
let chunk = Bytes::copy_from_slice(&temp[..n]);
|
||||
match self.tx.try_send(chunk) {
|
||||
Ok(_) => {
|
||||
// Только если успешно отправили в канал, удаляем данные из сокета
|
||||
socket.recv_slice(&mut temp[..n]).unwrap();
|
||||
}
|
||||
Err(mpsc::error::TrySendError::Full(_)) => {
|
||||
full = true; // Канал забит, сработает Backpressure в smoltcp
|
||||
full = true;
|
||||
}
|
||||
Err(_) => {
|
||||
self.state = ConnectionState::Closed;
|
||||
@@ -143,25 +140,21 @@ impl TcpConnection {
|
||||
|
||||
let current_pending = self.pending_data.len();
|
||||
|
||||
// Считаем % заполненности для логирования
|
||||
let fill_ratio = (current_pending as f32 / MAX_PENDING as f32) * 100.0;
|
||||
|
||||
if current_pending >= MAX_PENDING {
|
||||
// Состояние активного Backpressure
|
||||
netrunner_logger::warn!(
|
||||
%self.handle,
|
||||
"Backpressure ACTIVE: Buffer is FULL ({} bytes). Stalling RX channel.",
|
||||
current_pending
|
||||
);
|
||||
} else if fill_ratio > 80.0 {
|
||||
// Состояние Bufferbloat (буфер почти полон, пакеты задерживаются)
|
||||
netrunner_logger::info!(
|
||||
%self.handle,
|
||||
"Bufferbloat Warning: Buffer {:.1}% full ({} bytes). Latency increasing.",
|
||||
fill_ratio, current_pending
|
||||
);
|
||||
|
||||
// Продолжаем читать, пока есть хоть какое-то место
|
||||
while let Ok(data) = self.rx.try_recv() {
|
||||
self.pending_data.extend_from_slice(&data);
|
||||
if self.pending_data.len() >= MAX_PENDING {
|
||||
@@ -169,7 +162,6 @@ impl TcpConnection {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Обычный режим
|
||||
while let Ok(data) = self.rx.try_recv() {
|
||||
self.pending_data.extend_from_slice(&data);
|
||||
if self.pending_data.len() >= MAX_PENDING {
|
||||
@@ -178,13 +170,11 @@ impl TcpConnection {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. DOWNLOAD: Отправка накопленного буфера в smoltcp
|
||||
if !self.pending_data.is_empty() && socket.can_send() {
|
||||
match socket.send_slice(&self.pending_data) {
|
||||
Ok(n) => {
|
||||
self.pending_data.advance(n);
|
||||
|
||||
// Лог освобождения (опционально, чтобы видеть, что пробка рассасывается)
|
||||
if n > 0 && self.pending_data.len() < (MAX_PENDING / 2) && fill_ratio > 90.0 {
|
||||
netrunner_logger::info!(%self.handle, "Backpressure RELIEVED: Buffer drained to {} bytes", self.pending_data.len());
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ use bytes::Bytes;
|
||||
|
||||
pub struct UdpConnection {
|
||||
pub handle: SocketHandle,
|
||||
// UPLOAD: Ограниченный канал для передачи данных наружу
|
||||
|
||||
tx: mpsc::Sender<Bytes>,
|
||||
// DOWNLOAD: Канал для приема данных из сети
|
||||
|
||||
rx: mpsc::Receiver<Bytes>,
|
||||
client_endpoint: Option<IpEndpoint>,
|
||||
last_activity: Instant,
|
||||
@@ -20,10 +20,6 @@ pub struct UdpConnection {
|
||||
const UDP_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
|
||||
impl UdpConnection {
|
||||
/// Возвращает:
|
||||
/// 1. Экземпляр UdpConnection
|
||||
/// 2. Receiver (для чтения данных, отправляемых ИЗ smoltcp В сеть)
|
||||
/// 3. Sender (для записи данных ИЗ сети В smoltcp)
|
||||
pub fn new(handle: SocketHandle) -> (Self, mpsc::Receiver<Bytes>, mpsc::Sender<Bytes>) {
|
||||
let (tx_to_net, rx_from_smol) = mpsc::channel::<Bytes>(CHANNEL_CAPACITY);
|
||||
let (tx_to_smol, rx_from_net) = mpsc::channel::<Bytes>(CHANNEL_CAPACITY);
|
||||
@@ -40,31 +36,25 @@ impl UdpConnection {
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, socket: &mut udp::Socket) -> bool {
|
||||
// Проверка таймаута бездействия
|
||||
if self.last_activity.elapsed() > UDP_TIMEOUT {
|
||||
netrunner_logger::debug!(%self.handle, "UDP Session closed due to timeout");
|
||||
socket.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 1. UPLOAD: Читаем из smoltcp и отправляем в виртуальный канал
|
||||
if socket.can_recv() {
|
||||
while let Ok((data, metadata)) = socket.recv() {
|
||||
self.client_endpoint = Some(metadata.endpoint);
|
||||
|
||||
// Копируем данные в Bytes и пытаемся протолкнуть.
|
||||
// Если канал забит (Full), пакет дропается — это штатное поведение UDP.
|
||||
if self.tx.try_send(Bytes::copy_from_slice(data)).is_ok() {
|
||||
self.last_activity = Instant::now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. DOWNLOAD: Читаем из виртуального канала и пишем в smoltcp
|
||||
if socket.can_send() {
|
||||
if let Some(endpoint) = self.client_endpoint {
|
||||
while let Ok(data) = self.rx.try_recv() {
|
||||
// Сигнал закрытия стрима
|
||||
if data.is_empty() {
|
||||
socket.close();
|
||||
return false;
|
||||
@@ -75,8 +65,6 @@ impl UdpConnection {
|
||||
self.last_activity = Instant::now();
|
||||
}
|
||||
Err(_) => {
|
||||
// Если сокет smoltcp переполнен, прерываем цикл.
|
||||
// Пакет теряется, что опять же является нормой для UDP.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-29
@@ -1,35 +1,10 @@
|
||||
uniffi::setup_scaffolding!();
|
||||
|
||||
pub mod connections;
|
||||
pub mod session;
|
||||
pub mod tun;
|
||||
use netrunner_logger::info;
|
||||
|
||||
use std::sync::OnceLock;
|
||||
use tokio::runtime::Runtime;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::tun::routing::reset_platform_routing;
|
||||
pub mod session;
|
||||
|
||||
static RUNTIME: OnceLock<Runtime> = OnceLock::new();
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct Session {
|
||||
pub(crate) cancel_token: CancellationToken,
|
||||
pub(crate) proxy_ip: String,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl Session {
|
||||
pub fn stop(&self) {
|
||||
info!("Stopping session...");
|
||||
self.cancel_token.cancel();
|
||||
let _ = reset_platform_routing(Some(&self.proxy_ip));
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Session {
|
||||
fn drop(&mut self) {
|
||||
info!("Session dropped, stopping all tasks...");
|
||||
self.cancel_token.cancel();
|
||||
let _ = reset_platform_routing(Some(&self.proxy_ip));
|
||||
}
|
||||
}
|
||||
pub static RUNTIME: OnceLock<Runtime> = OnceLock::new();
|
||||
|
||||
+6
-17
@@ -6,7 +6,7 @@ use netrunner_client::{
|
||||
tun::Tun,
|
||||
},
|
||||
};
|
||||
use netrunner_core::proxy::{connection::connection::ConnectionRole, network::Network};
|
||||
use netrunner_core::proxy::connection::connection::ClientHandler;
|
||||
use netrunner_logger::{error, info};
|
||||
use smoltcp::{iface::Config, phy::DeviceCapabilities};
|
||||
use std::net::Ipv4Addr;
|
||||
@@ -42,26 +42,15 @@ async fn main() -> anyhow::Result<()> {
|
||||
caps.max_transmission_unit = 1350;
|
||||
caps.medium = smoltcp::phy::Medium::Ip;
|
||||
|
||||
let network = Network::new(
|
||||
"127.0.0.1".into(),
|
||||
8080,
|
||||
ConnectionRole::Client,
|
||||
Some(remote_address.clone()),
|
||||
);
|
||||
|
||||
let network_token = CancellationToken::new();
|
||||
let net_token_for_spawn = network_token.clone();
|
||||
|
||||
info!("Establishing secure tunnel to proxy server...");
|
||||
let muxer = match network.initialize_client_tunnel(net_token_for_spawn).await {
|
||||
|
||||
let muxer = match ClientHandler::connect(&remote_address).await {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
error!("Failed to establish secure tunnel: {}", e);
|
||||
|
||||
let _ = reset_platform_routing(Some(
|
||||
&remote_address.split(':').next().unwrap().to_string(),
|
||||
));
|
||||
return Err(anyhow::anyhow!("Tunnel initialization failed: {}", e));
|
||||
error!("Failed to establish secure tunnel to server: {}", e);
|
||||
return Err(anyhow::anyhow!("Failed to establish secure tunnel: {}", e));
|
||||
}
|
||||
};
|
||||
info!("Secure tunnel established, Muxer is ready.");
|
||||
@@ -96,7 +85,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
error!("Failed to restore routing: {}", e);
|
||||
} else {
|
||||
info!("System routing restored successfully.");
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+53
-63
@@ -1,22 +1,18 @@
|
||||
use crate::{
|
||||
RUNTIME,
|
||||
tun::{engine::EngineBuilder, routing::reset_platform_routing, tun::Tun},
|
||||
};
|
||||
use netrunner_logger::{error, info};
|
||||
use std::sync::Arc;
|
||||
use tokio::runtime::Runtime;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
pub mod desktop;
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
pub mod mobile;
|
||||
|
||||
use crate::{
|
||||
RUNTIME, Session,
|
||||
connections::dns::DnsHandler,
|
||||
tun::{engine::Engine, routing::setup_platform_routing, tun::Tun},
|
||||
};
|
||||
use netrunner_core::proxy::{connection::connection::ConnectionRole, network::Network};
|
||||
use netrunner_logger::{error, info};
|
||||
use smoltcp::{iface::Config, phy::DeviceCapabilities};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use tokio::runtime::Runtime;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
fn get_runtime() -> &'static Runtime {
|
||||
RUNTIME.get_or_init(|| {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
@@ -26,6 +22,29 @@ fn get_runtime() -> &'static Runtime {
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct Session {
|
||||
pub(crate) cancel_token: CancellationToken,
|
||||
pub(crate) proxy_ip: String,
|
||||
}
|
||||
|
||||
#[uniffi::export]
|
||||
impl Session {
|
||||
pub fn stop(&self) {
|
||||
info!("Stopping session...");
|
||||
self.cancel_token.cancel();
|
||||
let _ = reset_platform_routing(Some(&self.proxy_ip));
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Session {
|
||||
fn drop(&mut self) {
|
||||
info!("Session dropped, stopping all tasks...");
|
||||
self.cancel_token.cancel();
|
||||
let _ = reset_platform_routing(Some(&self.proxy_ip));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct SessionManager;
|
||||
|
||||
@@ -48,8 +67,7 @@ impl SessionManager {
|
||||
) -> Arc<Session> {
|
||||
let runtime = get_runtime();
|
||||
let cancel_token = CancellationToken::new();
|
||||
let sesison_token = cancel_token.clone();
|
||||
let net_token = cancel_token.clone();
|
||||
let session_token = cancel_token.clone();
|
||||
|
||||
let addr: std::net::SocketAddr = remote_address.parse().expect("Invalid address format");
|
||||
let remote_proxy_ip = addr.ip().to_string();
|
||||
@@ -68,11 +86,6 @@ impl SessionManager {
|
||||
}
|
||||
};
|
||||
|
||||
let mut dns_handler = DnsHandler::new(&cache_path);
|
||||
if let Err(e) = dns_handler.init().await {
|
||||
error!("Failed to initialize DNS blocklist: {}", e);
|
||||
}
|
||||
|
||||
let tun_device = {
|
||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||
{
|
||||
@@ -100,55 +113,32 @@ impl SessionManager {
|
||||
}
|
||||
};
|
||||
|
||||
let _ = setup_platform_routing(&remote_address);
|
||||
let builder_result = EngineBuilder::new(&remote_address)
|
||||
.with_cache_path(&cache_path)
|
||||
.with_tun(tun_device)
|
||||
.build()
|
||||
.await;
|
||||
|
||||
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
||||
let mut caps = DeviceCapabilities::default();
|
||||
caps.max_transmission_unit = 1350;
|
||||
caps.medium = smoltcp::phy::Medium::Ip;
|
||||
|
||||
let network = Network::new(
|
||||
"0.0.0.0".into(),
|
||||
8080,
|
||||
ConnectionRole::Client,
|
||||
Some(remote_address.clone()),
|
||||
);
|
||||
|
||||
let muxer = match network.initialize_client_tunnel(net_token).await {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
error!("Failed to establish secure tunnel to server: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
info!("Secure tunnel established, Muxer is ready.");
|
||||
|
||||
let mut engine = Engine::new(config, caps, dns_handler, muxer);
|
||||
engine.set_any_ip(true);
|
||||
engine.set_transparent_mode();
|
||||
engine.set_default_gateway(Ipv4Addr::new(10, 0, 0, 2));
|
||||
engine.activate();
|
||||
let cancel_token_for_engine = cancel_token.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
info!("Engine async task started");
|
||||
|
||||
tokio::select! {
|
||||
|
||||
res = engine.run(tun_device) => {
|
||||
|
||||
info!("Engine loop finished: {:?}", res);
|
||||
},
|
||||
_ = cancel_token_for_engine.cancelled() => {
|
||||
info!("Engine task shutting down via token");
|
||||
match builder_result {
|
||||
Ok((mut engine, tun)) => {
|
||||
info!("Engine async task started");
|
||||
tokio::select! {
|
||||
res = engine.run(tun) => {
|
||||
info!("Engine loop finished: {:?}", res);
|
||||
},
|
||||
_ = cancel_token.cancelled() => {
|
||||
info!("Engine task shutting down via token");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Err(e) => {
|
||||
error!("Failed to build VPN Engine: {}", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Arc::new(Session {
|
||||
cancel_token: sesison_token,
|
||||
cancel_token: session_token,
|
||||
proxy_ip: remote_proxy_ip,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -101,10 +101,7 @@ impl ConnectionManager {
|
||||
}
|
||||
|
||||
pub fn process_sockets(&mut self, socket_set: &mut SocketSet) {
|
||||
// Добавим лог в начало цикла, если сессий много, чтобы видеть нагрузку
|
||||
if !self.active_tcp_sessions.is_empty() || !self.active_udp_sessions.is_empty() {
|
||||
// trace!("Processing sockets: TCP={}, UDP={}", self.active_tcp_sessions.len(), self.active_udp_sessions.len());
|
||||
}
|
||||
if !self.active_tcp_sessions.is_empty() || !self.active_udp_sessions.is_empty() {}
|
||||
|
||||
for (handle, socket) in socket_set.iter_mut() {
|
||||
if let Some(tcp) = tcp::Socket::downcast_mut(socket) {
|
||||
@@ -170,7 +167,6 @@ impl ConnectionManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ждем подтверждения от прокси (handshake)
|
||||
match tokio::time::timeout(Duration::from_secs(10), v_rx.recv()).await {
|
||||
Ok(Some(data)) => {
|
||||
if data.len() >= 2 && data[1] == 0x00 {
|
||||
@@ -281,11 +277,9 @@ impl ConnectionManager {
|
||||
|
||||
netrunner_logger::info!(%handle, target = %target, "New UDP proxied session established");
|
||||
|
||||
// 1. Создаем UDP соединение и получаем каналы
|
||||
let (conn, mut rx_from_smol, tx_to_smol) = UdpConnection::new(handle);
|
||||
self.active_udp_sessions.insert(handle, conn);
|
||||
|
||||
// 2. Фоновая задача для Muxer'а
|
||||
let muxer = self.muxer.clone();
|
||||
let stream_id = muxer.next_id();
|
||||
let connect_payload = target.to_string();
|
||||
@@ -441,8 +435,8 @@ impl ConnectionManager {
|
||||
|
||||
fn create_dynamic_udp_socket<'a>(port: u16) -> udp::Socket<'a> {
|
||||
let (buf_size, packet_count) = match port {
|
||||
443 => (512 * 1024, 390), // Большой буфер для QUIC (YouTube)
|
||||
53 => (64 * 1024, 32), // DNS
|
||||
443 => (512 * 1024, 390),
|
||||
53 => (64 * 1024, 32),
|
||||
_ => (128 * 1024, 100),
|
||||
};
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ use std::{
|
||||
Arc, LazyLock, Mutex,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
},
|
||||
time::Instant as StdInstant, // Добавлено для расчёта скорости
|
||||
time::Instant as StdInstant,
|
||||
};
|
||||
|
||||
use bytes::BytesMut;
|
||||
use netrunner_logger::info; // Предполагается, что у тебя есть этот логгер
|
||||
use netrunner_logger::info;
|
||||
use smoltcp::{
|
||||
phy::{self, Device, DeviceCapabilities},
|
||||
time::Instant,
|
||||
@@ -20,7 +20,6 @@ use tokio::sync::mpsc;
|
||||
const TOKEN_BUFFER_LIST_MAX_SIZE: usize = 64;
|
||||
static TOKEN_BUFFER_LIST: LazyLock<Mutex<Vec<BytesMut>>> = LazyLock::new(|| Mutex::new(Vec::new()));
|
||||
|
||||
// Структура, которую мы будем возвращать пользователю
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct TrafficStats {
|
||||
pub rx_bytes: u64,
|
||||
@@ -79,20 +78,17 @@ pub struct VirtTunDevice {
|
||||
tx_queue: mpsc::UnboundedSender<TokenBuffer>,
|
||||
rx_avail: Arc<AtomicBool>,
|
||||
|
||||
// === Статистика трафика ===
|
||||
rx_bytes: u64,
|
||||
tx_bytes: u64,
|
||||
rx_packets: u64,
|
||||
tx_packets: u64,
|
||||
|
||||
// Внутренние переменные для расчёта скорости
|
||||
last_speed_calc: StdInstant,
|
||||
last_rx_bytes: u64,
|
||||
last_tx_bytes: u64,
|
||||
cached_rx_speed: f64,
|
||||
cached_tx_speed: f64,
|
||||
|
||||
// Для периодического логирования
|
||||
last_log_time: StdInstant,
|
||||
}
|
||||
|
||||
@@ -147,7 +143,6 @@ impl VirtTunDevice {
|
||||
let rx_diff = self.rx_bytes.saturating_sub(self.last_rx_bytes);
|
||||
let tx_diff = self.tx_bytes.saturating_sub(self.last_tx_bytes);
|
||||
|
||||
// Переводим в МегаБайты в секунду (MB/s)
|
||||
self.cached_rx_speed = (rx_diff as f64 / 1_048_576.0) / elapsed_speed;
|
||||
self.cached_tx_speed = (tx_diff as f64 / 1_048_576.0) / elapsed_speed;
|
||||
|
||||
@@ -166,12 +161,11 @@ impl VirtTunDevice {
|
||||
}
|
||||
}
|
||||
|
||||
/// Внутренний метод проверки таймера для вывода логов
|
||||
fn check_and_log_stats(&mut self) {
|
||||
let now = StdInstant::now();
|
||||
// Логируем каждые 5 секунд
|
||||
|
||||
if now.duration_since(self.last_log_time).as_secs() >= 5 {
|
||||
let stats = self.get_stats(); // Заодно обновляем скорости
|
||||
let stats = self.get_stats();
|
||||
|
||||
info!(
|
||||
"TunDevice Traffic: RX: {:.2} MB ({} pkts) | TX: {:.2} MB ({} pkts) | Speed: ↓{:.2} MB/s, ↑{:.2} MB/s",
|
||||
@@ -193,12 +187,9 @@ impl Device for VirtTunDevice {
|
||||
type TxToken<'a> = VirtTxToken<'a>;
|
||||
|
||||
fn receive(&mut self, _timestamp: Instant) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
|
||||
// Проверяем, не пора ли записать стату в лог. receive() вызывается очень часто,
|
||||
// поэтому это отличное место для heartbeat таймера.
|
||||
self.check_and_log_stats();
|
||||
|
||||
if let Ok(buffer) = self.rx_queue.try_recv() {
|
||||
// Учет входящего трафика (DOWNLOAD)
|
||||
self.rx_bytes += buffer.len() as u64;
|
||||
self.rx_packets += 1;
|
||||
|
||||
@@ -250,7 +241,6 @@ impl phy::TxToken for VirtTxToken<'_> {
|
||||
|
||||
let result = f(&mut buffer);
|
||||
|
||||
// Учет исходящего трафика (UPLOAD)
|
||||
self.0.tx_bytes += len as u64;
|
||||
self.0.tx_packets += 1;
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use netrunner_core::proxy::connection::connection::ClientHandler;
|
||||
use netrunner_core::proxy::connection::muxer::Muxer;
|
||||
use smoltcp::iface::PollResult;
|
||||
use smoltcp::time::Instant;
|
||||
@@ -6,6 +7,7 @@ use smoltcp::{
|
||||
iface::{Config, Interface, SocketSet},
|
||||
phy::DeviceCapabilities,
|
||||
};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::{
|
||||
sync::{Arc, LazyLock, atomic::AtomicBool},
|
||||
@@ -16,11 +18,12 @@ use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||
use tokio::time::{Duration, sleep};
|
||||
use tun::{DeviceReader, DeviceWriter};
|
||||
|
||||
use netrunner_logger::{debug, info, warn};
|
||||
use netrunner_logger::{debug, error, info, warn};
|
||||
|
||||
use crate::connections::dns::DnsHandler;
|
||||
use crate::tun::connection_manager::ConnectionManager;
|
||||
use crate::tun::device::{TokenBuffer, VirtTunDevice};
|
||||
use crate::tun::routing::setup_platform_routing;
|
||||
use crate::tun::tun::Tun;
|
||||
|
||||
pub static START_TIME: LazyLock<StdInstant> = LazyLock::new(StdInstant::now);
|
||||
@@ -212,3 +215,65 @@ impl Engine {
|
||||
self.manager.start_listening(&mut self.socket_set);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EngineBuilder {
|
||||
remote_address: String,
|
||||
cache_path: String,
|
||||
tun_device: Option<Tun>,
|
||||
}
|
||||
|
||||
impl EngineBuilder {
|
||||
pub fn new(remote_address: impl Into<String>) -> Self {
|
||||
Self {
|
||||
remote_address: remote_address.into(),
|
||||
cache_path: ".".to_string(),
|
||||
tun_device: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_cache_path(mut self, path: impl Into<String>) -> Self {
|
||||
self.cache_path = path.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_tun(mut self, tun: Tun) -> Self {
|
||||
self.tun_device = Some(tun);
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn build(self) -> Result<(Engine, Tun), String> {
|
||||
let tun = self.tun_device.ok_or("TUN device is required")?;
|
||||
|
||||
info!("Initializing Engine components...");
|
||||
|
||||
let mut dns_handler = DnsHandler::new(&self.cache_path);
|
||||
if let Err(e) = dns_handler.init().await {
|
||||
error!("Failed to initialize DNS blocklist: {}", e);
|
||||
}
|
||||
|
||||
if let Err(e) = setup_platform_routing(&self.remote_address) {
|
||||
return Err(format!("Routing setup failed: {}", e));
|
||||
}
|
||||
|
||||
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
||||
let mut caps = DeviceCapabilities::default();
|
||||
caps.max_transmission_unit = 1350;
|
||||
caps.medium = smoltcp::phy::Medium::Ip;
|
||||
|
||||
info!("Establishing secure tunnel to proxy server...");
|
||||
let muxer = ClientHandler::connect(&self.remote_address)
|
||||
.await
|
||||
.map_err(|e| format!("Failed to establish secure tunnel: {}", e))?;
|
||||
info!("Secure tunnel established, Muxer is ready.");
|
||||
|
||||
let mut engine = Engine::new(config, caps, dns_handler, muxer);
|
||||
engine.set_any_ip(true);
|
||||
engine.set_transparent_mode();
|
||||
engine.set_default_gateway(Ipv4Addr::new(10, 0, 0, 2));
|
||||
engine.activate();
|
||||
|
||||
info!("Stack IP initialized: 10.0.0.2");
|
||||
|
||||
Ok((engine, tun))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user