修复中继路由探测失效

- MsgType 的 TryFrom 与枚举判别值不一致:RelayProbe 写 18 却被解码为
  RelayProbeReply,真正的 Reply(19) 被当非法类型丢弃,改为 18/19 与枚举一致
- RelayProbeReply 回复 TTL 由 1 改为 2:TTL=1 时中继节点 decr 后即被丢弃,
  回复永远到不了发起方,中继路由(metric=2)无法建立
- 补充 MsgType 全变体 round-trip 与中继 TTL 语义测试
This commit is contained in:
lbl
2026-08-20 21:30:32 +08:00
parent 7d481560e3
commit 216cf16310
2 changed files with 66 additions and 3 deletions
+64 -2
View File
@@ -140,9 +140,9 @@ impl TryFrom<u8> for MsgType {
14 => MsgType::RpcReq,
15 => MsgType::RpcRes,
16 => MsgType::RelayProbe,
17 => MsgType::Quic,
18 => MsgType::RelayProbeReply,
18 => MsgType::RelayProbe,
19 => MsgType::RelayProbeReply,
_ => {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
@@ -304,3 +304,65 @@ impl NetPacket<TransmissionBytes> {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn msg_type_round_trip() {
let all = [
MsgType::Turn,
MsgType::Broadcast,
MsgType::ExcludeBroadcast,
MsgType::TargetBroadcast,
MsgType::Ping,
MsgType::Pong,
MsgType::PingTurn,
MsgType::PongTurn,
MsgType::PunchStart1,
MsgType::PunchStart2,
MsgType::PunchReq,
MsgType::PunchRes,
MsgType::PushClientIps,
MsgType::RpcReq,
MsgType::RpcRes,
MsgType::Quic,
MsgType::RelayProbe,
MsgType::RelayProbeReply,
];
for msg_type in all {
let byte = u8::from(msg_type);
assert_eq!(
MsgType::try_from(byte).unwrap(),
msg_type,
"round trip failed for {msg_type:?} ({byte})"
);
}
// 未分配的取值必须报错
assert!(MsgType::try_from(0u8).is_err());
assert!(MsgType::try_from(16u8).is_err());
assert!(MsgType::try_from(20u8).is_err());
}
/// 中继转发语义:包每经过一跳 curr_ttl 减 1curr_ttl >= 1 时才继续转发,
/// 接收方以 metric = max_ttl - curr_ttl 计算路由距离。
#[test]
fn relay_reply_survives_one_hop() {
let mut packet =
NetPacket::new(BytesMut::from(&[0u8; HEAD_LENGTH][..])).unwrap();
packet.set_msg_type(MsgType::RelayProbeReply);
// 目标方回复时 TTL 必须允许一次中继
packet.set_ttl(2);
// 中继节点:decr 后 curr_ttl == 1,满足转发条件 ttl >= 1
packet.decr_ttl();
assert_eq!(packet.ttl(), 1);
assert!(packet.ttl() >= 1, "relay node would drop this packet");
// 发起方:decr 后 curr_ttl == 0metric = 2(经由一个中继)
packet.decr_ttl();
assert_eq!(packet.ttl(), 0);
assert_eq!(packet.max_ttl() - packet.ttl(), 2);
}
}
+2 -1
View File
@@ -270,7 +270,8 @@ impl P2pInboundHandler {
self.packet_crypto.encrypt_reserve(),
))?;
packet.set_msg_type(MsgType::RelayProbeReply);
packet.set_ttl(1);
// 与 RelayProbe 对称:允许中继一次,到达发起方时 curr_ttl 为 0metric = 2
packet.set_ttl(2);
packet.set_src_id(ctx.dest_ip.into());
packet.set_dest_id(ctx.src_ip.into());
self.packet_crypto.encrypt_in_place(&mut packet)?;