fn read_qname(&mut self) -> io::Result<String> {
        let mut qname = String::new();
        let start = self.stream_position()?;

        // Read each label one at a time, to build up the full domain name.
        loop {
            // Length of the first label
            let len = self.read_u8()?;
            if len == 0 {
                if qname.is_empty() {
                    qname.push('.') // Root domain
                }
                break;
            }

            match len & 0xC0 {
                // No compression
                0x00 => {
                    let mut label = vec![0; len.into()];
                    self.read_exact(&mut label)?;

                    // Really this is meant to be ASCII, but we read as utf8
                    // (as that what Rust provides).
                    let label = match std::str::from_utf8(&label) {
                        Err(e) => bail!(InvalidData, "invalid label: {}", e),
                        Ok(s) => s,
                    };

                    if !label.is_ascii() {
                        bail!(InvalidData, "invalid label '{:}': not valid ascii", label);
                    }

                    // Now puny decode this label returning its original unicode.
                    let label = match idna::domain_to_unicode(label) {
                        (label, Err(e)) => bail!(InvalidData, "invalid label '{:}': {}", label, e),
                        (label, Ok(_)) => label,
                    };

                    qname.push_str(&label);
                    qname.push('.');
                }

                // Compression
                0xC0 => {
                    // Read the 14 bit pointer.
                    let b2 = self.read_u8()? as u16;
                    let ptr = ((len as u16 & !0xC0) << 8 | b2) as u64;

                    // Make sure we don't get into a loop.
                    if ptr >= start {
                        bail!(
                            InvalidData,
                            "invalid compressed pointer pointing to future bytes"
                        );
                    }

                    // We are going to jump backwards, so record where we
                    // currently are. So we can reset it later.
                    let current = self.stream_position()?;

                    // Jump and start reading the qname again.
                    self.seek(SeekFrom::Start(ptr))?;
                    qname.push_str(&self.read_qname()?);

                    // Reset ourselves.
                    self.seek(SeekFrom::Start(current))?;

                    break;
                }

                // Unknown
                _ => bail!(
                    InvalidData,
                    "unsupported compression type {0:b}",
                    len & 0xC0
                ),
            }
        }

        Ok(qname)
    }
/// Reads a puny encoded domain name from a byte array.
///
/// Used for extracting a encoding ASCII domain name from a DNS message. Will
/// returns the Unicode domain name, as well as the length of this name (ignoring
/// any compressed pointers) in bytes.
///
/// # Errors
///
/// Will return a io::Error(InvalidData) if the read domain name is invalid, or
/// a more general io::Error on any other read failure.
Reads a puny encoded domain name from a byte array.
Used for extracting a encoding ASCII domain name from a DNS message. Will
returns the Unicode domain name, as well as the length of this name (ignoring
any compressed pointers) in bytes.
Reads a puny encoded domain name from a byte array . Used for extracting a encoding ASCII domain name from a DNS message . Will returns the Unicode domain name as well as the length of this name ( ignoring any compressed pointers ) in bytes .
fn read_qname(&mut self) -> io::Result<String> {
        let mut qname = String::new();
        let start = self.stream_position()?;
        // Read each label one at a time, to build up the full domain name.
        loop {
            // Length of the first label
            let len = self.read_u8()?;
            if len == 0 {
                if qname.is_empty() {
                    qname.push('.') // Root domain
                }
                break;
            }
            match len & 0xC0 {
                // No compression
                0x00 => {
                    let mut label = vec![0; len.into()];
                    self.read_exact(&mut label)?;
                    // Really this is meant to be ASCII, but we read as utf8
                    // (as that what Rust provides).
                    let label = match std::str::from_utf8(&label) {
                        Err(e) => bail!(InvalidData, "invalid label: {}", e),
                        Ok(s) => s,
                    };
                    if !label.is_ascii() {
                        bail!(InvalidData, "invalid label '{:}': not valid ascii", label);
                    }
                    // Now puny decode this label returning its original unicode.
                    let label = match idna::domain_to_unicode(label) {
                        (label, Err(e)) => bail!(InvalidData, "invalid label '{:}': {}", label, e),
                        (label, Ok(_)) => label,
                    };
                    qname.push_str(&label);
                    qname.push('.');
                }
                // Compression
                0xC0 => {
                    // Read the 14 bit pointer.
                    let b2 = self.read_u8()? as u16;
                    let ptr = ((len as u16 & !0xC0) << 8 | b2) as u64;
                    // Make sure we don't get into a loop.
                    if ptr >= start {
                        bail!(
                            InvalidData,
                            "invalid compressed pointer pointing to future bytes"
                        );
                    }
                    // We are going to jump backwards, so record where we
                    // currently are. So we can reset it later.
                    let current = self.stream_position()?;
                    // Jump and start reading the qname again.
                    self.seek(SeekFrom::Start(ptr))?;
                    qname.push_str(&self.read_qname()?);
                    // Reset ourselves.
                    self.seek(SeekFrom::Start(current))?;
                    break;
                }
                // Unknown
                _ => bail!(
                    InvalidData,
                    "unsupported compression type {0:b}",
                    len & 0xC0
                ),
            }
        }
        Ok(qname)
    }
fn read_qname ( & mut self ) -> io :: Result < String > { let mut qname = String :: new ( ) ; let start = self . stream_position ( ) ? ; // Read each label one at a time, to build up the full domain name. loop { // Length of the first label let len = self . read_u8 ( ) ? ; if len == 0 { if qname . is_empty ( ) { qname . push ( '.' ) // Root domain } break ; } match len & 0xC0 { // No compression 0x00 => { let mut label = vec ! [ 0 len into ( ) ] ; self . read_exact ( & mut label ) ? ; // Really this is meant to be ASCII, but we read as utf8 // (as that what Rust provides). let label = match std :: str :: from_utf8 ( & label ) { Err ( e ) => bail ! ( InvalidData " " e ) , Ok ( s ) => s , } ; if ! label . is_ascii ( ) { bail ! ( InvalidData " " label ) ; } // Now puny decode this label returning its original unicode. let label = match idna :: domain_to_unicode ( label ) { ( label , Err ( e ) ) => bail ! ( InvalidData " " label e ) , ( label , Ok ( _ ) ) => label , } ; qname . push_str ( & label ) ; qname . push ( '.' ) ; } // Compression 0xC0 => { // Read the 14 bit pointer. let b2 = self . read_u8 ( ) ? as u16 ; let ptr = ( ( len as u16 & ! 0xC0 ) << 8 | b2 ) as u64 ; // Make sure we don't get into a loop. if ptr >= start { bail ! ( InvalidData " " ) ; } // We are going to jump backwards, so record where we // currently are. So we can reset it later. let current = self . stream_position ( ) ? ; // Jump and start reading the qname again. self . seek ( SeekFrom :: Start ( ptr ) ) ? ; qname . push_str ( & self . read_qname ( ) ? ) ; // Reset ourselves. self . seek ( SeekFrom :: Start ( current ) ) ? ; break ; } // Unknown _ => bail ! ( InvalidData " " len 0xC0 ) , } } Ok ( qname ) }
Reads a puny encoded domain name from a byte array.
Reads a puny encoded domain name from a byte array .
&mut self
errors
Will return a io::Error(InvalidData) if the read domain name is invalid, or
a more general io::Error on any other read failure.
Will return a io :: Error ( InvalidData ) if the read domain name is invalid or a more general io :: Error on any other read failure .