stable connection
This commit is contained in:
@@ -209,7 +209,6 @@ impl TcpConnection {
|
||||
tx_tunnel: mpsc::Sender<RawCastFrame>,
|
||||
) {
|
||||
tokio::spawn(async move {
|
||||
// 1. Формируем и отправляем кадр на установку соединения
|
||||
let mut frame = RawCastFrame::connect(LocalProtocol::Tcp, socket_id, dst_ip, dst_port);
|
||||
frame.payload = Bytes::from(target);
|
||||
|
||||
@@ -218,10 +217,8 @@ impl TcpConnection {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Сигнализируем ConnectionManager, что запрос в туннель ушел успешно
|
||||
let _ = handshake_tx.send(());
|
||||
|
||||
// 3. Цикл пересылки данных из smoltcp -> туннель
|
||||
while let Some(data) = rx_smol.recv().await {
|
||||
let data_frame = RawCastFrame::data(
|
||||
LocalProtocol::Tcp,
|
||||
@@ -232,7 +229,7 @@ impl TcpConnection {
|
||||
);
|
||||
|
||||
if tx_tunnel.send(data_frame).await.is_err() {
|
||||
break; // Туннель закрыт
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,7 +325,6 @@ impl UdpConnection {
|
||||
tokio::spawn(async move {
|
||||
debug!("📡 [UDP {}] Task started for {}", socket_id, target);
|
||||
|
||||
// 1. Регистрация UDP сессии в туннеле
|
||||
let mut frame = RawCastFrame::connect(LocalProtocol::Udp, socket_id, dst_ip, dst_port);
|
||||
frame.payload = Bytes::from(target);
|
||||
|
||||
@@ -337,8 +333,6 @@ impl UdpConnection {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Цикл пересылки пакетов
|
||||
// rx_smol отдает кортеж (данные, ip, порт)
|
||||
while let Some((data, ip, port)) = rx_smol.recv().await {
|
||||
let data_frame =
|
||||
RawCastFrame::data(LocalProtocol::Udp, socket_id, ip, port, data.to_vec());
|
||||
@@ -366,12 +360,9 @@ impl IcmpResponder {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Сначала достаем данные и адрес
|
||||
let result = socket.recv();
|
||||
|
||||
if let Ok((data, src_addr)) = result {
|
||||
// 2. Копируем данные в Vec, чтобы разорвать связь с буфером сокета.
|
||||
// Теперь заимствование `socket` от метода .recv() закончилось.
|
||||
let payload = data.to_vec();
|
||||
|
||||
match src_addr {
|
||||
@@ -381,7 +372,6 @@ impl IcmpResponder {
|
||||
}
|
||||
}
|
||||
|
||||
// Принимаем Vec<u8>, чтобы не делать to_vec() второй раз внутри
|
||||
fn reply_v4(socket: &mut icmp::Socket, mut payload: Vec<u8>, src: IpAddress) {
|
||||
if let Ok(pkt) = Icmpv4Packet::new_checked(&payload) {
|
||||
if pkt.msg_type() == Icmpv4Message::EchoRequest {
|
||||
|
||||
@@ -162,7 +162,6 @@ impl DnsHandler {
|
||||
.set_recursion_available(true)
|
||||
.add_query(query.clone());
|
||||
|
||||
// 1. Проверка блокировок
|
||||
if self.forbidden_suffixes.iter().any(|s| name.ends_with(s))
|
||||
|| self.block_list.contains(&name)
|
||||
{
|
||||
@@ -171,7 +170,6 @@ impl DnsHandler {
|
||||
return res.to_vec().ok();
|
||||
}
|
||||
|
||||
// 2. Генерация Fake IP для A-записей
|
||||
if query.query_type() == RecordType::A {
|
||||
let fake_ip = store.get_or_assign(&name);
|
||||
res.add_answer(Record::from_rdata(
|
||||
@@ -181,7 +179,6 @@ impl DnsHandler {
|
||||
));
|
||||
res.set_response_code(ResponseCode::NoError);
|
||||
} else {
|
||||
// Для остальных типов записей (AAAA и т.д.) просто возвращаем пустой NoError или NXDomain
|
||||
res.set_response_code(ResponseCode::NoError);
|
||||
}
|
||||
|
||||
|
||||
@@ -289,7 +289,7 @@ impl EngineConfig {
|
||||
pub struct EngineBuilder {
|
||||
config: EngineConfig,
|
||||
tun_device: Option<Tun>,
|
||||
// Добавляем возможность прокинуть кастомную фабрику сокетов
|
||||
|
||||
socket_factory: Option<Arc<dyn SocketProvider>>,
|
||||
}
|
||||
|
||||
@@ -344,13 +344,10 @@ impl EngineBuilder {
|
||||
.map_err(|e| format!("Failed to establish secure tunnel: {}", e))?;
|
||||
|
||||
let factory = self.socket_factory.unwrap_or_else(|| {
|
||||
// 1. Разыменовываем ссылку и клонируем данные в новый объект
|
||||
let config_owned = (*NetworkConfig::global()).clone();
|
||||
|
||||
// 2. Оборачиваем во владеющий Arc
|
||||
let config = Arc::new(config_owned);
|
||||
|
||||
// Теперь типы совпадают: Arc<NetworkConfig> -> SmolSocketFactory::new
|
||||
Arc::new(SmolSocketFactory::new(config))
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ pub struct SessionTracker {
|
||||
active_udp: HashMap<SocketHandle, UdpConnection>,
|
||||
inbound_tx: HashMap<u64, mpsc::Sender<Bytes>>,
|
||||
handle_to_id: HashMap<SocketHandle, u64>,
|
||||
// 🔥 ДОБАВЛЕНО: Обратный маппинг, чтобы находить сокет по ID из туннеля
|
||||
|
||||
id_to_handle: HashMap<u64, SocketHandle>,
|
||||
pending_tcp: HashMap<SocketHandle, StdInstant>,
|
||||
to_remove: Vec<SocketHandle>,
|
||||
@@ -34,7 +34,7 @@ impl SessionTracker {
|
||||
active_udp: HashMap::new(),
|
||||
inbound_tx: HashMap::new(),
|
||||
handle_to_id: HashMap::new(),
|
||||
id_to_handle: HashMap::new(), // Инициализация
|
||||
id_to_handle: HashMap::new(),
|
||||
pending_tcp: HashMap::new(),
|
||||
to_remove: Vec::new(),
|
||||
next_socket_id: 1,
|
||||
@@ -60,10 +60,10 @@ impl SessionTracker {
|
||||
) {
|
||||
self.pending_tcp.remove(&handle);
|
||||
self.handle_to_id.insert(handle, id);
|
||||
self.id_to_handle.insert(id, handle); // 🔥 Регистрация обратного индекса
|
||||
self.id_to_handle.insert(id, handle);
|
||||
self.active_tcp.insert(handle, conn);
|
||||
self.inbound_tx.insert(id, tx);
|
||||
self.last_activity.insert(handle, StdInstant::now()); // Для TCP тоже полезно
|
||||
self.last_activity.insert(handle, StdInstant::now());
|
||||
}
|
||||
|
||||
pub fn register_udp(
|
||||
@@ -74,7 +74,7 @@ impl SessionTracker {
|
||||
tx: mpsc::Sender<Bytes>,
|
||||
) {
|
||||
self.handle_to_id.insert(handle, id);
|
||||
self.id_to_handle.insert(id, handle); // 🔥 Регистрация обратного индекса
|
||||
self.id_to_handle.insert(id, handle);
|
||||
self.active_udp.insert(handle, conn);
|
||||
self.inbound_tx.insert(id, tx);
|
||||
self.last_activity.insert(handle, StdInstant::now());
|
||||
@@ -128,7 +128,7 @@ impl SessionTracker {
|
||||
|
||||
pub fn close_tunnel_session(&mut self, id: u64) {
|
||||
self.inbound_tx.remove(&id);
|
||||
// 🔥 ИСПРАВЛЕНО: Теперь мы реально находим сокет и ставим его в очередь на удаление
|
||||
|
||||
if let Some(handle) = self.id_to_handle.remove(&id) {
|
||||
self.queue_removal(handle);
|
||||
}
|
||||
@@ -140,7 +140,6 @@ impl SessionTracker {
|
||||
}
|
||||
}
|
||||
|
||||
// 🔥 ДОБАВЛЕНО: Сборщик мусора для залипших сокетов
|
||||
pub fn enforce_idle_timeouts(&mut self, timeout: Duration) {
|
||||
let now = StdInstant::now();
|
||||
let mut ghosts = Vec::new();
|
||||
@@ -159,8 +158,6 @@ impl SessionTracker {
|
||||
|
||||
pub fn cleanup(&mut self, socket_set: &mut SocketSet) {
|
||||
for handle in self.to_remove.drain(..) {
|
||||
// Удаление из socket_set автоматически делает abort() внутри smoltcp
|
||||
// и освобождает память пула/буферов
|
||||
socket_set.remove(handle);
|
||||
|
||||
self.active_tcp.remove(&handle);
|
||||
|
||||
@@ -46,17 +46,15 @@ impl SmolSocketFactory {
|
||||
pub fn new(config: Arc<NetworkConfig>) -> Self {
|
||||
Self {
|
||||
config,
|
||||
// Пул на 128 тяжелых буферов. Если нужно больше — queue вернет ошибку,
|
||||
// и мы просто отдадим память ОС (что безопасно).
|
||||
|
||||
heavy_pool: Arc::new(ArrayQueue::new(128)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Берем буфер из пула или создаем новый, если пул пуст
|
||||
fn alloc_buf(&self, size: usize) -> Vec<u8> {
|
||||
if size == self.config.tcp_buf_heavy {
|
||||
if let Some(mut buf) = self.heavy_pool.pop() {
|
||||
buf.fill(0); // Очищаем данные от прошлой сессии
|
||||
buf.fill(0);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
@@ -144,7 +142,7 @@ impl SocketProvider for SmolSocketFactory {
|
||||
|
||||
fn create_base_set(&self, n_icmp: usize) -> SocketSet<'static> {
|
||||
let mut sockets = SocketSet::new(Vec::with_capacity(128));
|
||||
sockets.add(self.create_bound_udp(None, 53)); // DNS
|
||||
sockets.add(self.create_bound_udp(None, 53));
|
||||
for _ in 0..n_icmp {
|
||||
sockets.add(self.create_icmp());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user