letmut buf = [0; u16::MAX as usize]; letmut meta = RecvMeta::default(); let segment_size = transmit.segment_size.unwrap_or(transmit.contents.len()); let expected_datagrams = transmit.contents.len() / segment_size; letmut datagrams = 0; while datagrams < expected_datagrams { let n = recv_state
.recv(
recv.into(),
&mut [IoSliceMut::new(&mut buf)],
slice::from_mut(&mut meta),
)
.unwrap();
assert_eq!(n, 1); let segments = meta.len / meta.stride; for i in0..segments {
assert_eq!(
&buf[(i * meta.stride)..((i + 1) * meta.stride)],
&transmit.contents
[(datagrams + i) * segment_size..(datagrams + i + 1) * segment_size]
);
}
datagrams += segments;
assert_eq!(
meta.addr.port(),
send.local_addr().unwrap().as_socket().unwrap().port()
); let send_v6 = send.local_addr().unwrap().as_socket().unwrap().is_ipv6(); let recv_v6 = recv.local_addr().unwrap().as_socket().unwrap().is_ipv6(); letmut addresses = vec![meta.addr.ip()]; // Not populated on every OS. See `RecvMeta::dst_ip` for details. iflet Some(addr) = meta.dst_ip {
addresses.push(addr);
} for addr in addresses { match (send_v6, recv_v6) {
(_, false) => assert_eq!(addr, Ipv4Addr::LOCALHOST), // Windows gives us real IPv4 addrs, whereas *nix use IPv6-mapped IPv4 // addrs. Canonicalize to IPv6-mapped for robustness.
(false, true) => {
assert_eq!(ip_to_v6_mapped(addr), Ipv4Addr::LOCALHOST.to_ipv6_mapped())
}
(true, true) => assert!(
addr == Ipv6Addr::LOCALHOST || addr == Ipv4Addr::LOCALHOST.to_ipv6_mapped()
),
}
}
let ipv4_or_ipv4_mapped_ipv6 = match transmit.destination.ip() {
IpAddr::V4(_) => true,
IpAddr::V6(a) => a.to_ipv4_mapped().is_some(),
};
// On Android API level <= 25 the IPv4 `IP_TOS` control message is // not supported and thus ECN bits can not be received. if ipv4_or_ipv4_mapped_ipv6
&& cfg!(target_os = "android")
&& std::env::var("API_LEVEL")
.ok()
.and_then(|v| v.parse::<u32>().ok())
.expect("API_LEVEL environment variable to be set on Android")
<= 25
{
assert_eq!(meta.ecn, None);
} else {
assert_eq!(meta.ecn, transmit.ecn);
}
}
assert_eq!(datagrams, expected_datagrams);
}
fn ip_to_v6_mapped(x: IpAddr) -> IpAddr { match x {
IpAddr::V4(x) => IpAddr::V6(x.to_ipv6_mapped()),
IpAddr::V6(_) => x,
}
}
/// Test Apple fast datapath enable/disable functionality. /// /// This test verifies that: /// 1. `max_gso_segments()` returns 1 by default (fast path disabled) /// 2. After calling `set_apple_fast_path()`, `max_gso_segments()` returns `BATCH_SIZE` /// 3. Send/recv still works correctly with the fast path enabled #[test] #[cfg(apple_fast)] fn apple_fast_datapath() { let send = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap(); let recv = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0)).unwrap(); let dst_addr = recv.local_addr().unwrap();
let send_state = UdpSocketState::new((&send).into()).unwrap(); let recv_state = UdpSocketState::new((&recv).into()).unwrap();
// Initially, fast path should be disabled and max_gso_segments should be 1
assert!(
!send_state.is_apple_fast_path_enabled(), "fast path should be disabled initially"
);
assert_eq!(
send_state.max_gso_segments(), 1, "max_gso_segments should be 1 before enabling fast path"
);
// Enable the fast path // SAFETY: Assume that sendmsg_x/recvmsg_x are available on the macOS test host. unsafe {
send_state.set_apple_fast_path();
recv_state.set_apple_fast_path();
}
// After enabling, fast path should be enabled and max_gso_segments should be BATCH_SIZE
assert!(
send_state.is_apple_fast_path_enabled(), "fast path should be enabled after calling set_apple_fast_path()"
);
assert_eq!(
send_state.max_gso_segments(),
quinn_udp::BATCH_SIZE, "max_gso_segments should be BATCH_SIZE after enabling fast path"
);
// Verify send/recv still works with fast path enabled
recv.set_nonblocking(false).unwrap();
const SEGMENT_SIZE: usize = 128; let segments = send_state.max_gso_segments(); let msg = vec![0xAB; SEGMENT_SIZE * segments];
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.