kns: variable length array IP encoding

This commit is contained in:
bitful-pannul 2024-08-05 20:43:21 +03:00
parent 950c42d909
commit c513dd1db0
3 changed files with 34 additions and 30 deletions

View File

@ -506,15 +506,15 @@ fn decode_routers(data: &[u8], state: &State) -> anyhow::Result<Vec<String>> {
pub fn bytes_to_ip(bytes: &[u8]) -> anyhow::Result<IpAddr> { pub fn bytes_to_ip(bytes: &[u8]) -> anyhow::Result<IpAddr> {
match bytes.len() { match bytes.len() {
16 => { 4 => {
let ip_num = u128::from_be_bytes(bytes.try_into().unwrap()); // IPv4 address
if ip_num < (1u128 << 32) { let ip_num = u32::from_be_bytes(bytes.try_into().unwrap());
// IPv4 Ok(IpAddr::V4(Ipv4Addr::from(ip_num)))
Ok(IpAddr::V4(Ipv4Addr::from(ip_num as u32)))
} else {
// IPv6
Ok(IpAddr::V6(Ipv6Addr::from(ip_num)))
} }
16 => {
// IPv6 address
let ip_num = u128::from_be_bytes(bytes.try_into().unwrap());
Ok(IpAddr::V6(Ipv6Addr::from(ip_num)))
} }
_ => Err(anyhow::anyhow!("Invalid byte length for IP address")), _ => Err(anyhow::anyhow!("Invalid byte length for IP address")),
} }

View File

@ -161,31 +161,35 @@ pub fn namehash(name: &str) -> [u8; 32] {
node.into() node.into()
} }
pub fn bytes_to_ip(bytes: &[u8]) -> Result<IpAddr, String> { pub fn bytes_to_ip(bytes: &[u8]) -> Result<IpAddr> {
match bytes.len() { match bytes.len() {
4 => {
// IPv4 address
let ip_num = u32::from_be_bytes(bytes.try_into().unwrap());
Ok(IpAddr::V4(Ipv4Addr::from(ip_num)))
}
16 => { 16 => {
// IPv6 address
let ip_num = u128::from_be_bytes(bytes.try_into().unwrap()); let ip_num = u128::from_be_bytes(bytes.try_into().unwrap());
if ip_num < (1u128 << 32) {
// IPv4
Ok(IpAddr::V4(Ipv4Addr::from(ip_num as u32)))
} else {
// IPv6
Ok(IpAddr::V6(Ipv6Addr::from(ip_num))) Ok(IpAddr::V6(Ipv6Addr::from(ip_num)))
} }
} _ => Err(anyhow::anyhow!("Invalid byte length for IP address")),
other => Err(format!("Invalid byte length for IP address: {other}")),
} }
} }
#[cfg(feature = "simulation-mode")] #[cfg(feature = "simulation-mode")]
pub fn ip_to_bytes(ip: IpAddr) -> [u8; 16] { pub fn ip_to_bytes(ip: IpAddr) -> Vec<u8> {
match ip { match ip {
IpAddr::V4(ipv4) => { IpAddr::V4(ipv4) => {
let mut bytes = [0u8; 16]; let mut bytes = Vec::with_capacity(4);
bytes[12..].copy_from_slice(&ipv4.octets()); bytes.extend_from_slice(&ipv4.octets());
bytes
}
IpAddr::V6(ipv6) => {
let mut bytes = Vec::with_capacity(16);
bytes.extend_from_slice(&ipv6.octets());
bytes bytes
} }
IpAddr::V6(ipv6) => ipv6.octets(),
} }
} }

View File

@ -20,25 +20,25 @@ export function bytesToIp(bytes: Uint8Array): string {
} }
export function ipToBytes(ip: string): Uint8Array { export function ipToBytes(ip: string): Uint8Array {
if (ip.includes(':')) {
// IPv6: Create a 16-byte array
const bytes = new Uint8Array(16); const bytes = new Uint8Array(16);
const view = new DataView(bytes.buffer); const view = new DataView(bytes.buffer);
if (ip.includes(':')) {
// IPv6
const parts = ip.split(':'); const parts = ip.split(':');
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
view.setUint16(i * 2, parseInt(parts[i] || '0', 16)); view.setUint16(i * 2, parseInt(parts[i] || '0', 16));
} }
return bytes;
} else { } else {
// IPv4 // IPv4: Create a 4-byte array
const bytes = new Uint8Array(4);
const parts = ip.split('.'); const parts = ip.split('.');
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
bytes[12 + i] = parseInt(parts[i], 10); bytes[i] = parseInt(parts[i], 10);
} }
}
return bytes; return bytes;
} }
}
export function bytesToPort(bytes: Uint8Array): number { export function bytesToPort(bytes: Uint8Array): number {
if (bytes.length !== 2) { if (bytes.length !== 2) {