From aa227cf2d2c1b45285d0848fdf0f7fafb60adffa Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Wed, 12 Jun 2019 14:47:23 +0200 Subject: [PATCH] Make JSON parser a separate dependency --- composer.json | 1 + lib/Internal/HttpsSocket.php | 4 +- lib/JsonDecoder.php | 369 ------------------------------- lib/JsonDecoderFactory.php | 63 ------ lib/QueryEncoder.php | 56 ----- lib/QueryEncoderFactory.php | 35 --- test/JsonDecoderFactoryTest.php | 15 -- test/JsonDecoderTest.php | 185 ---------------- test/QueryEncoderFactoryTest.php | 15 -- test/QueryEncoderTest.php | 208 ----------------- 10 files changed, 3 insertions(+), 948 deletions(-) delete mode 100644 lib/JsonDecoder.php delete mode 100644 lib/JsonDecoderFactory.php delete mode 100644 lib/QueryEncoder.php delete mode 100644 lib/QueryEncoderFactory.php delete mode 100644 test/JsonDecoderFactoryTest.php delete mode 100644 test/JsonDecoderTest.php delete mode 100644 test/QueryEncoderFactoryTest.php delete mode 100644 test/QueryEncoderTest.php diff --git a/composer.json b/composer.json index 38ee127..3bc20c5 100644 --- a/composer.json +++ b/composer.json @@ -44,6 +44,7 @@ "php": ">=7.0", "amphp/cache": "^1.2", "amphp/parser": "^1", + "danog/libdns-json": "^0.1", "daverandom/libdns": "^2.0.1", "amphp/amp": "^2", "amphp/artax": "dev-master", diff --git a/lib/Internal/HttpsSocket.php b/lib/Internal/HttpsSocket.php index 6e38384..667c88b 100644 --- a/lib/Internal/HttpsSocket.php +++ b/lib/Internal/HttpsSocket.php @@ -5,14 +5,14 @@ namespace Amp\DoH\Internal; use Amp\Artax\Client; use Amp\Artax\Request; use Amp\DoH\DoHException; -use Amp\DoH\JsonDecoderFactory; use Amp\DoH\Nameserver; -use Amp\DoH\QueryEncoderFactory; use Amp\Promise; use LibDNS\Decoder\DecoderFactory; use LibDNS\Encoder\EncoderFactory; use LibDNS\Messages\Message; use function Amp\call; +use danog\LibDNSJson\QueryEncoderFactory; +use danog\LibDNSJson\JsonDecoderFactory; /** @internal */ final class HttpsSocket extends Socket diff --git a/lib/JsonDecoder.php b/lib/JsonDecoder.php deleted file mode 100644 index d72b99b..0000000 --- a/lib/JsonDecoder.php +++ /dev/null @@ -1,369 +0,0 @@ -, Chris Wright - */ -class JsonDecoder -{ - /** - * @var \LibDNS\Packets\PacketFactory - */ - private $packetFactory; - - /** - * @var \LibDNS\Messages\MessageFactory - */ - private $messageFactory; - - /** - * @var \LibDNS\Records\QuestionFactory - */ - private $questionFactory; - - /** - * @var \LibDNS\Records\ResourceBuilder - */ - private $resourceBuilder; - - /** - * @var \LibDNS\Records\Types\TypeBuilder - */ - private $typeBuilder; - - /** - * @var \LibDNS\Decoder\DecodingContextFactory - */ - private $decodingContextFactory; - - /** - * Constructor. - * - * @param \LibDNS\Packets\PacketFactory $packetFactory - * @param \LibDNS\Messages\MessageFactory $messageFactory - * @param \LibDNS\Records\QuestionFactory $questionFactory - * @param \LibDNS\Records\ResourceBuilder $resourceBuilder - * @param \LibDNS\Records\Types\TypeBuilder $typeBuilder - * @param \LibDNS\Decoder\DecodingContextFactory $decodingContextFactory - * @param bool $allowTrailingData - */ - public function __construct( - PacketFactory $packetFactory, - MessageFactory $messageFactory, - QuestionFactory $questionFactory, - ResourceBuilder $resourceBuilder, - TypeBuilder $typeBuilder, - DecodingContextFactory $decodingContextFactory - ) { - $this->packetFactory = $packetFactory; - $this->messageFactory = $messageFactory; - $this->questionFactory = $questionFactory; - $this->resourceBuilder = $resourceBuilder; - $this->typeBuilder = $typeBuilder; - $this->decodingContextFactory = $decodingContextFactory; - } - /** - * Decode a question record. - * - * - * @return \LibDNS\Records\Question - * @throws \UnexpectedValueException When the record is invalid - */ - private function decodeQuestionRecord(array $record): Question - { - /** @var \LibDNS\Records\Types\DomainName $domainName */ - $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME); - $labels = \explode('.', $record['name']); - if (!empty($last = \array_pop($labels))) { - $labels[] = $last; - } - $domainName->setLabels($labels); - - $question = $this->questionFactory->create($record['type']); - $question->setName($domainName); - //$question->setClass($meta['class']); - return $question; - } - - /** - * Decode a resource record. - * - * - * @return \LibDNS\Records\Resource - * @throws \UnexpectedValueException When the record is invalid - * @throws \InvalidArgumentException When a type subtype is unknown - */ - private function decodeResourceRecord(array $record): Resource - { - /** @var \LibDNS\Records\Types\DomainName $domainName */ - $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME); - $labels = \explode('.', $record['name']); - if (!empty($last = \array_pop($labels))) { - $labels[] = $last; - } - $domainName->setLabels($labels); - $resource = $this->resourceBuilder->build($record['type']); - $resource->setName($domainName); - //$resource->setClass($meta['class']); - $resource->setTTL($record['TTL']); - - $data = $resource->getData(); - - $fieldDef = $index = null; - foreach ($resource->getData()->getTypeDefinition() as $index => $fieldDef) { - $field = $this->typeBuilder->build($fieldDef->getType()); - $this->decodeType($field, $record['data']); - $data->setField($index, $field); - break; // For now parse only one field - } - - return $resource; - } - /** - * Decode a Type field. - * - * - * @param \LibDNS\Records\Types\Type $type The object to populate with the result - * @throws \UnexpectedValueException When the packet data is invalid - * @throws \InvalidArgumentException When the Type subtype is unknown - */ - private function decodeType(Type $type, $data) - { - if ($type instanceof Anything) { - $this->decodeAnything($type, $data); - } elseif ($type instanceof BitMap) { - $this->decodeBitMap($type, $data); - } elseif ($type instanceof Char) { - $this->decodeChar($type, $data); - } elseif ($type instanceof CharacterString) { - $this->decodeCharacterString($type, $data); - } elseif ($type instanceof DomainName) { - $this->decodeDomainName($type, $data); - } elseif ($type instanceof IPv4Address) { - $this->decodeIPv4Address($type, $data); - } elseif ($type instanceof IPv6Address) { - $this->decodeIPv6Address($type, $data); - } elseif ($type instanceof Long) { - $this->decodeLong($type, $data); - } elseif ($type instanceof Short) { - $this->decodeShort($type, $data); - } else { - throw new \InvalidArgumentException('Unknown Type '.\get_class($type)); - } - } - /** - * Decode an Anything field. - * - * - * @param \LibDNS\Records\Types\Anything $anything The object to populate with the result - * @param int $length - * @return int The number of packet bytes consumed by the operation - * @throws \UnexpectedValueException When the packet data is invalid - */ - private function decodeAnything(Anything $anything, $data) - { - $anything->setValue(\hex2bin($data)); - } - - /** - * Decode a BitMap field. - * - * - * @param \LibDNS\Records\Types\BitMap $bitMap The object to populate with the result - * @param int $length - * @return int The number of packet bytes consumed by the operation - * @throws \UnexpectedValueException When the packet data is invalid - */ - private function decodeBitMap(BitMap $bitMap, $data) - { - $bitMap->setValue(\hex2bin($data)); - } - - /** - * Decode a Char field. - * - * - * @param \LibDNS\Records\Types\Char $char 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 decodeChar(Char $char, $result) - { - $value = \unpack('C', $result)[1]; - $char->setValue($value); - } - - /** - * Decode a CharacterString field. - * - * - * @param \LibDNS\Records\Types\CharacterString $characterString 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 decodeCharacterString(CharacterString $characterString, $result) - { - $characterString->setValue($result); - } - - /** - * Decode a DomainName field. - * - * - * @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(DomainName $domainName, $result) - { - $labels = \explode('.', $result); - if (!empty($last = \array_pop($labels))) { - $labels[] = $last; - } - - $domainName->setLabels($labels); - } - - /** - * Decode an IPv4Address field. - * - * - * @param \LibDNS\Records\Types\IPv4Address $ipv4Address 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 decodeIPv4Address(IPv4Address $ipv4Address, $result) - { - $octets = \unpack('C4', \inet_pton($result)); - $ipv4Address->setOctets($octets); - } - - /** - * Decode an IPv6Address field. - * - * - * @param \LibDNS\Records\Types\IPv6Address $ipv6Address 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 decodeIPv6Address(IPv6Address $ipv6Address, $result) - { - $shorts = \unpack('n8', \inet_pton($result)); - $ipv6Address->setShorts($shorts); - } - - /** - * Decode a Long field. - * - * - * @param \LibDNS\Records\Types\Long $long 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 decodeLong(Long $long, $result) - { - $long->setValue((int) $result); - } - - /** - * Decode a Short field. - * - * - * @param \LibDNS\Records\Types\Short $short 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 decodeShort(Short $short, $result) - { - $short->setValue((int) $result); - } - - /** - * Decode a Message from JSON-encoded string. - * - * @param string $data The data string to decode - * @param int $requestId The message ID to set - * @return \LibDNS\Messages\Message - * @throws \UnexpectedValueException When the packet data is invalid - * @throws \InvalidArgumentException When a type subtype is unknown - */ - public function decode(string $result, int $requestId): Message - { - $result = \json_decode($result, true); - if ($result === false) { - $error = \json_last_error_msg(); - throw new DnsException("Could not decode JSON DNS payload ($error)"); - } - if (!isset($result['Status'], $result['TC'], $result['RD'], $result['RA'])) { - throw new DnsException('Wrong reply from server, missing required fields'); - } - - $message = $this->messageFactory->create(); - $decodingContext = $this->decodingContextFactory->create($this->packetFactory->create()); - - //$message->isAuthoritative(true); - $message->setType(MessageTypes::RESPONSE); - $message->setID($requestId); - $message->setResponseCode($result['Status']); - $message->isTruncated($result['TC']); - $message->isRecursionDesired($result['RD']); - $message->isRecursionAvailable($result['RA']); - - $decodingContext->setExpectedQuestionRecords(isset($result['Question']) ? \count($result['Question']) : 0); - $decodingContext->setExpectedAnswerRecords(isset($result['Answer']) ? \count($result['Answer']) : 0); - $decodingContext->setExpectedAuthorityRecords(0); - $decodingContext->setExpectedAdditionalRecords(isset($result['Additional']) ? \count($result['Additional']) : 0); - - $questionRecords = $message->getQuestionRecords(); - $expected = $decodingContext->getExpectedQuestionRecords(); - for ($i = 0; $i < $expected; $i++) { - $questionRecords->add($this->decodeQuestionRecord($result['Question'][$i])); - } - - $answerRecords = $message->getAnswerRecords(); - $expected = $decodingContext->getExpectedAnswerRecords(); - for ($i = 0; $i < $expected; $i++) { - $answerRecords->add($this->decodeResourceRecord($result['Answer'][$i])); - } - - $authorityRecords = $message->getAuthorityRecords(); - $expected = $decodingContext->getExpectedAuthorityRecords(); - for ($i = 0; $i < $expected; $i++) { - $authorityRecords->add($this->decodeResourceRecord($result['Authority'][$i])); - } - - $additionalRecords = $message->getAdditionalRecords(); - $expected = $decodingContext->getExpectedAdditionalRecords(); - for ($i = 0; $i < $expected; $i++) { - $additionalRecords->add($this->decodeResourceRecord($result['Additional'][$i])); - } - return $message; - } -} diff --git a/lib/JsonDecoderFactory.php b/lib/JsonDecoderFactory.php deleted file mode 100644 index 07cad26..0000000 --- a/lib/JsonDecoderFactory.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @copyright Copyright (c) Chris Wright , - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -namespace Amp\DoH; - -use \LibDNS\Messages\MessageFactory; -use \LibDNS\Packets\PacketFactory; -use \LibDNS\Records\QuestionFactory; -use \LibDNS\Records\RDataBuilder; -use \LibDNS\Records\RDataFactory; -use \LibDNS\Records\RecordCollectionFactory; -use \LibDNS\Records\ResourceBuilder; -use \LibDNS\Records\ResourceFactory; -use \LibDNS\Records\TypeDefinitions\FieldDefinitionFactory; -use \LibDNS\Records\TypeDefinitions\TypeDefinitionFactory; -use \LibDNS\Records\TypeDefinitions\TypeDefinitionManager; -use \LibDNS\Records\Types\TypeBuilder; -use \LibDNS\Records\Types\TypeFactory; -use LibDNS\Decoder\DecodingContextFactory; - -/** - * Creates JsonDecoder objects. - * - * @author Chris Wright - */ -class JsonDecoderFactory -{ - /** - * Create a new JsonDecoder object. - * - * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager - * @return JsonDecoder - */ - public function create(TypeDefinitionManager $typeDefinitionManager = null): JsonDecoder - { - $typeBuilder = new TypeBuilder(new TypeFactory); - - return new JsonDecoder( - new PacketFactory, - new MessageFactory(new RecordCollectionFactory), - new QuestionFactory, - new ResourceBuilder( - new ResourceFactory, - new RDataBuilder( - new RDataFactory, - $typeBuilder - ), - $typeDefinitionManager ?: new TypeDefinitionManager( - new TypeDefinitionFactory, - new FieldDefinitionFactory - ) - ), - $typeBuilder, - new DecodingContextFactory - ); - } -} diff --git a/lib/QueryEncoder.php b/lib/QueryEncoder.php deleted file mode 100644 index 1b44163..0000000 --- a/lib/QueryEncoder.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @copyright Copyright (c) Chris Wright - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 2.0.0 - */ - -namespace Amp\DoH; - -use \LibDNS\Messages\Message; -use Amp\Dns\DnsException; -use LibDNS\Messages\MessageTypes; - -/** - * Encodes Message objects to raw network data. - * - * @category LibDNS - * @package Encoder - * @author Chris Wright - */ -class QueryEncoder -{ - /** - * Encode a Message to URL payload. - * - * @param \LibDNS\Messages\Message $message The Message to encode - * @return string - */ - public function encode(Message $message): string - { - if ($message->getType() !== MessageTypes::QUERY) { - throw new DnsException('Invalid question: is not a question record'); - } - $questions = $message->getQuestionRecords(); - if ($questions->count() === 0) { - throw new DnsException('Invalid question: 0 question records provided'); - } - $question = $questions->getRecordByIndex(0); - return \http_build_query( - [ - 'cd' => 0, // Do not disable result validation - 'do' => 0, // Do not send me DNSSEC data - 'type' => $question->getType(), // Record type being requested - 'name' => \implode('.', $question->getName()->getLabels()), // Record name being requested - 'ct' => 'application/dns-json', // Content-type of request - ] - ); - } -} diff --git a/lib/QueryEncoderFactory.php b/lib/QueryEncoderFactory.php deleted file mode 100644 index fda12cf..0000000 --- a/lib/QueryEncoderFactory.php +++ /dev/null @@ -1,35 +0,0 @@ - - * @copyright Copyright (c) Chris Wright - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @version 2.0.0 - */ - -namespace Amp\DoH; - -/** - * Creates Encoder objects. - * - * @category LibDNS - * @package Encoder - * @author Chris Wright - */ -class QueryEncoderFactory -{ - /** - * Create a new Encoder object. - * - * @return \LibDNS\Encoder\Encoder - */ - public function create(): QueryEncoder - { - return new QueryEncoder(); - } -} diff --git a/test/JsonDecoderFactoryTest.php b/test/JsonDecoderFactoryTest.php deleted file mode 100644 index 158b0ef..0000000 --- a/test/JsonDecoderFactoryTest.php +++ /dev/null @@ -1,15 +0,0 @@ -assertInstanceOf(JsonDecoder::class, (new JsonDecoderFactory)->create()); - } -} diff --git a/test/JsonDecoderTest.php b/test/JsonDecoderTest.php deleted file mode 100644 index 101d1e9..0000000 --- a/test/JsonDecoderTest.php +++ /dev/null @@ -1,185 +0,0 @@ -create(); - $response = $decoder->decode($message, $requestId); - - $this->assertInstanceOf(Message::class, $response); - $this->assertEquals(MessageTypes::RESPONSE, $response->getType()); - } - - public function provideValidJsonPayloads() - { - return [ - [ - '{ - "Status": 0, - "TC": false, - "RD": true, - "RA": true, - "AD": false, - "CD": false, - "Question": - [ - { - "name": "apple.com.", - "type": 1 - } - ], - "Answer": - [ - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.178.96.59" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.172.224.47" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.142.160.59" - } - ], - "Additional": [ ], - "edns_client_subnet": "12.34.56.78/0" - }', - 2, - ], - [ - '{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', - 3, - ], - [ - '{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', - 3, - ], - [ - '{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', - 3, - ], - ]; - } - - - /** - * Test decoding of invalid JSON DNS payloads. - * - * @param string $message - * @param int $requestId - * @return void - * - * @dataProvider provideInvalidJsonPayloads - */ - public function testDecodesInvalidJsonPayloads($message, $requestId) - { - $decoder = (new JsonDecoderFactory)->create(); - $this->expectException(DnsException::class); - $decoder->decode($message, $requestId); - } - - public function provideInvalidJsonPayloads() - { - return [ - [ - '{lmfao - "Status": 0, - "TC": false, - "RD": true, - "RA": true, - "AD": false, - "CD": false, - "Question": - [ - { - "name": "apple.com.", - "type": 1 - } - ], - "Answer": - [ - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.178.96.59" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.172.224.47" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.142.160.59" - } - ], - "Additional": [ ], - "edns_client_subnet": "12.34.56.78/0" - }', - 2, - ], - [ - 'xd{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', - 3, - ], - [ - 'whaaa{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', - 3, - ], - [ - 'xdxdxxxxx{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', - 3, - ], - [ - '{"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', - 3, - ], - [ - '{"Status": 0,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', - 3, - ], - [ - '{"Status": 0,"TC": false,"RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', - 3, - ], - [ - '{"Status": 0,"TC": false,"RD": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', - 3, - ], - [ - 'xd', - 0 - ], - ]; - } -} diff --git a/test/QueryEncoderFactoryTest.php b/test/QueryEncoderFactoryTest.php deleted file mode 100644 index 60fc258..0000000 --- a/test/QueryEncoderFactoryTest.php +++ /dev/null @@ -1,15 +0,0 @@ -assertInstanceOf(QueryEncoder::class, (new QueryEncoderFactory)->create()); - } -} diff --git a/test/QueryEncoderTest.php b/test/QueryEncoderTest.php deleted file mode 100644 index d69fcf4..0000000 --- a/test/QueryEncoderTest.php +++ /dev/null @@ -1,208 +0,0 @@ -create(); - $response = $decoder->decode($message, 0); - $response->setType(MessageTypes::QUERY); - - $encoder = (new QueryEncoderFactory)->create(); - $request = $encoder->encode($response); - - $this->assertInternalType('string', $request, "Got a ".\gettype($request)." instead of a string"); - \parse_str($request, $output); - $this->assertNotEmpty($output); - $this->assertArrayHasKey('cd', $output); - $this->assertArrayHasKey('do', $output); - $this->assertArrayHasKey('ct', $output); - $this->assertArrayHasKey('type', $output); - $this->assertArrayHasKey('name', $output); - $this->assertEquals($output['cd'], 0); - $this->assertEquals($output['do'], 0); - $this->assertEquals($output['ct'], 'application/dns-json'); - $this->assertEquals($output['type'], $response->getQuestionRecords()->getRecordByIndex(0)->getType()); - $this->assertEquals($output['name'], \implode('.', $response->getQuestionRecords()->getRecordByIndex(0)->getName()->getLabels())); - } - - public function provideValidQueryPayloads() - { - return [ - [ - '{ - "Status": 0, - "TC": false, - "RD": true, - "RA": true, - "AD": false, - "CD": false, - "Question": - [ - { - "name": "apple.com.", - "type": 1 - } - ], - "Answer": - [ - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.178.96.59" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.172.224.47" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.142.160.59" - } - ], - "Additional": [ ], - "edns_client_subnet": "12.34.56.78/0" - }', - 2 - ], - [ - '{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', - 3 - ], - [ - '{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', - 3 - ], - [ - '{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', - 3 - ], - ]; - } - - /** - * Test query encoding of invalid DNS payloads. - * - * @param $request - * @return void - * - * @dataProvider provideInvalidQueryPayloads - */ - public function testEncodesInvalidQueryPayloads($request) - { - $encoder = (new QueryEncoderFactory)->create(); - $this->expectException(DnsException::class); - $encoder->encode($request); - } - - public function provideInvalidQueryPayloads() - { - $decoder = (new JsonDecoderFactory)->create(); - return [ - [ - $decoder->decode( - '{ - "Status": 0, - "TC": false, - "RD": true, - "RA": true, - "AD": false, - "CD": false, - "Question": - [ - { - "name": "apple.com.", - "type": 1 - } - ], - "Answer": - [ - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.178.96.59" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.172.224.47" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.142.160.59" - } - ], - "Additional": [ ], - "edns_client_subnet": "12.34.56.78/0" - }', - 2 - ) - ], - [ - $decoder->decode( - '{ - "Status": 0, - "TC": false, - "RD": true, - "RA": true, - "AD": false, - "CD": false, - "Question": - [ - ], - "Answer": - [ - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.178.96.59" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.172.224.47" - }, - { - "name": "apple.com.", - "type": 1, - "TTL": 3599, - "data": "17.142.160.59" - } - ], - "Additional": [ ], - "edns_client_subnet": "12.34.56.78/0" - }', - 2 - ) - ], - ]; - } -}