test(portmap): find the unmap among resent maps
The NAT-PMP client resends a map the gateway has not answered within 250 ms, and the mock gateway records every request, so a slow mock put a resent map where the test expected the unmap and failed it. The test now looks for the lifetime-0 request among whatever arrives after the drop. On Windows the mock's answer to that resend meets an already-closed socket, and the next receive reports the bounce as a connection reset, which ended the mock's loop before the unmap. It now carries on past it.
This commit is contained in:
@@ -418,7 +418,18 @@ mod tests {
|
|||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let mut buf = [0u8; 64];
|
let mut buf = [0u8; 64];
|
||||||
// Answer many requests (initial map + cleanup unmap + any renews).
|
// Answer many requests (initial map + cleanup unmap + any renews).
|
||||||
while let Ok((n, from)) = socket.recv_from(&mut buf) {
|
loop {
|
||||||
|
let (n, from) = match socket.recv_from(&mut buf) {
|
||||||
|
Ok(received) => received,
|
||||||
|
// Windows reports a reply that met an already-closed
|
||||||
|
// client socket on the next receive; the gateway is fine.
|
||||||
|
Err(e)
|
||||||
|
if e.kind() == std::io::ErrorKind::ConnectionReset =>
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(_) => break,
|
||||||
|
};
|
||||||
let request = buf[..n].to_vec();
|
let request = buf[..n].to_vec();
|
||||||
let internal = u16::from_be_bytes([request[4], request[5]]);
|
let internal = u16::from_be_bytes([request[4], request[5]]);
|
||||||
let lifetime = u32::from_be_bytes([
|
let lifetime = u32::from_be_bytes([
|
||||||
@@ -465,20 +476,21 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Dropping the mapper must remove the mapping (a lifetime-0 request).
|
// Dropping the mapper must remove the mapping (a lifetime-0 request).
|
||||||
|
// A map the gateway was slow to answer is sent again, and that resend
|
||||||
|
// can arrive first.
|
||||||
drop(mapper);
|
drop(mapper);
|
||||||
let unmap_req = requests
|
let unmapped = std::iter::from_fn(|| {
|
||||||
.recv_timeout(StdDuration::from_secs(3))
|
requests.recv_timeout(StdDuration::from_secs(3)).ok()
|
||||||
.expect("dropping the mapper should send an unmap request");
|
})
|
||||||
assert_eq!(
|
.any(|request| {
|
||||||
u32::from_be_bytes([
|
u32::from_be_bytes([
|
||||||
unmap_req[8],
|
request[8],
|
||||||
unmap_req[9],
|
request[9],
|
||||||
unmap_req[10],
|
request[10],
|
||||||
unmap_req[11]
|
request[11],
|
||||||
]),
|
]) == 0
|
||||||
0,
|
});
|
||||||
"cleanup should request lifetime 0"
|
assert!(unmapped, "cleanup should request lifetime 0");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A minimal in-process UPnP IGD: an HTTP server that answers every SOAP
|
/// A minimal in-process UPnP IGD: an HTTP server that answers every SOAP
|
||||||
|
|||||||
Reference in New Issue
Block a user