in neqo-transport/src/tparams.rs [212:255]
fn decode_preferred_address(d: &mut Decoder) -> Res<Self> {
// IPv4 address (maybe)
let v4ip = Ipv4Addr::from(<[u8; 4]>::try_from(d.decode(4).ok_or(Error::NoMoreData)?)?);
let v4port = d.decode_uint::<u16>().ok_or(Error::NoMoreData)?;
// Can't have non-zero IP and zero port, or vice versa.
if v4ip.is_unspecified() ^ (v4port == 0) {
return Err(Error::TransportParameterError);
}
let v4 = if v4port == 0 {
None
} else {
Some(SocketAddrV4::new(v4ip, v4port))
};
// IPv6 address (mostly the same as v4)
let v6ip = Ipv6Addr::from(<[u8; 16]>::try_from(
d.decode(16).ok_or(Error::NoMoreData)?,
)?);
let v6port = d.decode_uint().ok_or(Error::NoMoreData)?;
if v6ip.is_unspecified() ^ (v6port == 0) {
return Err(Error::TransportParameterError);
}
let v6 = if v6port == 0 {
None
} else {
Some(SocketAddrV6::new(v6ip, v6port, 0, 0))
};
// Need either v4 or v6 to be present.
if v4.is_none() && v6.is_none() {
return Err(Error::TransportParameterError);
}
// Connection ID (non-zero length)
let cid = ConnectionId::from(d.decode_vec(1).ok_or(Error::NoMoreData)?);
if cid.is_empty() || cid.len() > MAX_CONNECTION_ID_LEN {
return Err(Error::TransportParameterError);
}
// Stateless reset token
let srtbuf = d.decode(16).ok_or(Error::NoMoreData)?;
let srt = <[u8; 16]>::try_from(srtbuf)?;
Ok(Self::PreferredAddress { v4, v6, cid, srt })
}