/** * 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; }