1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
<?php
namespace React\Dns\Resolver;
use React\Dns\Query\ExecutorInterface;
use React\Dns\Query\Query;
use React\Dns\RecordNotFoundException;
use React\Dns\Model\Message;
class Resolver
{
private $nameserver;
private $executor;
public function __construct($nameserver, ExecutorInterface $executor)
{
$this->nameserver = $nameserver;
$this->executor = $executor;
}
public function resolve($domain)
{
$query = new Query($domain, Message::TYPE_A, Message::CLASS_IN, time());
$that = $this;
return $this->executor
->query($this->nameserver, $query)
->then(function (Message $response) use ($query, $that) {
return $that->extractAddress($query, $response);
});
}
public function extractAddress(Query $query, Message $response)
{
$answers = $response->answers;
$addresses = $this->resolveAliases($answers, $query->name);
if (0 === count($addresses)) {
$message = 'DNS Request did not return valid answer.';
throw new RecordNotFoundException($message);
}
$address = $addresses[array_rand($addresses)];
return $address;
}
public function resolveAliases(array $answers, $name)
{
$named = $this->filterByName($answers, $name);
$aRecords = $this->filterByType($named, Message::TYPE_A);
$cnameRecords = $this->filterByType($named, Message::TYPE_CNAME);
if ($aRecords) {
return $this->mapRecordData($aRecords);
}
if ($cnameRecords) {
$aRecords = array();
$cnames = $this->mapRecordData($cnameRecords);
foreach ($cnames as $cname) {
$targets = $this->filterByName($answers, $cname);
$aRecords = array_merge(
$aRecords,
$this->resolveAliases($answers, $cname)
);
}
return $aRecords;
}
return array();
}
private function filterByName(array $answers, $name)
{
return $this->filterByField($answers, 'name', $name);
}
private function filterByType(array $answers, $type)
{
return $this->filterByField($answers, 'type', $type);
}
private function filterByField(array $answers, $field, $value)
{
$value = strtolower($value);
return array_filter($answers, function ($answer) use ($field, $value) {
return $value === strtolower($answer->$field);
});
}
private function mapRecordData(array $records)
{
return array_map(function ($record) {
return $record->data;
}, $records);
}
}
|