1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
use super::{decode_u8, DecodeError, DecodeResult}; use crate::DomainName; use std::ops::Deref; use std::str::from_utf8; const DOMAIN_NAME_MAX_RECURSION: usize = 16; impl DomainName { pub fn decode<T>(bytes: &T, offset: &mut usize) -> DecodeResult<DomainName> where T: Deref<Target = [u8]>, { let mut domain_name = DomainName::default(); DomainName::decode_recursion(bytes, offset, &mut domain_name, 0)?; Ok(domain_name) } fn decode_recursion<T>( bytes: &T, offset: &mut usize, domain_name: &mut DomainName, recursion: usize, ) -> DecodeResult<()> where T: Deref<Target = [u8]>, { if recursion > DOMAIN_NAME_MAX_RECURSION { return Err(DecodeError::MaxRecursionError); } let mut length = decode_u8(bytes, offset)?; while length != 0 { let compressed = (length & 0b1100_0000) == 0b1100_0000; if compressed { let buffer = decode_u8(bytes, offset)?; let mut recursion_offset = ((length as usize & 0b0011_1111) << 8) as usize | buffer as usize; DomainName::decode_recursion( bytes, &mut recursion_offset, domain_name, recursion + 1, )?; break; } else { let start = *offset; *offset += length as usize; if let Some(buffer) = bytes.get(start..*offset) { let label = from_utf8(buffer)?; domain_name.append_label(label)?; } else { return Err(DecodeError::NotEnoughData); } length = decode_u8(bytes, offset)?; } } Ok(()) } }