structure refactoring
This commit is contained in:
@@ -1,77 +0,0 @@
|
|||||||
use smoltcp::iface::SocketHandle;
|
|
||||||
use smoltcp::socket::udp;
|
|
||||||
use smoltcp::wire::IpEndpoint;
|
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
use tokio::sync::mpsc;
|
|
||||||
|
|
||||||
use crate::connections::CHANNEL_CAPACITY;
|
|
||||||
use bytes::Bytes;
|
|
||||||
|
|
||||||
pub struct UdpConnection {
|
|
||||||
pub handle: SocketHandle,
|
|
||||||
|
|
||||||
tx: mpsc::Sender<Bytes>,
|
|
||||||
|
|
||||||
rx: mpsc::Receiver<Bytes>,
|
|
||||||
client_endpoint: Option<IpEndpoint>,
|
|
||||||
last_activity: Instant,
|
|
||||||
}
|
|
||||||
|
|
||||||
const UDP_TIMEOUT: Duration = Duration::from_secs(60);
|
|
||||||
|
|
||||||
impl UdpConnection {
|
|
||||||
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);
|
|
||||||
|
|
||||||
let conn = Self {
|
|
||||||
handle,
|
|
||||||
tx: tx_to_net,
|
|
||||||
rx: rx_from_net,
|
|
||||||
client_endpoint: None,
|
|
||||||
last_activity: Instant::now(),
|
|
||||||
};
|
|
||||||
|
|
||||||
(conn, rx_from_smol, tx_to_smol)
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if socket.can_recv() {
|
|
||||||
while let Ok((data, metadata)) = socket.recv() {
|
|
||||||
self.client_endpoint = Some(metadata.endpoint);
|
|
||||||
|
|
||||||
if self.tx.try_send(Bytes::copy_from_slice(data)).is_ok() {
|
|
||||||
self.last_activity = Instant::now();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
match socket.send_slice(&data, endpoint) {
|
|
||||||
Ok(_) => {
|
|
||||||
self.last_activity = Instant::now();
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+148
-4
@@ -1,10 +1,154 @@
|
|||||||
|
use uniffi;
|
||||||
uniffi::setup_scaffolding!();
|
uniffi::setup_scaffolding!();
|
||||||
|
|
||||||
pub mod connections;
|
mod net;
|
||||||
pub mod session;
|
mod tun;
|
||||||
pub mod tun;
|
pub use crate::tun::{routing, tun::Tun}; //for desktop test in main.rs
|
||||||
|
|
||||||
use std::sync::OnceLock;
|
use crate::{
|
||||||
|
net::engine::{EngineBuilder, EngineConfig},
|
||||||
|
tun::routing::reset_platform_routing,
|
||||||
|
};
|
||||||
|
use netrunner_logger::{error, info};
|
||||||
|
use std::sync::{Arc, OnceLock};
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
pub static RUNTIME: OnceLock<Runtime> = OnceLock::new();
|
pub static RUNTIME: OnceLock<Runtime> = OnceLock::new();
|
||||||
|
|
||||||
|
// Инициализация Tokio Runtime
|
||||||
|
fn get_runtime() -> &'static Runtime {
|
||||||
|
RUNTIME.get_or_init(|| {
|
||||||
|
tokio::runtime::Builder::new_multi_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create tokio runtime")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// SESSION
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
#[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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// SESSION MANAGER (Публичный API UniFFI)
|
||||||
|
// ==========================================
|
||||||
|
|
||||||
|
#[derive(uniffi::Object)]
|
||||||
|
pub struct SessionManager;
|
||||||
|
|
||||||
|
#[uniffi::export]
|
||||||
|
impl SessionManager {
|
||||||
|
pub(crate) fn spawn_session(
|
||||||
|
&self,
|
||||||
|
remote_address: String,
|
||||||
|
tun_fd: Option<i32>,
|
||||||
|
cache_dir: String,
|
||||||
|
) -> Arc<Session> {
|
||||||
|
let runtime = get_runtime();
|
||||||
|
let cancel_token = CancellationToken::new();
|
||||||
|
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();
|
||||||
|
|
||||||
|
// 1. Создаем базовый конфиг
|
||||||
|
let mut config = EngineConfig::new(&remote_address).with_cache_path(&cache_dir);
|
||||||
|
|
||||||
|
// 2. Тонкая настройка под платформу
|
||||||
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
|
{
|
||||||
|
// На мобилках роутингом обычно управляет VpnService (Android) или NEPacketTunnelProvider (iOS)
|
||||||
|
// Поэтому отключаем попытки движка менять системные таблицы роутинга напрямую
|
||||||
|
config = config.disable_routing().with_mtu(1280);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
config = config.with_mtu(1350);
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.spawn(async move {
|
||||||
|
info!("Starting VPN session thread...");
|
||||||
|
|
||||||
|
// 3. Инициализация TUN устройства (специфично для платформ)
|
||||||
|
let tun_device = {
|
||||||
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
|
{
|
||||||
|
Tun::from_fd(tun_fd.expect("TUN FD required on mobile"))
|
||||||
|
.expect("Failed to init TUN from FD")
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
{
|
||||||
|
Tun::create(|tun_cfg| {
|
||||||
|
tun_cfg
|
||||||
|
.tun_name("netr0")
|
||||||
|
.address((10, 0, 0, 1))
|
||||||
|
.netmask((255, 255, 255, 0))
|
||||||
|
.mtu(config.mtu as u16) // Используем MTU из нашего конфига
|
||||||
|
.up();
|
||||||
|
})
|
||||||
|
.expect("Failed to init TUN")
|
||||||
|
}
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
{
|
||||||
|
Tun::create(|tun_cfg| {
|
||||||
|
tun_cfg.tun_name("netr0");
|
||||||
|
})
|
||||||
|
.expect("Failed to init TUN")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 4. Используем обновленный билдер
|
||||||
|
let builder_result = EngineBuilder::new(config)
|
||||||
|
.with_tun(tun_device)
|
||||||
|
.build()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
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: session_token,
|
||||||
|
proxy_ip: remote_proxy_ip,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+24
-12
@@ -1,5 +1,10 @@
|
|||||||
use netrunner_client::tun::{engine::EngineBuilder, routing::reset_platform_routing, tun::Tun};
|
|
||||||
use netrunner_logger::{error, info};
|
use netrunner_logger::{error, info};
|
||||||
|
mod net;
|
||||||
|
mod tun;
|
||||||
|
|
||||||
|
// Импортируем и Билдер, и Конфиг
|
||||||
|
use crate::tun::{routing::reset_platform_routing, tun::Tun};
|
||||||
|
use net::engine::{EngineBuilder, EngineConfig};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
@@ -8,27 +13,34 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let remote_address = "147.45.43.70:443";
|
let remote_address = "147.45.43.70:443";
|
||||||
|
|
||||||
// 1. Создаем TUN интерфейс (зависит от платформы, поэтому делаем тут)
|
// 1. Создаем конфигурацию движка
|
||||||
let tun_device = Tun::create(|config| {
|
// Здесь мы можем гибко настроить параметры, которые раньше были захардкожены
|
||||||
config
|
let config = EngineConfig::new(remote_address)
|
||||||
|
.with_cache_path(".")
|
||||||
|
.with_mtu(1350); // Указываем MTU здесь, чтобы использовать его и для TUN, и для стека
|
||||||
|
|
||||||
|
// 2. Создаем TUN интерфейс
|
||||||
|
// Используем значение MTU из конфига, чтобы данные были синхронизированы
|
||||||
|
let tun_device = Tun::create(|tun_cfg| {
|
||||||
|
tun_cfg
|
||||||
.tun_name("netr0")
|
.tun_name("netr0")
|
||||||
.address((10, 0, 0, 1))
|
.address((10, 0, 0, 1))
|
||||||
.netmask((255, 255, 255, 0))
|
.netmask((255, 255, 255, 0))
|
||||||
.destination((10, 0, 0, 2))
|
.destination((10, 0, 0, 2))
|
||||||
|
.mtu(config.mtu as u16)
|
||||||
.up();
|
.up();
|
||||||
})
|
})
|
||||||
.expect("Failed to initialize TUN device");
|
.expect("Failed to initialize TUN device");
|
||||||
|
|
||||||
info!("TUN interface is UP: 10.0.0.1/24");
|
info!("TUN interface is UP: 10.0.0.1/24 (MTU: {})", config.mtu);
|
||||||
|
|
||||||
// 2. Собираем движок через наш новый Builder
|
// 3. Собираем движок, передавая объект конфигурации
|
||||||
let builder_result = EngineBuilder::new(remote_address)
|
let builder_result = EngineBuilder::new(config)
|
||||||
.with_cache_path(".")
|
|
||||||
.with_tun(tun_device)
|
.with_tun(tun_device)
|
||||||
.build()
|
.build()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// 3. Обрабатываем результат и запускаем цикл
|
// 4. Обрабатываем результат и запускаем цикл
|
||||||
match builder_result {
|
match builder_result {
|
||||||
Ok((mut engine, tun)) => {
|
Ok((mut engine, tun)) => {
|
||||||
info!("Engine starting process loop...");
|
info!("Engine starting process loop...");
|
||||||
@@ -36,8 +48,8 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let ctrl_c = tokio::signal::ctrl_c();
|
let ctrl_c = tokio::signal::ctrl_c();
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
res = engine.run(tun) => {
|
_res = engine.run(tun) => {
|
||||||
error!("Engine loop error: {:?}", res);
|
info!("Engine loop finished");
|
||||||
},
|
},
|
||||||
_ = ctrl_c => {
|
_ = ctrl_c => {
|
||||||
info!("Ctrl+C received, shutting down...");
|
info!("Ctrl+C received, shutting down...");
|
||||||
@@ -49,7 +61,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Очистка системных роутов при любом сценарии выхода (ошибка или Ctrl+C)
|
// 5. Очистка системных роутов
|
||||||
info!("Restoring system routing...");
|
info!("Restoring system routing...");
|
||||||
let addr: std::net::SocketAddr = remote_address.parse().expect("Invalid address format");
|
let addr: std::net::SocketAddr = remote_address.parse().expect("Invalid address format");
|
||||||
let p_ip = addr.ip().to_string();
|
let p_ip = addr.ip().to_string();
|
||||||
|
|||||||
@@ -1,9 +1,46 @@
|
|||||||
|
use crate::net::CHANNEL_CAPACITY;
|
||||||
use bytes::{Buf, Bytes, BytesMut};
|
use bytes::{Buf, Bytes, BytesMut};
|
||||||
use smoltcp::iface::SocketHandle;
|
use smoltcp::{
|
||||||
use smoltcp::socket::tcp;
|
iface::SocketHandle,
|
||||||
use tokio::sync::{mpsc, oneshot};
|
socket::{tcp, udp},
|
||||||
|
wire::IpEndpoint,
|
||||||
|
};
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::{
|
||||||
|
sync::{mpsc, oneshot},
|
||||||
|
time::Instant,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::connections::CHANNEL_CAPACITY;
|
// ============================================================================
|
||||||
|
// 1. БАЗОВАЯ СТРУКТУРА (ConnectionCore)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
/// Фундамент для любого соединения.
|
||||||
|
/// Инициализирует и хранит каналы связи между smoltcp и Muxer'ом.
|
||||||
|
pub struct ConnectionCore {
|
||||||
|
pub handle: SocketHandle,
|
||||||
|
pub tx: mpsc::Sender<Bytes>,
|
||||||
|
pub rx: mpsc::Receiver<Bytes>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConnectionCore {
|
||||||
|
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);
|
||||||
|
|
||||||
|
let core = Self {
|
||||||
|
handle,
|
||||||
|
tx: tx_to_net,
|
||||||
|
rx: rx_from_net,
|
||||||
|
};
|
||||||
|
|
||||||
|
(core, rx_from_smol, tx_to_smol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 2. TCP СОЕДИНЕНИЕ (TcpConnection)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
pub enum ConnectionState {
|
pub enum ConnectionState {
|
||||||
Established,
|
Established,
|
||||||
@@ -12,18 +49,16 @@ pub enum ConnectionState {
|
|||||||
Closed,
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAX_PENDING: usize = 64 * 1024;
|
||||||
|
const TCP_CHUNK_SIZE: usize = 1024 * 16;
|
||||||
|
|
||||||
pub struct TcpConnection {
|
pub struct TcpConnection {
|
||||||
pub handle: SocketHandle,
|
core: ConnectionCore,
|
||||||
state: ConnectionState,
|
state: ConnectionState,
|
||||||
tx: mpsc::Sender<Bytes>,
|
|
||||||
rx: mpsc::Receiver<Bytes>,
|
|
||||||
pending_data: BytesMut,
|
pending_data: BytesMut,
|
||||||
handshake_rx: Option<oneshot::Receiver<()>>,
|
handshake_rx: Option<oneshot::Receiver<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_PENDING: usize = 64 * 1024;
|
|
||||||
const TCP_CHUNK_SIZE: usize = 1024 * 16;
|
|
||||||
|
|
||||||
impl TcpConnection {
|
impl TcpConnection {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
handle: SocketHandle,
|
handle: SocketHandle,
|
||||||
@@ -33,15 +68,12 @@ impl TcpConnection {
|
|||||||
mpsc::Sender<Bytes>,
|
mpsc::Sender<Bytes>,
|
||||||
oneshot::Sender<()>,
|
oneshot::Sender<()>,
|
||||||
) {
|
) {
|
||||||
let (tx_to_net, rx_from_smol) = mpsc::channel::<Bytes>(CHANNEL_CAPACITY);
|
let (core, rx_from_smol, tx_to_smol) = ConnectionCore::new(handle);
|
||||||
let (tx_to_smol, rx_from_net) = mpsc::channel::<Bytes>(CHANNEL_CAPACITY);
|
|
||||||
let (handshake_tx, handshake_rx) = oneshot::channel();
|
let (handshake_tx, handshake_rx) = oneshot::channel();
|
||||||
|
|
||||||
let conn = Self {
|
let conn = Self {
|
||||||
handle,
|
core,
|
||||||
state: ConnectionState::Handshaking,
|
state: ConnectionState::Handshaking,
|
||||||
tx: tx_to_net,
|
|
||||||
rx: rx_from_net,
|
|
||||||
pending_data: BytesMut::new(),
|
pending_data: BytesMut::new(),
|
||||||
handshake_rx: Some(handshake_rx),
|
handshake_rx: Some(handshake_rx),
|
||||||
};
|
};
|
||||||
@@ -49,6 +81,14 @@ impl TcpConnection {
|
|||||||
(conn, rx_from_smol, tx_to_smol, handshake_tx)
|
(conn, rx_from_smol, tx_to_smol, handshake_tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_finished(&self, socket: &tcp::Socket) -> bool {
|
||||||
|
matches!(socket.state(), tcp::State::Closed | tcp::State::TimeWait)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _is_active(&self) -> bool {
|
||||||
|
matches!(self.state, ConnectionState::Active)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self, socket: &mut tcp::Socket) -> bool {
|
pub fn tick(&mut self, socket: &mut tcp::Socket) -> bool {
|
||||||
let state = socket.state();
|
let state = socket.state();
|
||||||
|
|
||||||
@@ -87,28 +127,21 @@ impl TcpConnection {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionState::Closed => {
|
ConnectionState::Closed => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_finished(&self, socket: &tcp::Socket) -> bool {
|
|
||||||
use tcp::State;
|
|
||||||
matches!(socket.state(), State::Closed | State::TimeWait)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_active(&self) -> bool {
|
|
||||||
matches!(self.state, ConnectionState::Active)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll_and_process(&mut self, socket: &mut tcp::Socket) {
|
fn poll_and_process(&mut self, socket: &mut tcp::Socket) {
|
||||||
|
// 1. Вычитываем данные из smoltcp и шлем в Muxer
|
||||||
while socket.can_recv() {
|
while socket.can_recv() {
|
||||||
let mut full = false;
|
let mut full = false;
|
||||||
|
|
||||||
let mut temp = [0u8; TCP_CHUNK_SIZE];
|
let mut temp = [0u8; TCP_CHUNK_SIZE];
|
||||||
|
|
||||||
if let Ok(n) = socket.peek_slice(&mut temp) {
|
if let Ok(n) = socket.peek_slice(&mut temp) {
|
||||||
@@ -117,7 +150,7 @@ impl TcpConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let chunk = Bytes::copy_from_slice(&temp[..n]);
|
let chunk = Bytes::copy_from_slice(&temp[..n]);
|
||||||
match self.tx.try_send(chunk) {
|
match self.core.tx.try_send(chunk) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
socket.recv_slice(&mut temp[..n]).unwrap();
|
socket.recv_slice(&mut temp[..n]).unwrap();
|
||||||
}
|
}
|
||||||
@@ -138,31 +171,31 @@ impl TcpConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 2. Читаем данные из Muxer'а с учетом Backpressure
|
||||||
let current_pending = self.pending_data.len();
|
let current_pending = self.pending_data.len();
|
||||||
|
|
||||||
let fill_ratio = (current_pending as f32 / MAX_PENDING as f32) * 100.0;
|
let fill_ratio = (current_pending as f32 / MAX_PENDING as f32) * 100.0;
|
||||||
|
|
||||||
if current_pending >= MAX_PENDING {
|
if current_pending >= MAX_PENDING {
|
||||||
netrunner_logger::warn!(
|
netrunner_logger::warn!(
|
||||||
%self.handle,
|
%self.core.handle,
|
||||||
"Backpressure ACTIVE: Buffer is FULL ({} bytes). Stalling RX channel.",
|
"Backpressure ACTIVE: Buffer is FULL ({} bytes). Stalling RX channel.",
|
||||||
current_pending
|
current_pending
|
||||||
);
|
);
|
||||||
} else if fill_ratio > 80.0 {
|
} else if fill_ratio > 80.0 {
|
||||||
netrunner_logger::info!(
|
netrunner_logger::info!(
|
||||||
%self.handle,
|
%self.core.handle,
|
||||||
"Bufferbloat Warning: Buffer {:.1}% full ({} bytes). Latency increasing.",
|
"Bufferbloat Warning: Buffer {:.1}% full ({} bytes). Latency increasing.",
|
||||||
fill_ratio, current_pending
|
fill_ratio, current_pending
|
||||||
);
|
);
|
||||||
|
|
||||||
while let Ok(data) = self.rx.try_recv() {
|
while let Ok(data) = self.core.rx.try_recv() {
|
||||||
self.pending_data.extend_from_slice(&data);
|
self.pending_data.extend_from_slice(&data);
|
||||||
if self.pending_data.len() >= MAX_PENDING {
|
if self.pending_data.len() >= MAX_PENDING {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while let Ok(data) = self.rx.try_recv() {
|
while let Ok(data) = self.core.rx.try_recv() {
|
||||||
self.pending_data.extend_from_slice(&data);
|
self.pending_data.extend_from_slice(&data);
|
||||||
if self.pending_data.len() >= MAX_PENDING {
|
if self.pending_data.len() >= MAX_PENDING {
|
||||||
break;
|
break;
|
||||||
@@ -170,19 +203,90 @@ impl TcpConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3. Отправляем буферизированные данные в smoltcp
|
||||||
if !self.pending_data.is_empty() && socket.can_send() {
|
if !self.pending_data.is_empty() && socket.can_send() {
|
||||||
match socket.send_slice(&self.pending_data) {
|
match socket.send_slice(&self.pending_data) {
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
self.pending_data.advance(n);
|
self.pending_data.advance(n);
|
||||||
|
|
||||||
if n > 0 && self.pending_data.len() < (MAX_PENDING / 2) && fill_ratio > 90.0 {
|
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());
|
netrunner_logger::info!(
|
||||||
|
%self.core.handle,
|
||||||
|
"Backpressure RELIEVED: Buffer drained to {} bytes",
|
||||||
|
self.pending_data.len()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
netrunner_logger::debug!(%self.handle, "Smoltcp socket send error: {:?}", e);
|
netrunner_logger::debug!(%self.core.handle, "Smoltcp socket send error: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 3. UDP СОЕДИНЕНИЕ (UdpConnection)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
const UDP_TIMEOUT: Duration = Duration::from_secs(60);
|
||||||
|
|
||||||
|
pub struct UdpConnection {
|
||||||
|
core: ConnectionCore,
|
||||||
|
client_endpoint: Option<IpEndpoint>,
|
||||||
|
last_activity: Instant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UdpConnection {
|
||||||
|
pub fn new(handle: SocketHandle) -> (Self, mpsc::Receiver<Bytes>, mpsc::Sender<Bytes>) {
|
||||||
|
let (core, rx_from_smol, tx_to_smol) = ConnectionCore::new(handle);
|
||||||
|
|
||||||
|
let conn = Self {
|
||||||
|
core,
|
||||||
|
client_endpoint: None,
|
||||||
|
last_activity: Instant::now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
(conn, rx_from_smol, tx_to_smol)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(&mut self, socket: &mut udp::Socket) -> bool {
|
||||||
|
// Проверка таймаута
|
||||||
|
if self.last_activity.elapsed() > UDP_TIMEOUT {
|
||||||
|
netrunner_logger::debug!(%self.core.handle, "UDP Session closed due to timeout");
|
||||||
|
socket.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Читаем из smoltcp и шлем в сеть
|
||||||
|
if socket.can_recv() {
|
||||||
|
while let Ok((data, metadata)) = socket.recv() {
|
||||||
|
self.client_endpoint = Some(metadata.endpoint);
|
||||||
|
|
||||||
|
if self.core.tx.try_send(Bytes::copy_from_slice(data)).is_ok() {
|
||||||
|
self.last_activity = Instant::now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Читаем из сети и шлем в smoltcp
|
||||||
|
if socket.can_send() {
|
||||||
|
if let Some(endpoint) = self.client_endpoint {
|
||||||
|
while let Ok(data) = self.core.rx.try_recv() {
|
||||||
|
if data.is_empty() {
|
||||||
|
socket.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if socket.send_slice(&data, endpoint).is_ok() {
|
||||||
|
self.last_activity = Instant::now();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ use netrunner_core::{
|
|||||||
protocol::codec::{frame::FrameType, socks::TargetAddress},
|
protocol::codec::{frame::FrameType, socks::TargetAddress},
|
||||||
proxy::connection::muxer::{MuxMessage, Muxer},
|
proxy::connection::muxer::{MuxMessage, Muxer},
|
||||||
};
|
};
|
||||||
use netrunner_logger::{debug, error, info, warn};
|
use netrunner_logger::{debug, info, warn};
|
||||||
use smoltcp::{
|
use smoltcp::{
|
||||||
iface::{SocketHandle, SocketSet},
|
iface::{SocketHandle, SocketSet},
|
||||||
socket::{AnySocket, icmp, tcp, udp},
|
socket::{AnySocket, icmp, tcp, udp},
|
||||||
@@ -12,9 +12,11 @@ use smoltcp::{
|
|||||||
use std::{collections::HashMap, time::Duration, time::Instant as StdInstant};
|
use std::{collections::HashMap, time::Duration, time::Instant as StdInstant};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::connections::{
|
use crate::net::{
|
||||||
CHANNEL_CAPACITY, dns::DnsHandler, ip_store::FakeIpStore, tcp_connection::TcpConnection,
|
CHANNEL_CAPACITY,
|
||||||
udp_connection::UdpConnection,
|
connection::{TcpConnection, UdpConnection},
|
||||||
|
dns::DnsHandler,
|
||||||
|
ip_store::FakeIpStore,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::connections::ip_store::FakeIpStore;
|
use crate::net::ip_store::FakeIpStore;
|
||||||
use hickory_proto::op::{Message, MessageType, ResponseCode};
|
use hickory_proto::op::{Message, MessageType, ResponseCode};
|
||||||
use hickory_proto::rr::{RData, Record, RecordType};
|
use hickory_proto::rr::{RData, Record, RecordType};
|
||||||
use netrunner_logger::{debug, error, info};
|
use netrunner_logger::{debug, error, info};
|
||||||
@@ -20,8 +20,8 @@ use tun::{DeviceReader, DeviceWriter};
|
|||||||
|
|
||||||
use netrunner_logger::{debug, error, info, warn};
|
use netrunner_logger::{debug, error, info, warn};
|
||||||
|
|
||||||
use crate::connections::dns::DnsHandler;
|
use crate::net::connection_manager::ConnectionManager;
|
||||||
use crate::tun::connection_manager::ConnectionManager;
|
use crate::net::dns::DnsHandler;
|
||||||
use crate::tun::device::{TokenBuffer, VirtTunDevice};
|
use crate::tun::device::{TokenBuffer, VirtTunDevice};
|
||||||
use crate::tun::routing::setup_platform_routing;
|
use crate::tun::routing::setup_platform_routing;
|
||||||
use crate::tun::tun::Tun;
|
use crate::tun::tun::Tun;
|
||||||
@@ -216,18 +216,31 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EngineBuilder {
|
// ============================================================================
|
||||||
remote_address: String,
|
// КОНФИГУРАЦИЯ ДВИЖКА
|
||||||
cache_path: String,
|
// ============================================================================
|
||||||
tun_device: Option<Tun>,
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct EngineConfig {
|
||||||
|
pub remote_address: String,
|
||||||
|
pub cache_path: String,
|
||||||
|
pub mtu: usize,
|
||||||
|
pub setup_routing: bool,
|
||||||
|
pub any_ip: bool,
|
||||||
|
pub transparent_mode: bool,
|
||||||
|
pub default_gateway: Ipv4Addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EngineBuilder {
|
impl EngineConfig {
|
||||||
pub fn new(remote_address: impl Into<String>) -> Self {
|
pub fn new(remote_address: impl Into<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
remote_address: remote_address.into(),
|
remote_address: remote_address.into(),
|
||||||
cache_path: ".".to_string(),
|
cache_path: ".".to_string(),
|
||||||
tun_device: None,
|
mtu: 1350,
|
||||||
|
setup_routing: true,
|
||||||
|
any_ip: true,
|
||||||
|
transparent_mode: true,
|
||||||
|
default_gateway: Ipv4Addr::new(10, 0, 0, 2),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +249,36 @@ impl EngineBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_mtu(mut self, mtu: usize) -> Self {
|
||||||
|
self.mtu = mtu;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _disable_routing(mut self) -> Self {
|
||||||
|
self.setup_routing = false;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// БИЛДЕР ДВИЖКА
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
pub struct EngineBuilder {
|
||||||
|
config: EngineConfig,
|
||||||
|
tun_device: Option<Tun>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EngineBuilder {
|
||||||
|
/// Инициализируем билдер на основе готового конфига
|
||||||
|
pub fn new(config: EngineConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
config,
|
||||||
|
tun_device: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Передаем TUN интерфейс (зависит от платформы, поэтому не в конфиге)
|
||||||
pub fn with_tun(mut self, tun: Tun) -> Self {
|
pub fn with_tun(mut self, tun: Tun) -> Self {
|
||||||
self.tun_device = Some(tun);
|
self.tun_device = Some(tun);
|
||||||
self
|
self
|
||||||
@@ -244,35 +287,53 @@ impl EngineBuilder {
|
|||||||
pub async fn build(self) -> Result<(Engine, Tun), String> {
|
pub async fn build(self) -> Result<(Engine, Tun), String> {
|
||||||
let tun = self.tun_device.ok_or("TUN device is required")?;
|
let tun = self.tun_device.ok_or("TUN device is required")?;
|
||||||
|
|
||||||
info!("Initializing Engine components...");
|
info!(
|
||||||
|
"Initializing Engine components with config: {:?}",
|
||||||
|
self.config
|
||||||
|
);
|
||||||
|
|
||||||
let mut dns_handler = DnsHandler::new(&self.cache_path);
|
// 1. Инициализация DNS
|
||||||
|
let mut dns_handler = DnsHandler::new(&self.config.cache_path);
|
||||||
if let Err(e) = dns_handler.init().await {
|
if let Err(e) = dns_handler.init().await {
|
||||||
error!("Failed to initialize DNS blocklist: {}", e);
|
error!("Failed to initialize DNS blocklist: {}", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = setup_platform_routing(&self.remote_address) {
|
// 2. Настройка системного роутинга (Опционально)
|
||||||
|
if self.config.setup_routing {
|
||||||
|
info!("Applying platform routing rules...");
|
||||||
|
if let Err(e) = setup_platform_routing(&self.config.remote_address) {
|
||||||
return Err(format!("Routing setup failed: {}", e));
|
return Err(format!("Routing setup failed: {}", e));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
info!("Platform routing setup skipped via config.");
|
||||||
|
}
|
||||||
|
|
||||||
let config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
// 3. Конфигурация интерфейса smoltcp
|
||||||
|
let smol_config = Config::new(smoltcp::wire::HardwareAddress::Ip);
|
||||||
let mut caps = DeviceCapabilities::default();
|
let mut caps = DeviceCapabilities::default();
|
||||||
caps.max_transmission_unit = 1350;
|
caps.max_transmission_unit = self.config.mtu; // Берем из конфига
|
||||||
caps.medium = smoltcp::phy::Medium::Ip;
|
caps.medium = smoltcp::phy::Medium::Ip;
|
||||||
|
|
||||||
|
// 4. Подключение к серверу
|
||||||
info!("Establishing secure tunnel to proxy server...");
|
info!("Establishing secure tunnel to proxy server...");
|
||||||
let muxer = ClientHandler::connect(&self.remote_address)
|
let muxer = ClientHandler::connect(&self.config.remote_address)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("Failed to establish secure tunnel: {}", e))?;
|
.map_err(|e| format!("Failed to establish secure tunnel: {}", e))?;
|
||||||
info!("Secure tunnel established, Muxer is ready.");
|
info!("Secure tunnel established, Muxer is ready.");
|
||||||
|
|
||||||
let mut engine = Engine::new(config, caps, dns_handler, muxer);
|
// 5. Инициализация и настройка Engine
|
||||||
engine.set_any_ip(true);
|
let mut engine = Engine::new(smol_config, caps, dns_handler, muxer);
|
||||||
|
|
||||||
|
engine.set_any_ip(self.config.any_ip);
|
||||||
|
|
||||||
|
if self.config.transparent_mode {
|
||||||
engine.set_transparent_mode();
|
engine.set_transparent_mode();
|
||||||
engine.set_default_gateway(Ipv4Addr::new(10, 0, 0, 2));
|
}
|
||||||
|
|
||||||
|
engine.set_default_gateway(self.config.default_gateway);
|
||||||
engine.activate();
|
engine.activate();
|
||||||
|
|
||||||
info!("Stack IP initialized: 10.0.0.2");
|
info!("Stack IP initialized: {}", self.config.default_gateway);
|
||||||
|
|
||||||
Ok((engine, tun))
|
Ok((engine, tun))
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ use std::num::NonZeroUsize;
|
|||||||
|
|
||||||
pub struct FakeIpStore {
|
pub struct FakeIpStore {
|
||||||
cache: LruCache<String, Ipv4Addr>,
|
cache: LruCache<String, Ipv4Addr>,
|
||||||
pub rev_cache: LruCache<Ipv4Addr, String>,
|
rev_cache: LruCache<Ipv4Addr, String>,
|
||||||
next_ip: u32,
|
next_ip: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
|
mod connection;
|
||||||
|
pub mod connection_manager;
|
||||||
pub mod dns;
|
pub mod dns;
|
||||||
|
pub mod engine;
|
||||||
pub mod ip_store;
|
pub mod ip_store;
|
||||||
pub mod tcp_connection;
|
|
||||||
pub mod udp_connection;
|
|
||||||
|
|
||||||
pub const CHANNEL_CAPACITY: usize = 16;
|
pub const CHANNEL_CAPACITY: usize = 16;
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
use super::{Session, SessionManager};
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
impl SessionManager {
|
|
||||||
pub fn start_desktop(&self, remote_address: String) -> Arc<Session> {
|
|
||||||
self.spawn_session(remote_address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
use super::{Session, SessionManager};
|
|
||||||
use std::sync::Arc;
|
|
||||||
use uniffi;
|
|
||||||
|
|
||||||
#[uniffi::export]
|
|
||||||
impl SessionManager {
|
|
||||||
pub fn start_mobile(
|
|
||||||
&self,
|
|
||||||
remote_address: String,
|
|
||||||
tun_fd: i32,
|
|
||||||
cache_dir: String,
|
|
||||||
) -> Arc<Session> {
|
|
||||||
self.spawn_session(remote_address, Some(tun_fd), cache_dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_desktop(&self, remote_address: String, cache_dir: String) -> Arc<Session> {
|
|
||||||
self.spawn_session(remote_address, None, cache_dir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
fn get_runtime() -> &'static Runtime {
|
|
||||||
RUNTIME.get_or_init(|| {
|
|
||||||
tokio::runtime::Builder::new_multi_thread()
|
|
||||||
.enable_all()
|
|
||||||
.build()
|
|
||||||
.expect("Failed to create tokio 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;
|
|
||||||
|
|
||||||
#[uniffi::export]
|
|
||||||
impl SessionManager {
|
|
||||||
#[uniffi::constructor]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
netrunner_logger::Logger::init();
|
|
||||||
info!("SessionManager initialized");
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SessionManager {
|
|
||||||
pub(crate) fn spawn_session(
|
|
||||||
&self,
|
|
||||||
remote_address: String,
|
|
||||||
#[cfg(any(target_os = "android", target_os = "ios"))] tun_fd: Option<i32>,
|
|
||||||
#[cfg(any(target_os = "android", target_os = "ios"))] cache_dir: String,
|
|
||||||
) -> Arc<Session> {
|
|
||||||
let runtime = get_runtime();
|
|
||||||
let cancel_token = CancellationToken::new();
|
|
||||||
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();
|
|
||||||
|
|
||||||
runtime.spawn(async move {
|
|
||||||
info!("Starting VPN session thread...");
|
|
||||||
|
|
||||||
let cache_path = {
|
|
||||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
|
||||||
{
|
|
||||||
cache_dir
|
|
||||||
}
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
|
||||||
{
|
|
||||||
".".to_string()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let tun_device = {
|
|
||||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
|
||||||
{
|
|
||||||
Tun::from_fd(tun_fd.expect("TUN FD required on mobile"))
|
|
||||||
.expect("Failed to init TUN from FD")
|
|
||||||
}
|
|
||||||
#[cfg(target_os = "linux")]
|
|
||||||
{
|
|
||||||
Tun::create(|config| {
|
|
||||||
config
|
|
||||||
.tun_name("netr0")
|
|
||||||
.address((10, 0, 0, 1))
|
|
||||||
.netmask((255, 255, 255, 0))
|
|
||||||
.mtu(1350)
|
|
||||||
.up();
|
|
||||||
})
|
|
||||||
.expect("Failed to init TUN")
|
|
||||||
}
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
{
|
|
||||||
Tun::create(|config| {
|
|
||||||
config.tun_name("netr0");
|
|
||||||
})
|
|
||||||
.expect("Failed to init TUN")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let builder_result = EngineBuilder::new(&remote_address)
|
|
||||||
.with_cache_path(&cache_path)
|
|
||||||
.with_tun(tun_device)
|
|
||||||
.build()
|
|
||||||
.await;
|
|
||||||
|
|
||||||
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: session_token,
|
|
||||||
proxy_ip: remote_proxy_ip,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
pub mod connection_manager;
|
|
||||||
pub mod device;
|
pub mod device;
|
||||||
pub mod engine;
|
|
||||||
pub mod routing;
|
pub mod routing;
|
||||||
pub mod tun;
|
pub mod tun;
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ pub struct Tun {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Tun {
|
impl Tun {
|
||||||
pub fn build() -> Configuration {
|
|
||||||
Configuration::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(config: &Configuration) -> io::Result<Self> {
|
pub fn new(config: &Configuration) -> io::Result<Self> {
|
||||||
match create_as_async(config) {
|
match create_as_async(config) {
|
||||||
Ok(device) => Ok(Self { device }),
|
Ok(device) => Ok(Self { device }),
|
||||||
|
|||||||
Reference in New Issue
Block a user