udprelay: per-client upstream sockets (SL 30fps flood mis-routed scan replies to the wrong socket)
This commit is contained in:
parent
ab8090be79
commit
03d0e79268
|
|
@ -1877,40 +1877,78 @@ fn session_loop(sock: &UdpSocket, dst: &str, target: &str, rng: &mut Rng, b12: u
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ★UDP 31772 通用中继 (udprelay 子命令): 跨网段主机验证用
|
/// ★UDP 31772 通用中继 (udprelay 子命令): 跨网段主机验证用
|
||||||
/// 客户端(任意网段) ↔ sockA(listen_addr) | sockB(src_ip:0) ↔ Butler
|
/// 客户端(任意网段) ↔ sockA(listen_addr) | 每客户端独立 sockB(src_ip:0) ↔ Butler
|
||||||
/// 发往 Butler 的帧源 IP = src_ip (123.113, 绕过 AECH 固件源过滤);
|
/// 发往 Butler 的帧源 IP = src_ip (123.113, 绕过 AECH 固件源过滤);
|
||||||
/// Butler 应答(单播到 sockB) 转发回最后一个客户端; Butler 广播(到 sockA) 也转发。
|
/// Butler 应答(单播到该客户端的 sockB) 原路转发回该客户端; Butler 广播(到 sockA) 广播给所有客户端。
|
||||||
|
///
|
||||||
|
/// 2026-09-13 重构: 旧版用单个 `client` 变量记录"最后发包者", 任何客户端在
|
||||||
|
/// 请求与应答之间只要有另一个客户端发了包(如 SL 30fps 灌流 vs 低频扫描套接字),
|
||||||
|
/// 应答就会被投递给错误的套接字 —— SL 扫描因此永远收不到 DUB 上行。
|
||||||
|
/// 现在每个客户端持有独立的上行 socket, Butler 按目的端口(=该 socket)天然
|
||||||
|
/// 区分客户端, 应答无歧义回原客户端; 上限 8 客户端, 淘汰最旧。
|
||||||
pub fn udp_relay(listen_addr: &str, butler_ip: &str, src_ip: &str) {
|
pub fn udp_relay(listen_addr: &str, butler_ip: &str, src_ip: &str) {
|
||||||
let a = open_reuse(listen_addr);
|
let a = open_reuse(listen_addr);
|
||||||
let b = open_reuse(&format!("{}:0", src_ip));
|
a.set_read_timeout(Some(Duration::from_millis(1))).unwrap();
|
||||||
a.set_read_timeout(Some(Duration::from_millis(2))).unwrap();
|
|
||||||
b.set_read_timeout(Some(Duration::from_millis(2))).unwrap();
|
|
||||||
let bdst = format!("{}:31772", butler_ip);
|
let bdst = format!("{}:31772", butler_ip);
|
||||||
let mut client: Option<std::net::SocketAddr> = None;
|
let butler_sa: std::net::SocketAddr = bdst.parse().unwrap();
|
||||||
|
struct Up {
|
||||||
|
addr: std::net::SocketAddr,
|
||||||
|
sock: UdpSocket,
|
||||||
|
}
|
||||||
|
let mut ups: Vec<Up> = Vec::new();
|
||||||
let mut ba = [0u8; 4096];
|
let mut ba = [0u8; 4096];
|
||||||
let mut bb = [0u8; 4096];
|
let mut bb = [0u8; 4096];
|
||||||
let (mut n_fwd, mut n_rev) = (0u64, 0u64);
|
let (mut n_fwd, mut n_rev) = (0u64, 0u64);
|
||||||
println!("[RELAY] {} <-> Butler {} (源伪装 {}), Ctrl+C 停止", listen_addr, bdst, src_ip);
|
println!("[RELAY] {} <-> Butler {} (源伪装 {}, 每客户端独立上行), Ctrl+C 停止", listen_addr, bdst, src_ip);
|
||||||
loop {
|
loop {
|
||||||
if let Ok((n, from)) = a.recv_from(&mut ba) {
|
// Butler → 各客户端: 逐上行 socket 收(非阻塞, 无歧义归属)
|
||||||
|
for up in ups.iter_mut() {
|
||||||
|
loop {
|
||||||
|
match up.sock.recv_from(&mut bb) {
|
||||||
|
Ok((n, from)) => {
|
||||||
if from.ip().to_string() == butler_ip {
|
if from.ip().to_string() == butler_ip {
|
||||||
// Butler 广播/事件 → 客户端
|
let _ = a.send_to(&bb[..n], up.addr);
|
||||||
if let Some(c) = client { let _ = a.send_to(&ba[..n], c); n_rev += 1; }
|
|
||||||
} else {
|
|
||||||
client = Some(from);
|
|
||||||
let _ = b.send_to(&ba[..n], &bdst);
|
|
||||||
n_fwd += 1;
|
|
||||||
if n_fwd == 1 { println!("[RELAY] 客户端 = {}", from); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Ok((n, _from)) = b.recv_from(&mut bb) {
|
|
||||||
if let Some(c) = client {
|
|
||||||
let _ = a.send_to(&bb[..n], c);
|
|
||||||
n_rev += 1;
|
n_rev += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 客户端(或 Butler 侧广播) → listen socket
|
||||||
|
if let Ok((n, from)) = a.recv_from(&mut ba) {
|
||||||
|
// 2026-09-13: Butler 判定改为完整 socket (IP:31772)。旧逻辑只比
|
||||||
|
// 对 IP —— DUT 侧内部发现 walker 从 .68.200:*临时端口* 发出的查询
|
||||||
|
// 被误判为 Butler 事件转发给 SL,永远到不了总线。
|
||||||
|
if from == butler_sa {
|
||||||
|
// Butler 广播/事件 → 所有客户端
|
||||||
|
for up in ups.iter() {
|
||||||
|
let _ = a.send_to(&ba[..n], up.addr);
|
||||||
|
n_rev += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match ups.iter_mut().find(|up| up.addr == from) {
|
||||||
|
Some(up) => {
|
||||||
|
let _ = up.sock.send_to(&ba[..n], &bdst);
|
||||||
|
n_fwd += 1;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let sock = open_reuse(&format!("{}:0", src_ip));
|
||||||
|
let _ = sock.set_nonblocking(true);
|
||||||
|
let _ = sock.send_to(&ba[..n], &bdst);
|
||||||
|
ups.push(Up { addr: from, sock });
|
||||||
|
if ups.len() > 8 {
|
||||||
|
ups.remove(0);
|
||||||
|
}
|
||||||
|
n_fwd += 1;
|
||||||
|
println!("[RELAY] 客户端 #{} = {}", ups.len(), from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (n_fwd + n_rev) % 2000 == 1 && n_fwd > 1 {
|
if (n_fwd + n_rev) % 2000 == 1 && n_fwd > 1 {
|
||||||
println!("[RELAY] 已转发 客户端→Butler {} 帧, Butler→客户端 {} 帧", n_fwd, n_rev);
|
println!("[RELAY] 已转发 客户端→Butler {} 帧, Butler→客户端 {} 帧 ({} 客户端)", n_fwd, n_rev, ups.len());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user