nice buf sizes and moved duration in consts

This commit is contained in:
2026-04-05 13:48:56 +07:00
parent 1ab28cefcf
commit 240c4e3c20
11 changed files with 160 additions and 83 deletions
-8
View File
@@ -7,8 +7,6 @@ pub static GLOBAL_NET_CONFIG: OnceLock<NetworkConfig> = OnceLock::new();
#[derive(Debug, Clone)]
pub struct NetworkConfig {
pub mtu: usize,
pub max_wire_frame_size: usize,
pub safe_payload_size: usize,
pub tcp_buffer_size: usize,
pub udp_buffer_size: usize,
@@ -29,17 +27,11 @@ pub struct NetworkConfig {
}
impl NetworkConfig {
pub fn new(system_mtu: usize) -> Self {
let transport_overhead = 48;
let max_wire_frame = system_mtu.saturating_sub(transport_overhead);
let safe_payload = max_wire_frame.saturating_sub(64);
let chunk_size = 16 * 1024;
let heavy_buf = 256 * 1024;
Self {
mtu: system_mtu,
max_wire_frame_size: max_wire_frame,
safe_payload_size: safe_payload,
tcp_buffer_size: 8 * 1024,
udp_buffer_size: 64 * 1024,
+3 -5
View File
@@ -2,7 +2,7 @@ use std::sync::Arc;
use std::time::Duration;
use crate::net::connection::muxer::{MuxMessage, Muxer};
use crate::net::NetworkConfig;
use crate::net::{NetworkConfig, BRIDGE_IDLE_TIMEOUT};
use crate::nrxp::FrameType;
use bytes::{Bytes, BytesMut};
use netrunner_logger::{debug, error, info, warn};
@@ -10,8 +10,6 @@ use tokio::net::UdpSocket;
use tokio::sync::mpsc;
use tokio::time::timeout;
const IDLE_TIMEOUT: Duration = Duration::from_secs(300);
struct StreamGuard {
stream_id: u32,
muxer: Arc<Muxer>,
@@ -43,7 +41,7 @@ pub(crate) async fn run_tcp_bridge<R, W>(
loop {
buf.reserve(NetworkConfig::global().tcp_buffer_size);
let select_res = timeout(IDLE_TIMEOUT, async {
let select_res = timeout(BRIDGE_IDLE_TIMEOUT, async {
tokio::select! {
res = reader.read_buf(&mut buf) => {
@@ -132,7 +130,7 @@ pub(crate) async fn run_udp_bridge(
info!(stream_id, "🌉 UDP Bridge active");
loop {
let select_res = timeout(IDLE_TIMEOUT, async {
let select_res = timeout(BRIDGE_IDLE_TIMEOUT, async {
tokio::select! {
res = socket.recv(&mut buf) => {
+12 -16
View File
@@ -1,4 +1,4 @@
use std::{net::Ipv4Addr, sync::Arc, time::Duration};
use std::{net::Ipv4Addr, sync::Arc};
use crate::{
net::{
@@ -7,7 +7,8 @@ use crate::{
handler::{RemoteOpener, StreamHandler},
muxer::Muxer,
},
NetworkConfig,
NetworkConfig, FALLBACK_CONNECT_TIMEOUT, LEG_RECONNECT_DELAY, LEG_STAGGER_DELAY,
MAX_TUNNEL_LEGS, SECURE_HANDSHAKE_TIMEOUT, TLS_HELLO_TIMEOUT, TOPOLOGY_PRINT_INTERVAL,
},
nrxp::{Codec, ErrorAction, Frame, FrameType},
rawcast::{LocalProtocol, RawCastAdapter, RawCastFrame},
@@ -200,17 +201,17 @@ impl ClientHandler {
info!("🚀 Netrunner Multi-Path Tunnel Initializing (10 Legs max).");
for id in 0..10 {
for id in 0..MAX_TUNNEL_LEGS {
let addr = remote_proxy_addr.to_string();
let m = muxer.clone();
let sid = session_id.clone();
tokio::spawn(async move {
tokio::time::sleep(std::time::Duration::from_millis(id as u64 * 250)).await;
tokio::time::sleep(LEG_STAGGER_DELAY * id).await;
loop {
if let Err(e) = Self::establish_leg(&addr, id, m.clone(), &sid).await {
error!("Leg {} disconnected: {}. Reconnecting in 3s...", id, e);
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
tokio::time::sleep(LEG_RECONNECT_DELAY).await;
}
}
});
@@ -219,7 +220,7 @@ impl ClientHandler {
let m_weak = Arc::downgrade(&muxer);
tokio::spawn(async move {
while let Some(m_stats) = m_weak.upgrade() {
tokio::time::sleep(Duration::from_secs(15)).await;
tokio::time::sleep(TOPOLOGY_PRINT_INTERVAL).await;
if m_stats.active_legs_count() == 0 {
break;
}
@@ -362,11 +363,8 @@ impl ServerHandler {
let target_host = "ubuntu.com:443";
info!(target = %target_host, "Stealth fallback: bridging to Target");
let target_stream = tokio::time::timeout(
std::time::Duration::from_secs(3),
TcpStream::connect(target_host),
)
.await;
let target_stream =
tokio::time::timeout(FALLBACK_CONNECT_TIMEOUT, TcpStream::connect(target_host)).await;
match target_stream {
Ok(Ok(target_server)) => {
@@ -406,8 +404,6 @@ impl TunnelHandler for ServerHandler {
async fn run(mut self) -> Result<(), String> {
info!("Acting as TLS Server with Stealth Fallback");
let handshake_timeout = std::time::Duration::from_secs(1);
let hello = loop {
let buf_snapshot = self.conn.read_buf.clone().freeze();
match self
@@ -419,7 +415,7 @@ impl TunnelHandler for ServerHandler {
Err(e) => match e.execute_strategy() {
ErrorAction::Wait => {
let res = tokio::time::timeout(
handshake_timeout,
TLS_HELLO_TIMEOUT,
self.conn.inbound.read_buf(&mut self.conn.read_buf),
)
.await;
@@ -462,7 +458,7 @@ impl TunnelHandler for ServerHandler {
let (session_id, leg_id) = loop {
let n = tokio::time::timeout(
std::time::Duration::from_secs(3),
SECURE_HANDSHAKE_TIMEOUT,
self.conn.inbound.read_buf(&mut self.conn.read_buf),
)
.await
@@ -527,7 +523,7 @@ impl TunnelHandler for ServerHandler {
let m_weak = Arc::downgrade(&muxer);
tokio::spawn(async move {
while let Some(m_stats) = m_weak.upgrade() {
tokio::time::sleep(std::time::Duration::from_secs(15)).await;
tokio::time::sleep(TOPOLOGY_PRINT_INTERVAL).await;
if m_stats.active_legs_count() == 0 {
break;
}
+2 -2
View File
@@ -12,7 +12,7 @@ use tokio_util::sync::CancellationToken;
use crate::{
net::{
connection::{handler::StreamHandler, muxer::MuxMessage},
NetworkConfig,
NetworkConfig, HEALTH_CHECK_INTERVAL,
},
nrxp::{Codec, ErrorAction, FrameType},
};
@@ -114,7 +114,7 @@ impl TunnelEngine {
let mut outbound = outbound;
let mut control_rx = control_rx;
let mut data_rx = data_rx;
let mut heartbeat = tokio::time::interval(std::time::Duration::from_secs(15));
let mut heartbeat = tokio::time::interval(HEALTH_CHECK_INTERVAL);
loop {
tokio::select! {
+75 -33
View File
@@ -3,9 +3,10 @@ use dashmap::DashMap;
use netrunner_logger::{debug, info, warn};
use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
use std::sync::Arc;
use tokio::sync::mpsc::error::TrySendError;
use tokio::sync::mpsc::Sender;
// Подключаем твои константы (убедись, что путь импорта совпадает с твоей структурой)
use crate::net::constants::{HEALTH_CHECK_TIMEOUT, MAX_TUNNEL_LEGS, MUXER_POOL_SIZE};
use crate::nrxp::FrameType;
#[derive(Default, Debug)]
@@ -13,6 +14,7 @@ pub struct LegStats {
pub tx_bytes: AtomicU64,
pub rx_bytes: AtomicU64,
pub rtt_ms: AtomicU32,
pub strikes: AtomicU32, // 👈 Счетчик пропущенных пингов (страйков)
}
#[derive(Default, Debug)]
@@ -58,6 +60,7 @@ pub struct Muxer {
id_gen: Arc<IdGenerator>,
session_id: Arc<String>,
}
impl Muxer {
pub fn new(is_client: bool, session_id: String) -> Self {
Self {
@@ -74,11 +77,9 @@ impl Muxer {
control_tx: Sender<MuxMessage>,
data_tx: Sender<MuxMessage>,
) {
if self.legs.len() >= 10 {
warn!(
leg_id,
"MUXER: Maximum of 10 legs reached. Ignoring new leg."
);
// 👈 Используем константу вместо магической 10
if self.legs.len() >= MAX_TUNNEL_LEGS as usize {
warn!(leg_id, "MUXER: Max legs reached: {}", MAX_TUNNEL_LEGS);
return;
}
@@ -124,6 +125,7 @@ impl Muxer {
.collect();
}
// Выбираем ноги с наименьшим RTT (ноги со страйками = 5000ms будут в конце)
candidates.sort_by_key(|(_, leg)| {
let rtt = leg.stats.rtt_ms.load(Ordering::Relaxed);
if rtt == 0 {
@@ -133,7 +135,8 @@ impl Muxer {
}
});
let pool_size = std::cmp::min(candidates.len(), 2);
// 👈 Используем константу
let pool_size = std::cmp::min(candidates.len(), MUXER_POOL_SIZE);
let target = &candidates[stream_id as usize % pool_size];
Some(target.clone())
@@ -244,6 +247,7 @@ impl Muxer {
self.id_gen.next()
}
// 👈 Полностью переписанный параллельный Health Check со страйками
pub async fn perform_health_check(&self) {
let legs: Vec<(u32, Sender<MuxMessage>)> = self
.legs
@@ -251,40 +255,67 @@ impl Muxer {
.map(|k| (*k.key(), k.value().control_tx.clone()))
.collect();
// Запускаем проверку каждой ноги параллельно
for (leg_id, tx) in legs {
let probe_stream_id = self.id_gen.next();
let (probe_tx, mut probe_rx) = tokio::sync::mpsc::channel(2);
let muxer = self.clone(); // Дешевое клонирование (внутри Arc)
self.register_stream(probe_stream_id, probe_tx);
tokio::spawn(async move {
let probe_stream_id = muxer.id_gen.next();
let (probe_tx, mut probe_rx) = tokio::sync::mpsc::channel(2);
let msg = MuxMessage {
stream_id: probe_stream_id,
frame_type: FrameType::Handshake,
data: Bytes::from("PING"),
};
muxer.register_stream(probe_stream_id, probe_tx);
let start = std::time::Instant::now();
let msg = MuxMessage {
stream_id: probe_stream_id,
frame_type: FrameType::Handshake,
data: Bytes::from("PING"),
};
if tx.try_send(msg).is_ok() {
match tokio::time::timeout(std::time::Duration::from_secs(2), probe_rx.recv()).await
{
Ok(Some(_)) => {
let rtt = start.elapsed().as_millis() as u32;
if let Some(leg) = self.legs.get(&leg_id) {
leg.stats.rtt_ms.store(rtt, Ordering::Relaxed);
debug!(leg_id, rtt, "✅ Leg Health Check OK");
let start = std::time::Instant::now();
if tx.try_send(msg).is_ok() {
// Используем новую константу таймаута
match tokio::time::timeout(HEALTH_CHECK_TIMEOUT, probe_rx.recv()).await {
Ok(Some(_)) => {
let rtt = start.elapsed().as_millis() as u32;
if let Some(leg) = muxer.legs.get(&leg_id) {
// Пинг прошел: обновляем RTT и СБРАСЫВАЕМ страйки
leg.stats.rtt_ms.store(rtt, Ordering::Relaxed);
leg.stats.strikes.store(0, Ordering::Relaxed);
debug!(leg_id, rtt, "✅ Leg Health Check OK");
}
}
_ => {
// Пинг провален: увеличиваем страйки
if let Some(leg) = muxer.legs.get(&leg_id) {
let strikes = leg.stats.strikes.fetch_add(1, Ordering::Relaxed) + 1;
if strikes >= 3 {
// 3 промаха = смерть. Балансировщик перестанет кидать сюда трафик
leg.stats.rtt_ms.store(5000, Ordering::Relaxed);
warn!(
leg_id,
strikes, "❌ Leg DEAD (3 strikes). RTT set to 5000."
);
} else {
// 1-2 промаха: ждем, возможно это радио-пауза в мобильной сети
warn!(
leg_id,
strikes, "⚠️ Leg missed ping. Strike {}/3", strikes
);
}
}
}
}
_ => {
if let Some(leg) = self.legs.get(&leg_id) {
leg.stats.rtt_ms.store(5000, Ordering::Relaxed);
warn!(leg_id, "❌ Leg Health Check Timeout (marked as slow)");
}
} else {
// Если канал (mpsc) забит или закрыт, считаем ногу мертвой сразу
if let Some(leg) = muxer.legs.get(&leg_id) {
leg.stats.rtt_ms.store(5000, Ordering::Relaxed);
}
}
}
self.remove_stream(probe_stream_id);
muxer.remove_stream(probe_stream_id);
});
}
}
@@ -319,6 +350,7 @@ impl Muxer {
let tx = stats.tx_bytes.load(Ordering::Relaxed);
let rx = stats.rx_bytes.load(Ordering::Relaxed);
let rtt = stats.rtt_ms.load(Ordering::Relaxed);
let strikes = stats.strikes.load(Ordering::Relaxed);
total_tx += tx;
total_rx += rx;
@@ -330,13 +362,23 @@ impl Muxer {
format!("{}ms", rtt)
};
// 👈 Добавлен визуальный статус ноги для отладки
let status_icon = if strikes >= 3 {
"💀"
} else if strikes > 0 {
"⚠️"
} else {
""
};
legs_info.push(format!(
" ├─ Leg {} ({}) ─ ⇡ {:<9} | ⇣ {:<9} [RTT: {}]",
" ├─ Leg {} ({}) ─ ⇡ {:<9} | ⇣ {:<9} [RTT: {:<6}] [Status: {}]",
id,
leg_type,
Self::format_size(tx),
Self::format_size(rx),
rtt_str
rtt_str,
status_icon
));
}
+41
View File
@@ -0,0 +1,41 @@
use std::time::Duration;
// --- Лимиты системы ---
pub const MAX_SOCKETS: usize = 2048; // Лимит сокетов в SocketSet (Anti-DDoS)
pub const MAX_TUNNEL_LEGS: u32 = 10; // Максимальное кол-во физических соединений (Legs)
pub const MUXER_POOL_SIZE: usize = 2; // Из скольких лучших Leg-ов выбирать для балансировки
// --- Таймауты ---
pub const TCP_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(20); // Время на установку SYN/ACK
pub const UDP_IDLE_TIMEOUT: Duration = Duration::from_secs(60); // Смерть UDP сессии без данных
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(5);
pub const LEG_RECONNECT_DELAY: Duration = Duration::from_secs(5); // Пауза перед реконнектом Leg
pub const BRIDGE_IDLE_TIMEOUT: Duration = Duration::from_secs(300); // Таймаут задач-бриджей
// --- Сетевые порты ---
pub const DNS_PORT: u16 = 53;
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)
// --- Настройки Multipath (Legs) ---
pub const LEG_STAGGER_DELAY: Duration = Duration::from_millis(250);
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);
// --- Таймауты Handshake ---
pub const TLS_HELLO_TIMEOUT: Duration = Duration::from_secs(1);
pub const SECURE_HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(3);
+2
View File
@@ -1,5 +1,7 @@
mod config;
mod connection;
mod constants;
pub use config::NetworkConfig;
pub use connection::{ClientHandler, Connection, ServerHandler, TunnelHandler};
pub use constants::*;