Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distant master #1

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
8 changes: 6 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
"license": "MIT",
"keywords": ["dns"],
"require": {
"php": ">=5.4.0"
"php": ">=7.0"
},
"autoload": {
"psr-4": {
"LibDNS\\": "src/"
}
},
"files": ["src/functions.php"]
},
"support": {
"issues": "https://github.com/DaveRandom/LibDNS/issues"
},
"suggest": {
"ext-intl": "Required for IDN support"
}
}
2 changes: 1 addition & 1 deletion examples/AQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
use \LibDNS\Decoder\DecoderFactory;

// Config
$queryName = 'google.com';
$queryName = 'faß.de';
$serverIP = '8.8.8.8';
$requestTimeout = 3;

Expand Down
112 changes: 57 additions & 55 deletions src/Decoder/Decoder.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* Decodes raw network data to Message objects
*
Expand All @@ -13,24 +13,26 @@
*/
namespace LibDNS\Decoder;

use \LibDNS\Packets\PacketFactory;
use \LibDNS\Packets\Packet;
use \LibDNS\Messages\MessageFactory;
use \LibDNS\Messages\Message;
use \LibDNS\Records\QuestionFactory;
use \LibDNS\Records\ResourceBuilder;
use \LibDNS\Records\Types\Type;
use \LibDNS\Records\Types\Anything;
use \LibDNS\Records\Types\BitMap;
use \LibDNS\Records\Types\Char;
use \LibDNS\Records\Types\CharacterString;
use \LibDNS\Records\Types\DomainName;
use \LibDNS\Records\Types\IPv4Address;
use \LibDNS\Records\Types\IPv6Address;
use \LibDNS\Records\Types\Long;
use \LibDNS\Records\Types\Short;
use \LibDNS\Records\Types\Types;
use \LibDNS\Records\Types\TypeBuilder;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Packets\Packet;
use LibDNS\Packets\PacketFactory;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\Resource;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\Types;

/**
* Decodes raw network data to Message objects
Expand Down Expand Up @@ -94,7 +96,7 @@ public function __construct(
ResourceBuilder $resourceBuilder,
TypeBuilder $typeBuilder,
DecodingContextFactory $decodingContextFactory,
$allowTrailingData = false
bool $allowTrailingData = true
) {
$this->packetFactory = $packetFactory;
$this->messageFactory = $messageFactory;
Expand All @@ -113,7 +115,7 @@ public function __construct(
* @return string
* @throws \UnexpectedValueException When the read operation does not result in the requested number of bytes
*/
private function readDataFromPacket(Packet $packet, $length)
private function readDataFromPacket(Packet $packet, int $length): string
{
if ($packet->getBytesRemaining() < $length) {
throw new \UnexpectedValueException('Decode error: Incomplete packet (tried to read ' . $length . ' bytes from index ' . $packet->getPointer());
Expand All @@ -131,7 +133,7 @@ private function readDataFromPacket(Packet $packet, $length)
*/
private function decodeHeader(DecodingContext $decodingContext, Message $message)
{
$header = unpack('nid/nmeta/nqd/nan/nns/nar', $this->readDataFromPacket($decodingContext->getPacket(), 12));
$header = \unpack('nid/nmeta/nqd/nan/nns/nar', $this->readDataFromPacket($decodingContext->getPacket(), 12));
if (!$header) {
throw new \UnexpectedValueException('Decode error: Header unpack failed');
}
Expand All @@ -140,10 +142,10 @@ private function decodeHeader(DecodingContext $decodingContext, Message $message

$message->setType(($header['meta'] & 0b1000000000000000) >> 15);
$message->setOpCode(($header['meta'] & 0b0111100000000000) >> 11);
$message->isAuthoritative(($header['meta'] & 0b0000010000000000) >> 10);
$message->isTruncated(($header['meta'] & 0b0000001000000000) >> 9);
$message->isRecursionDesired(($header['meta'] & 0b0000000100000000) >> 8);
$message->isRecursionAvailable(($header['meta'] & 0b0000000010000000) >> 7);
$message->isAuthoritative((bool)(($header['meta'] & 0b0000010000000000) >> 10));
$message->isTruncated((bool)(($header['meta'] & 0b0000001000000000) >> 9));
$message->isRecursionDesired((bool)(($header['meta'] & 0b0000000100000000) >> 8));
$message->isRecursionAvailable((bool)(($header['meta'] & 0b0000000010000000) >> 7));
$message->setResponseCode($header['meta'] & 0b0000000000001111);

$decodingContext->setExpectedQuestionRecords($header['qd']);
Expand All @@ -161,7 +163,7 @@ private function decodeHeader(DecodingContext $decodingContext, Message $message
* @return int The number of packet bytes consumed by the operation
* @throws \UnexpectedValueException When the packet data is invalid
*/
private function decodeAnything(DecodingContext $decodingContext, Anything $anything, $length)
private function decodeAnything(DecodingContext $decodingContext, Anything $anything, int $length): int
{
$anything->setValue($this->readDataFromPacket($decodingContext->getPacket(), $length));

Expand All @@ -177,7 +179,7 @@ private function decodeAnything(DecodingContext $decodingContext, Anything $anyt
* @return int The number of packet bytes consumed by the operation
* @throws \UnexpectedValueException When the packet data is invalid
*/
private function decodeBitMap(DecodingContext $decodingContext, BitMap $bitMap, $length)
private function decodeBitMap(DecodingContext $decodingContext, BitMap $bitMap, int $length): int
{
$bitMap->setValue($this->readDataFromPacket($decodingContext->getPacket(), $length));

Expand All @@ -192,9 +194,9 @@ private function decodeBitMap(DecodingContext $decodingContext, BitMap $bitMap,
* @return int The number of packet bytes consumed by the operation
* @throws \UnexpectedValueException When the packet data is invalid
*/
private function decodeChar(DecodingContext $decodingContext, Char $char)
private function decodeChar(DecodingContext $decodingContext, Char $char): int
{
$value = unpack('C', $this->readDataFromPacket($decodingContext->getPacket(), 1))[1];
$value = \unpack('C', $this->readDataFromPacket($decodingContext->getPacket(), 1))[1];
$char->setValue($value);

return 1;
Expand All @@ -208,10 +210,10 @@ private function decodeChar(DecodingContext $decodingContext, Char $char)
* @return int The number of packet bytes consumed by the operation
* @throws \UnexpectedValueException When the packet data is invalid
*/
private function decodeCharacterString(DecodingContext $decodingContext, CharacterString $characterString)
private function decodeCharacterString(DecodingContext $decodingContext, CharacterString $characterString): int
{
$packet = $decodingContext->getPacket();
$length = ord($this->readDataFromPacket($packet, 1));
$length = \ord($this->readDataFromPacket($packet, 1));
$characterString->setValue($this->readDataFromPacket($packet, $length));

return $length + 1;
Expand All @@ -225,32 +227,32 @@ private function decodeCharacterString(DecodingContext $decodingContext, Charact
* @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)
private function decodeDomainName(DecodingContext $decodingContext, DomainName $domainName): int
{
$packet = $decodingContext->getPacket();
$startIndex = '0x' . dechex($packet->getPointer());
$startIndex = '0x' . \dechex($packet->getPointer());
$labelRegistry = $decodingContext->getLabelRegistry();

$labels = [];
$totalLength = 0;

while (++$totalLength && $length = ord($this->readDataFromPacket($packet, 1))) {
while (++$totalLength && $length = \ord($this->readDataFromPacket($packet, 1))) {
$labelType = $length & 0b11000000;

if ($labelType === 0b00000000) {
$index = $packet->getPointer() - 1;
$label = $this->readDataFromPacket($packet, $length);

array_unshift($labels, [$index, $label]);
\array_unshift($labels, [$index, $label]);
$totalLength += $length;
} else if ($labelType === 0b11000000) {
$index = (($length & 0b00111111) << 8) | ord($this->readDataFromPacket($packet, 1));
$index = (($length & 0b00111111) << 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);
\array_unshift($labels, $ref);
$totalLength++;

break;
Expand All @@ -265,8 +267,8 @@ private function decodeDomainName(DecodingContext $decodingContext, DomainName $

$result = [];
foreach ($labels as $label) {
if (is_int($label[0])) {
array_unshift($result, $label[1]);
if (\is_int($label[0])) {
\array_unshift($result, $label[1]);
$labelRegistry->register($result, $label[0]);
} else {
$result = $label;
Expand All @@ -285,9 +287,9 @@ private function decodeDomainName(DecodingContext $decodingContext, DomainName $
* @return int The number of packet bytes consumed by the operation
* @throws \UnexpectedValueException When the packet data is invalid
*/
private function decodeIPv4Address(DecodingContext $decodingContext, IPv4Address $ipv4Address)
private function decodeIPv4Address(DecodingContext $decodingContext, IPv4Address $ipv4Address): int
{
$octets = unpack('C4', $this->readDataFromPacket($decodingContext->getPacket(), 4));
$octets = \unpack('C4', $this->readDataFromPacket($decodingContext->getPacket(), 4));
$ipv4Address->setOctets($octets);

return 4;
Expand All @@ -301,9 +303,9 @@ private function decodeIPv4Address(DecodingContext $decodingContext, IPv4Address
* @return int The number of packet bytes consumed by the operation
* @throws \UnexpectedValueException When the packet data is invalid
*/
private function decodeIPv6Address(DecodingContext $decodingContext, IPv6Address $ipv6Address)
private function decodeIPv6Address(DecodingContext $decodingContext, IPv6Address $ipv6Address): int
{
$shorts = unpack('n8', $this->readDataFromPacket($decodingContext->getPacket(), 16));
$shorts = \unpack('n8', $this->readDataFromPacket($decodingContext->getPacket(), 16));
$ipv6Address->setShorts($shorts);

return 16;
Expand All @@ -317,9 +319,9 @@ private function decodeIPv6Address(DecodingContext $decodingContext, IPv6Address
* @return int The number of packet bytes consumed by the operation
* @throws \UnexpectedValueException When the packet data is invalid
*/
private function decodeLong(DecodingContext $decodingContext, Long $long)
private function decodeLong(DecodingContext $decodingContext, Long $long): int
{
$value = unpack('N', $this->readDataFromPacket($decodingContext->getPacket(), 4))[1];
$value = \unpack('N', $this->readDataFromPacket($decodingContext->getPacket(), 4))[1];
$long->setValue($value);

return 4;
Expand All @@ -333,9 +335,9 @@ private function decodeLong(DecodingContext $decodingContext, Long $long)
* @return int The number of packet bytes consumed by the operation
* @throws \UnexpectedValueException When the packet data is invalid
*/
private function decodeShort(DecodingContext $decodingContext, Short $short)
private function decodeShort(DecodingContext $decodingContext, Short $short): int
{
$value = unpack('n', $this->readDataFromPacket($decodingContext->getPacket(), 2))[1];
$value = \unpack('n', $this->readDataFromPacket($decodingContext->getPacket(), 2))[1];
$short->setValue($value);

return 2;
Expand All @@ -351,7 +353,7 @@ private function decodeShort(DecodingContext $decodingContext, Short $short)
* @throws \UnexpectedValueException When the packet data is invalid
* @throws \InvalidArgumentException When the Type subtype is unknown
*/
private function decodeType(DecodingContext $decodingContext, Type $type, $length)
private function decodeType(DecodingContext $decodingContext, Type $type, int $length): int
{
if ($type instanceof Anything) {
$result = $this->decodeAnything($decodingContext, $type, $length);
Expand All @@ -372,7 +374,7 @@ private function decodeType(DecodingContext $decodingContext, Type $type, $lengt
} else if ($type instanceof Short) {
$result = $this->decodeShort($decodingContext, $type);
} else {
throw new \InvalidArgumentException('Unknown Type ' . get_class($type));
throw new \InvalidArgumentException('Unknown Type ' . \get_class($type));
}

return $result;
Expand All @@ -385,12 +387,12 @@ private function decodeType(DecodingContext $decodingContext, Type $type, $lengt
* @return \LibDNS\Records\Question
* @throws \UnexpectedValueException When the record is invalid
*/
private function decodeQuestionRecord(DecodingContext $decodingContext)
private function decodeQuestionRecord(DecodingContext $decodingContext): Question
{
/** @var \LibDNS\Records\Types\DomainName $domainName */
$domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
$this->decodeDomainName($decodingContext, $domainName);
$meta = unpack('ntype/nclass', $this->readDataFromPacket($decodingContext->getPacket(), 4));
$meta = \unpack('ntype/nclass', $this->readDataFromPacket($decodingContext->getPacket(), 4));

$question = $this->questionFactory->create($meta['type']);
$question->setName($domainName);
Expand All @@ -407,12 +409,12 @@ private function decodeQuestionRecord(DecodingContext $decodingContext)
* @throws \UnexpectedValueException When the record is invalid
* @throws \InvalidArgumentException When a type subtype is unknown
*/
private function decodeResourceRecord(DecodingContext $decodingContext)
private function decodeResourceRecord(DecodingContext $decodingContext): Resource
{
/** @var \LibDNS\Records\Types\DomainName $domainName */
$domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
$this->decodeDomainName($decodingContext, $domainName);
$meta = unpack('ntype/nclass/Nttl/nlength', $this->readDataFromPacket($decodingContext->getPacket(), 10));
$meta = \unpack('ntype/nclass/Nttl/nlength', $this->readDataFromPacket($decodingContext->getPacket(), 10));

$resource = $this->resourceBuilder->build($meta['type']);
$resource->setName($domainName);
Expand Down Expand Up @@ -452,7 +454,7 @@ private function decodeResourceRecord(DecodingContext $decodingContext)
* @throws \UnexpectedValueException When the packet data is invalid
* @throws \InvalidArgumentException When a type subtype is unknown
*/
public function decode($data)
public function decode(string $data): Message
{
$packet = $this->packetFactory->create($data);
$decodingContext = $this->decodingContextFactory->create($packet);
Expand Down
4 changes: 2 additions & 2 deletions src/Decoder/DecoderFactory.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?php
<?php declare(strict_types=1);
/**
* Creates Decoder objects
*
Expand Down Expand Up @@ -43,7 +43,7 @@ class DecoderFactory
* @param bool $allowTrailingData
* @return Decoder
*/
public function create(TypeDefinitionManager $typeDefinitionManager = null, $allowTrailingData = false)
public function create(TypeDefinitionManager $typeDefinitionManager = null, bool $allowTrailingData = true): Decoder
{
$typeBuilder = new TypeBuilder(new TypeFactory);

Expand Down
Loading