修复中继路由探测失效
- 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:
@@ -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 减 1,curr_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 == 0,metric = 2(经由一个中继)
|
||||
packet.decr_ttl();
|
||||
assert_eq!(packet.ttl(), 0);
|
||||
assert_eq!(packet.max_ttl() - packet.ttl(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,8 @@ impl P2pInboundHandler {
|
||||
self.packet_crypto.encrypt_reserve(),
|
||||
))?;
|
||||
packet.set_msg_type(MsgType::RelayProbeReply);
|
||||
packet.set_ttl(1);
|
||||
// 与 RelayProbe 对称:允许中继一次,到达发起方时 curr_ttl 为 0,metric = 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)?;
|
||||
|
||||
Reference in New Issue
Block a user