cliet tun core

This commit is contained in:
2026-03-05 19:55:05 +07:00
parent 9cc9b75123
commit 592005cbac
20 changed files with 525 additions and 2401 deletions
+144
View File
@@ -0,0 +1,144 @@
use smoltcp::time::Instant;
use smoltcp::{
iface::{Config, Interface, SocketSet},
phy::DeviceCapabilities,
};
use std::{
mem,
sync::{Arc, LazyLock, atomic::AtomicBool},
time::Instant as StdInstant,
};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
use tokio::time::{Duration, sleep};
use tun::{DeviceReader, DeviceWriter};
use tracing::{debug, warn};
use crate::tun::connection_manager::ConnectionManager;
use crate::tun::device::{TokenBuffer, VirtTunDevice};
use crate::tun::tun::Tun;
pub static START_TIME: LazyLock<StdInstant> = LazyLock::new(StdInstant::now);
pub struct Engine {
interface: Interface,
socket_set: SocketSet<'static>,
manager: ConnectionManager,
device: VirtTunDevice,
bridge_rx: UnboundedReceiver<TokenBuffer>,
bridge_tx: UnboundedSender<TokenBuffer>,
avail: Arc<AtomicBool>,
}
impl Engine {
pub fn new(config: Config, caps: DeviceCapabilities, ip: String) -> Self {
let now = Engine::current_time();
let (mut device, bridge_rx, bridge_tx, avail) = VirtTunDevice::new(caps);
let interface = Interface::new(config, &mut device, now);
let socket_set = SocketSet::new(vec![]);
Self {
interface,
socket_set,
device,
bridge_tx,
bridge_rx,
avail,
manager: ConnectionManager::new(ip),
}
}
pub async fn run(&mut self, tun: Tun) {
//Bridge from tun to stack and stack to tun
let (writer, reader) = tun.split().expect("Failed to split TUN");
// Забираем bridge_rx, так как он нам нужен только в одной задаче
let from_engine = mem::replace(&mut self.bridge_rx, mpsc::unbounded_channel().1);
Self::spawn_tun_to_engine(reader, self.bridge_tx.clone(), self.avail.clone());
Self::spawn_engine_to_tun(writer, from_engine);
loop {
self.manager.refill_sockets(&mut self.socket_set);
self.poll();
self.manager.process_sockets(&mut self.socket_set);
if self.avail.load(std::sync::atomic::Ordering::Acquire) {
tokio::task::yield_now().await;
continue;
}
self.poll_delay().await;
}
}
pub fn poll(&mut self) {
let now = Self::current_time();
// Передаем девайс и сокеты в интерфейс
self.interface
.poll(now, &mut self.device, &mut self.socket_set);
}
pub async fn poll_delay(&mut self) {
let timestamp = Self::current_time();
let delay = self.interface.poll_delay(timestamp, &self.socket_set);
let sleep_duration = match delay {
Some(d) => Duration::from_micros(d.micros()),
None => Duration::from_millis(10),
};
sleep(sleep_duration).await;
}
fn spawn_tun_to_engine(
mut reader: DeviceReader,
to_engine: UnboundedSender<TokenBuffer>,
is_avail: Arc<AtomicBool>,
) {
tokio::spawn(async move {
debug!("TUN-to-Engine bridge task started");
let mut buf = [0u8; 4096];
while let Ok(n) = reader.read(&mut buf).await {
if n == 0 {
break;
}
let mut token = TokenBuffer::with_capacity(n);
token.extend_from_slice(&buf[..n]);
if to_engine.send(token).is_ok() {
is_avail.store(true, std::sync::atomic::Ordering::Release);
} else {
break;
}
}
warn!("TUN-to-Engine bridge task stopped");
});
}
fn spawn_engine_to_tun(
mut writer: DeviceWriter,
mut from_engine: UnboundedReceiver<TokenBuffer>,
) {
tokio::spawn(async move {
debug!("Engine-to-TUN bridge task started");
while let Some(token) = from_engine.recv().await {
if writer.write_all(&token).await.is_err() {
break;
}
}
warn!("Engine-to-TUN bridge task stopped");
});
}
fn current_time() -> Instant {
let duration = StdInstant::now().duration_since(*START_TIME);
Instant::from_micros(duration.as_micros() as i64)
}
pub fn add_address(&mut self, address: smoltcp::wire::IpCidr) {
self.interface.update_ip_addrs(|addrs| {
addrs
.push(address)
.expect("Failed to add IP: address list is full");
});
self.interface
.routes_mut()
.add_default_ipv4_route(smoltcp::wire::Ipv4Address::new(10, 0, 0, 1))
.ok();
}
}