/** * Decode a DomainName field * * @param \LibDNS\Decoder\DecodingContext $decodingContext * @param \LibDNS\Records\Types\DomainName $domainName The object to populate with the result * @return int The number of packet bytes consumed by the operation * @throws \UnexpectedValueException When the packet data is invalid */ private function decodeDomainName(DecodingContext $decodingContext, DomainName $domainName) { $packet = $decodingContext->getPacket(); $startIndex = '0x' . dechex($packet->getPointer()); $labelRegistry = $decodingContext->getLabelRegistry(); $labels = []; $totalLength = 0; while (++$totalLength && ($length = ord($this->readDataFromPacket($packet, 1)))) { $labelType = $length & 0b11000000; if ($labelType === 0b0) { $index = $packet->getPointer() - 1; $label = $this->readDataFromPacket($packet, $length); array_unshift($labels, [$index, $label]); $totalLength += $length; } else { if ($labelType === 0b11000000) { $index = ($length & 0b111111) << 8 | ord($this->readDataFromPacket($packet, 1)); $ref = $labelRegistry->lookupLabel($index); if ($ref === null) { throw new \UnexpectedValueException('Decode error: Invalid compression pointer reference in domain name at position ' . $startIndex); } array_unshift($labels, $ref); $totalLength++; break; } else { throw new \UnexpectedValueException('Decode error: Invalid label type ' . $labelType . 'in domain name at position ' . $startIndex); } } } if (!$labels) { throw new \UnexpectedValueException('Decode error: Empty domain name at position ' . $startIndex); } $result = []; foreach ($labels as $label) { if (is_int($label[0])) { array_unshift($result, $label[1]); $labelRegistry->register($result, $label[0]); } else { $result = $label; } } $domainName->setLabels($result); return $totalLength; }
/** * Encode a DomainName field * * @param \LibDNS\Records\Types\DomainName $domainName * @param \LibDNS\Encoder\EncodingContext $encodingContext * @return string */ private function encodeDomainName(DomainName $domainName, EncodingContext $encodingContext) { $packetIndex = $encodingContext->getPacket()->getLength() + 12; $labelRegistry = $encodingContext->getLabelRegistry(); $result = ''; $labels = $domainName->getLabels(); if ($encodingContext->useCompression()) { do { $part = implode('.', $labels); $index = $labelRegistry->lookupIndex($part); if ($index === null) { $labelRegistry->register($part, $packetIndex); $label = array_shift($labels); $length = strlen($label); $result .= chr($length) . $label; $packetIndex += $length + 1; } else { $result .= pack('n', 0b1100000000000000 | $index); break; } } while ($labels); if (!$labels) { $result .= ""; } } else { foreach ($labels as $label) { $result .= chr(strlen($label)) . $label; } $result .= ""; } return $result; }