use std::net::Ipv4Addr;
use super::{
ETH_HEADER_LEN,
checksum::{ipv4_header_checksum, udp_checksum},
};
#[must_use]
pub fn build_udp_ip_ethernet(
src_ip: Ipv4Addr,
dst_ip: Ipv4Addr,
src_port: u16,
dst_port: u16,
payload: &[u8],
src_mac: [u8; 6],
dst_mac: [u8; 6],
) -> Vec<u8> {
let udp_len = 8 + payload.len();
let ip_total_len = 20 + udp_len;
let frame_len = ETH_HEADER_LEN + ip_total_len;
let mut frame = vec![0u8; frame_len];
frame[0..6].copy_from_slice(&dst_mac);
frame[6..12].copy_from_slice(&src_mac);
frame[12..14].copy_from_slice(&0x0800u16.to_be_bytes());
let ip = &mut frame[ETH_HEADER_LEN..];
ip[0] = 0x45; ip[2..4].copy_from_slice(&(ip_total_len as u16).to_be_bytes());
ip[8] = 64; ip[9] = 17; ip[12..16].copy_from_slice(&src_ip.octets());
ip[16..20].copy_from_slice(&dst_ip.octets());
let ip_cksum = ipv4_header_checksum(&ip[..20]);
ip[10..12].copy_from_slice(&ip_cksum.to_be_bytes());
let udp_start = ETH_HEADER_LEN + 20;
frame[udp_start..udp_start + 2].copy_from_slice(&src_port.to_be_bytes());
frame[udp_start + 2..udp_start + 4].copy_from_slice(&dst_port.to_be_bytes());
frame[udp_start + 4..udp_start + 6].copy_from_slice(&(udp_len as u16).to_be_bytes());
frame[udp_start + 6..udp_start + 8].copy_from_slice(&[0, 0]);
frame[udp_start + 8..].copy_from_slice(payload);
let udp_cksum = udp_checksum(src_ip, dst_ip, &frame[udp_start..]);
frame[udp_start + 6..udp_start + 8].copy_from_slice(&udp_cksum.to_be_bytes());
frame
}