1
0
mirror of https://github.com/danog/dns.git synced 2025-01-23 05:51:11 +01:00

Merge branch '0.1' into 0.2

This commit is contained in:
Chris Wright 2014-06-17 18:06:25 +01:00
commit d4257d132f
3 changed files with 80 additions and 13 deletions

View File

@ -7,4 +7,5 @@ class AddressModes
const INET4_ADDR = 1; const INET4_ADDR = 1;
const INET6_ADDR = 2; const INET6_ADDR = 2;
const PREFER_INET6 = 4; const PREFER_INET6 = 4;
const CNAME = 8;
} }

View File

@ -206,24 +206,41 @@ class Client
{ {
$packet = fread($this->socket, 512); $packet = fread($this->socket, 512);
$response = $this->responseInterpreter->interpret($packet); // Decode the response and clean up the pending requests list
if ($response === null) { $decoded = $this->responseInterpreter->decode($packet);
if ($decoded === null) {
return; return;
} }
list($id, $addr, $ttl) = $response; list($id, $response) = $decoded;
$request = $this->pendingRequestsById[$id]; $request = $this->pendingRequestsById[$id];
$type = $request['type'];
$name = $request['name']; $name = $request['name'];
$this->reactor->cancel($request['timeout_id']); $this->reactor->cancel($request['timeout_id']);
unset($this->pendingRequestsById[$id], $this->pendingRequestsByNameAndType[$name][$type]); unset($this->pendingRequestsById[$id], $this->pendingRequestsByNameAndType[$name][$request['type']]);
if (!$this->pendingRequestsById) { if (!$this->pendingRequestsById) {
$this->reactor->cancel($this->readWatcherId); $this->reactor->cancel($this->readWatcherId);
$this->readWatcherId = null; $this->readWatcherId = null;
} }
if ($addr !== null) {
// Interpret the response and make sure we have at least one resource record
$interpreted = $this->responseInterpreter->interpret($response, $request['type']);
if ($interpreted === null) {
foreach ($request['lookups'] as $id => $lookup) {
$this->processPendingLookup($id);
}
return;
}
// Distribute the result to the appropriate lookup routine
list($type, $addr, $ttl) = $interpreted;
if ($type === AddressModes::CNAME) {
foreach ($request['lookups'] as $id => $lookup) {
$this->redirectPendingLookup($id, $addr);
}
} else if ($addr !== null) {
if ($this->cache) { if ($this->cache) {
$this->cache->store($name, $addr, $type, $ttl); $this->cache->store($name, $addr, $type, $ttl);
} }
@ -289,6 +306,21 @@ class Client
} }
} }
/**
* Redirect a lookup to search for another name
*
* @param int $id
* @param string $name
*/
private function redirectPendingLookup($id, $name)
{
array_unshift($this->pendingLookups[$id]['requests'], $this->pendingLookups[$id]['last_type']);
$this->pendingLookups[$id]['last_type'] = null;
$this->pendingLookups[$id]['name'] = $name;
$this->processPendingLookup($id);
}
/** /**
* Resolve a name from a server * Resolve a name from a server
* *

View File

@ -3,7 +3,9 @@
namespace Addr; namespace Addr;
use LibDNS\Decoder\Decoder, use LibDNS\Decoder\Decoder,
LibDNS\Messages\MessageTypes; LibDNS\Messages\Message,
LibDNS\Messages\MessageTypes,
LibDNS\Records\ResourceTypes;
class ResponseInterpreter class ResponseInterpreter
{ {
@ -23,12 +25,12 @@ class ResponseInterpreter
} }
/** /**
* Extract the message ID and response data from a DNS response packet * Attempt to decode a data packet to a DNS response message
* *
* @param string $packet * @param string $packet
* @return array|null * @return Message|null
*/ */
public function interpret($packet) public function decode($packet)
{ {
try { try {
$message = $this->decoder->decode($packet); $message = $this->decoder->decode($packet);
@ -40,13 +42,45 @@ class ResponseInterpreter
return null; return null;
} }
return [$message->getID(), $message];
}
/**
* Extract the message ID and response data from a DNS response packet
*
* @param Message $message
* @param int $expectedType
* @return array|null
*/
public function interpret($message, $expectedType)
{
static $typeMap = [
AddressModes::INET4_ADDR => ResourceTypes::A,
AddressModes::INET6_ADDR => ResourceTypes::AAAA,
];
$answers = $message->getAnswerRecords(); $answers = $message->getAnswerRecords();
if (!count($answers)) { if (!count($answers)) {
return [$message->getID(), null]; return null;
} }
/** @var \LibDNS\Records\Resource $record */ /** @var \LibDNS\Records\Resource $record */
$record = $answers->getRecordByIndex(0); $cname = null;
return [$message->getID(), (string)$record->getData(), $record->getTTL()]; foreach ($answers as $record) {
switch ($record->getType()) {
case $typeMap[$expectedType]:
return [$expectedType, (string)$record->getData(), $record->getTTL()];
case ResourceTypes::CNAME:
$cname = (string)$record->getData();
break;
}
}
if ($cname) {
return [AddressModes::CNAME, $cname, null];
}
return null;
} }
} }