perfect
This commit is contained in:
@@ -44,6 +44,8 @@ impl TunnelEngine {
|
||||
let leg_id = self.leg_id;
|
||||
let muxer = self.muxer.clone();
|
||||
|
||||
let muxer_pong = muxer.clone();
|
||||
|
||||
let token = CancellationToken::new();
|
||||
|
||||
let codec_reader = codec.clone();
|
||||
@@ -102,6 +104,10 @@ impl TunnelEngine {
|
||||
}
|
||||
|
||||
for frame in frames {
|
||||
if frame.header.frame_type == FrameType::Heartbeat {
|
||||
muxer.record_pong(leg_id).await;
|
||||
continue;
|
||||
}
|
||||
handler.handle(frame).await;
|
||||
}
|
||||
}
|
||||
@@ -134,6 +140,9 @@ impl TunnelEngine {
|
||||
}
|
||||
|
||||
_ = heartbeat.tick() => {
|
||||
// 1. Фиксируем время
|
||||
muxer_pong.record_ping_sent(leg_id);
|
||||
// 2. Шлем пакет
|
||||
let msg = MuxMessage { stream_id: 0, frame_type: FrameType::Heartbeat, data: Bytes::new() };
|
||||
Self::handle_outbound(&mut outbound, &codec_writer, msg).await?;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use bytes::Bytes;
|
||||
use netrunner_logger::{debug, error, info, warn};
|
||||
use netrunner_logger::{debug, error, info, trace, warn};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio::net::{TcpStream, UdpSocket};
|
||||
@@ -75,6 +75,21 @@ impl StreamHandler {
|
||||
let stream_id = frame.header.stream_id;
|
||||
|
||||
match frame.header.frame_type {
|
||||
FrameType::Heartbeat => {
|
||||
// Проверяем: если мы Opener (т.е. мы Сервер), то отвечаем.
|
||||
// Если мы Клиент (opener == None), то мы сюда вообще не должны дойти
|
||||
// (т.к. перехватили в TunnelEngine), но на всякий случай логируем.
|
||||
if self.opener.is_some() {
|
||||
trace!(stream_id, "💓 [Server] Ping received, sending Pong");
|
||||
let _ = self
|
||||
.muxer
|
||||
.send_control(stream_id, FrameType::Heartbeat, Bytes::new())
|
||||
.await;
|
||||
} else {
|
||||
trace!(stream_id, "💓 [Client] Pong received (captured by Engine)");
|
||||
}
|
||||
}
|
||||
|
||||
FrameType::Connect => {
|
||||
self.handle_conn_request(stream_id, frame.payload, false)
|
||||
.await
|
||||
@@ -92,10 +107,10 @@ impl StreamHandler {
|
||||
debug!(stream_id, "🏁 [Tunnel] Peer closed stream");
|
||||
self.muxer.remove_stream(stream_id);
|
||||
}
|
||||
|
||||
_ => debug!(stream_id, "Unhandled frame: {:?}", frame.header.frame_type),
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_conn_request(&self, stream_id: u32, payload: Bytes, is_udp: bool) {
|
||||
let target = String::from_utf8_lossy(&payload).to_string();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ use dashmap::DashMap;
|
||||
use netrunner_logger::{debug, info, trace, warn};
|
||||
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
use crate::net::{HEALTH_CHECK_TIMEOUT, MAX_TUNNEL_LEGS, MUXER_POOL_SIZE};
|
||||
@@ -55,8 +56,9 @@ pub struct MuxMessage {
|
||||
pub struct Muxer {
|
||||
legs: Arc<DashMap<u32, MuxLeg>>,
|
||||
streams: Arc<DashMap<u32, (Sender<Bytes>, Arc<StreamStats>)>>,
|
||||
// 🚨 Sticky Sessions: Привязка Stream ID -> Leg ID
|
||||
stream_bindings: Arc<DashMap<u32, u32>>,
|
||||
// 🚨 Добавляем сюда:
|
||||
pending_pings: Arc<DashMap<u32, Instant>>,
|
||||
id_gen: Arc<IdGenerator>,
|
||||
session_id: Arc<String>,
|
||||
}
|
||||
@@ -68,6 +70,7 @@ impl Muxer {
|
||||
streams: Arc::new(DashMap::new()),
|
||||
stream_bindings: Arc::new(DashMap::new()),
|
||||
id_gen: Arc::new(IdGenerator::new(is_client)),
|
||||
pending_pings: Arc::new(DashMap::new()),
|
||||
session_id: Arc::new(session_id),
|
||||
}
|
||||
}
|
||||
@@ -163,6 +166,22 @@ impl Muxer {
|
||||
Some((selected_id, selected_leg))
|
||||
}
|
||||
|
||||
pub fn record_ping_sent(&self, leg_id: u32) {
|
||||
self.pending_pings.insert(leg_id, Instant::now());
|
||||
}
|
||||
|
||||
pub async fn record_pong(&self, leg_id: u32) {
|
||||
if let Some((_, start_time)) = self.pending_pings.remove(&leg_id) {
|
||||
let rtt = start_time.elapsed().as_millis() as u32;
|
||||
|
||||
if let Some(leg) = self.legs.get(&leg_id) {
|
||||
// Обновляем атомик, который потом прочитает принт топологии
|
||||
leg.stats.rtt_ms.store(rtt, Ordering::Relaxed);
|
||||
trace!(leg_id, rtt, "💓 [Muxer] RTT updated for leg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_to_network(&self, message: MuxMessage) -> Result<(), String> {
|
||||
let stream_id = message.stream_id;
|
||||
let size = message.data.len() as u64;
|
||||
|
||||
@@ -11,7 +11,7 @@ pub const UDP_IDLE_TIMEOUT: Duration = Duration::from_secs(60); // Смерть
|
||||
pub const GLOBAL_IDLE_TIMEOUT: Duration = Duration::from_secs(120); // Очистка Tracker-ом
|
||||
pub const HEALTH_CHECK_INTERVAL: Duration = Duration::from_secs(5); // Частота пинга Leg-ов
|
||||
pub const HEALTH_CHECK_TIMEOUT: Duration = Duration::from_secs(15);
|
||||
pub const LEG_RECONNECT_DELAY: Duration = Duration::from_secs(30); // Пауза перед реконнектом Leg
|
||||
pub const LEG_RECONNECT_DELAY: Duration = Duration::from_secs(5); // Пауза перед реконнектом Leg
|
||||
pub const BRIDGE_IDLE_TIMEOUT: Duration = Duration::from_secs(300); // Таймаут задач-бриджей
|
||||
|
||||
// --- Сетевые порты ---
|
||||
@@ -20,10 +20,6 @@ pub const HTTP_PORT: u16 = 80;
|
||||
pub const HTTPS_PORT: u16 = 443;
|
||||
pub const NETBIOS_PORTS: [u16; 2] = [137, 138];
|
||||
|
||||
// --- Критические оверхеды (для MTU/MSS) ---
|
||||
pub const IPV4_TCP_OVERHEAD: usize = 40; // IPv4(20) + TCP(20)
|
||||
pub const NRXP_OVERHEAD: usize = 254; // Запас под заголовки твоего протокола и TLS
|
||||
|
||||
// --- Настройки безопасности ---
|
||||
pub const AUTH_TIME_STEP: u64 = 60; // Шаг генерации токена (секунды)
|
||||
pub const AUTH_WINDOW_SIZE: u64 = 2; // Допуск шагов времени (current +/- 2)
|
||||
@@ -34,8 +30,8 @@ pub const TOPOLOGY_PRINT_INTERVAL: Duration = Duration::from_secs(15);
|
||||
|
||||
// --- Настройки Stealth Fallback (Маскировка) ---
|
||||
pub const STEALTH_FALLBACK_HOST: &str = "ubuntu.com:443";
|
||||
pub const FALLBACK_CONNECT_TIMEOUT: Duration = Duration::from_secs(3);
|
||||
pub const FALLBACK_CONNECT_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
// --- Таймауты Handshake ---
|
||||
pub const TLS_HELLO_TIMEOUT: Duration = Duration::from_secs(1);
|
||||
pub const SECURE_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(3);
|
||||
pub const TLS_HELLO_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
pub const SECURE_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(15);
|
||||
|
||||
Reference in New Issue
Block a user