Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

less allocations in parse_svcb_ip #41

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 31 additions & 31 deletions src/decoders/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use byteorder::{BigEndian, WriteBytesExt};
use log::{error, warn};
use nom::{
bytes::complete::take,
combinator::{fail, map, map_parser, verify},
multi::{fold_many0, many0},
combinator::{fail, iterator, map, map_parser, verify},
multi::fold_many0,
number::complete::{be_u128, be_u16, be_u32, be_u8, le_u32},
sequence::tuple,
IResult,
Expand Down Expand Up @@ -227,46 +227,46 @@ fn parse_svcb_alpn(mut input: &[u8]) -> nom::IResult<&[u8], String> {
}

/// Parse the IPs
fn parse_svcb_ip(data: &[u8]) -> nom::IResult<&[u8], String> {
fn parse_svcb_ip(mut input: &[u8]) -> nom::IResult<&[u8], String> {
const IPV4: u16 = 4;
const IPV6: u16 = 6;

let mut dns_data = data;
let ipv4_parser = || map(be_u32, Ipv4Addr::from);
let ipv6_parser = || map(be_u128, Ipv6Addr::from);

let mut ipv4_addrs = vec![];
let mut ipv6_addrs = vec![];
let mut ipv4s = String::with_capacity(2 * 16); // let's reserve max space for 2 IPV4 addresses
let mut ipv6s = String::with_capacity(2 * 40); // let's reserve max space for 2 IPV6 addresses

// IPs can either be IPv4 or/and IPv6
while !dns_data.is_empty() {
let (remaining_dns_data, (ip_version, ip_size)) =
tuple((verify(be_u16, |val| *val == IPV4 || *val == IPV6), be_u16))(dns_data)?;

let (remaining_dns_data, ip_data) = take(ip_size)(remaining_dns_data)?;

dns_data = remaining_dns_data;
while !input.is_empty() {
let (i, ip_version) = verify(be_u16, |val| *val == IPV4 || *val == IPV6)(input)?;
let (i, ip_size) = be_u16(i)?;
let (i, ip_data) = take(ip_size)(i)?;
input = i;

// There can be multiple IPs
match ip_version {
IPV4 => {
let (_, mut addrs) =
many0(map(be_u32, |raw| Ipv4Addr::from(raw).to_string()))(ip_data)?;
ipv4_addrs.append(&mut addrs);
if ip_version == IPV4 {
let mut iter = iterator(ip_data, ipv4_parser());
for ip in iter.into_iter() {
if !ipv4s.is_empty() {
ipv4s.push(',');
}
write!(ipv4s, "{}", ip).ok(); // ignore errors on write in String
}
IPV6 => {
let (_, mut addrs) =
many0(map(be_u128, |raw| Ipv6Addr::from(raw).to_string()))(ip_data)?;
ipv6_addrs.append(&mut addrs);
iter.finish()?;
} else if ip_version == IPV6 {
let mut iter = iterator(ip_data, ipv6_parser());
for ip in iter.into_iter() {
if !ipv6s.is_empty() {
ipv6s.push(',');
}
write!(ipv6s, "{}", ip).ok(); // ignore errors on write in String
}
_ => {}
};
iter.finish()?;
}
}

let message = format!(
"ipv4 hint:{}, ipv6 hint:{}",
ipv4_addrs.join(","),
ipv6_addrs.join(",")
);
Ok((dns_data, message))
let message = format!("ipv4 hint:{ipv4s}, ipv6 hint:{ipv6s}");
Ok((input, message))
}

/// Get the MAC Address from the log data
Expand Down