in neqo-transport/src/connection/mod.rs [1978:2025]
fn migrate_to_preferred_address(&mut self, now: Instant) -> Res<()> {
let spa: Option<(tparams::PreferredAddress, ConnectionIdEntry<[u8; 16]>)> = if matches!(
self.conn_params.get_preferred_address(),
PreferredAddressConfig::Disabled
) {
qdebug!("[{self}] Preferred address is disabled");
None
} else {
self.tps.borrow_mut().remote().get_preferred_address()
};
if let Some((addr, cid)) = spa {
// The connection ID isn't special, so just save it.
self.cids.add_remote(cid)?;
// The preferred address doesn't dictate what the local address is, so this
// has to use the existing address. So only pay attention to a preferred
// address from the same family as is currently in use. More thought will
// be needed to work out how to get addresses from a different family.
let prev = self
.paths
.primary()
.ok_or(Error::NoAvailablePath)?
.borrow()
.remote_address();
let remote = match prev.ip() {
IpAddr::V4(_) => addr.ipv4().map(SocketAddr::V4),
IpAddr::V6(_) => addr.ipv6().map(SocketAddr::V6),
};
if let Some(remote) = remote {
// Ignore preferred address that move to loopback from non-loopback.
// `migrate` doesn't enforce this rule.
if !prev.ip().is_loopback() && remote.ip().is_loopback() {
qwarn!("[{self}] Ignoring a move to a loopback address: {remote}");
return Ok(());
}
if self.migrate(None, Some(remote), false, now).is_err() {
qwarn!("[{self}] Ignoring bad preferred address: {remote}");
}
} else {
qwarn!("[{self}] Unable to migrate to a different address family");
}
} else {
qdebug!("[{self}] No preferred address to migrate to");
}
Ok(())
}