Completed
Push — master ( ecf71f...65af6f )
by Sam
09:47
created

SystemResolver::IANA2PHP()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.1406

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 14
ccs 6
cts 8
cp 0.75
crap 3.1406
rs 10
1
<?php
2
3
/*
4
 * This file is part of PHP DNS Server.
5
 *
6
 * (c) Yif Swery <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace yswery\DNS\Resolver;
13
14
use yswery\DNS\UnsupportedTypeException;
15
use yswery\DNS\ResourceRecord;
16
use yswery\DNS\RecordTypeEnum;
17
18
/**
19
 * Use the host system's configured DNS.
20
 */
21
class SystemResolver extends AbstractResolver
22
{
23
    /**
24
     * SystemResolver constructor.
25
     *
26
     * @param bool $recursionAvailable
27
     * @param bool $authoritative
28
     */
29 2
    public function __construct($recursionAvailable = true, $authoritative = false)
30
    {
31 2
        $this->allowRecursion = (bool) $recursionAvailable;
32 2
        $this->isAuthoritative = (bool) $authoritative;
33 2
    }
34
35
    /**
36
     * @param ResourceRecord[] $queries
37
     *
38
     * @return ResourceRecord[]
39
     *
40
     * @throws UnsupportedTypeException
41
     */
42 2
    public function getAnswer(array $queries, ?string $client = null): array
43
    {
44 2
        $answer = [];
45 2
        foreach ($queries as $query) {
46 1
            $answer = array_merge($answer, $this->getRecordsRecursively($query));
47
        }
48
49 2
        return $answer;
50
    }
51
52
    /**
53
     * Resolve the $query using the system configured local DNS.
54
     *
55
     * @param ResourceRecord $query
56
     *
57
     * @return ResourceRecord[]
58
     *
59
     * @throws UnsupportedTypeException
60
     */
61 1
    private function getRecordsRecursively(ResourceRecord $query): array
62
    {
63 1
        $records = dns_get_record($query->getName(), $this->IANA2PHP($query->getType()));
64 1
        $result = [];
65
66 1
        foreach ($records as $record) {
67 1
            $result[] = (new ResourceRecord())
68 1
                ->setName($query->getName())
69 1
                ->setClass($query->getClass())
70 1
                ->setTtl($record['ttl'])
71 1
                ->setRdata($this->extractPhpRdata($record))
72 1
                ->setType($query->getType());
73
        }
74
75 1
        return $result;
76
    }
77
78
    /**
79
     * @param array $resourceRecord
80
     *
81
     * @return array|string
82
     *
83
     * @throws UnsupportedTypeException
84
     */
85 1
    protected function extractPhpRdata(array $resourceRecord)
86
    {
87 1
        $type = RecordTypeEnum::getTypeFromName($resourceRecord['type']);
88
89
        switch ($type) {
90 1
            case RecordTypeEnum::TYPE_A:
91 1
                return $resourceRecord['ip'];
92 1
            case RecordTypeEnum::TYPE_AAAA:
93 1
                return $resourceRecord['ipv6'];
94
            case RecordTypeEnum::TYPE_NS:
95
            case RecordTypeEnum::TYPE_CNAME:
96
            case RecordTypeEnum::TYPE_PTR:
97
                return $resourceRecord['target'];
98
            case RecordTypeEnum::TYPE_SOA:
99
                return [
100
                        'mname' => $resourceRecord['mname'],
101
                        'rname' => $resourceRecord['rname'],
102
                        'serial' => $resourceRecord['serial'],
103
                        'refresh' => $resourceRecord['refresh'],
104
                        'retry' => $resourceRecord['retry'],
105
                        'expire' => $resourceRecord['expire'],
106
                        'minimum' => $resourceRecord['minimum-ttl'],
107
                    ];
108
            case RecordTypeEnum::TYPE_MX:
109
                return [
110
                    'preference' => $resourceRecord['pri'],
111
                    'exchange' => $resourceRecord['host'],
112
                ];
113
            case RecordTypeEnum::TYPE_TXT:
114
                return $resourceRecord['txt'];
115
            case RecordTypeEnum::TYPE_SRV:
116
                return [
117
                    'priority' => $resourceRecord['pri'],
118
                    'port' => $resourceRecord['port'],
119
                    'weight' => $resourceRecord['weight'],
120
                    'target' => $resourceRecord['target'],
121
                ];
122
            default:
123
                throw new UnsupportedTypeException(
124
                    sprintf('Record type "%s" is not a supported type.', RecordTypeEnum::getName($type))
125
                );
126
        }
127
    }
128
129
    /**
130
     * Maps an IANA Rdata type to the built-in PHP DNS constant.
131
     *
132
     * @example $this->IANA_to_PHP(5) //Returns DNS_CNAME int(16)
133
     *
134
     * @param int $type the IANA RTYPE
135
     *
136
     * @return int the built-in PHP DNS_<type> constant or `false` if the type is not defined
137
     *
138
     * @throws UnsupportedTypeException|\InvalidArgumentException
139
     */
140 1
    private function IANA2PHP(int $type): int
141
    {
142 1
        $constantName = 'DNS_'.RecordTypeEnum::getName($type);
143 1
        if (!defined($constantName)) {
144
            throw new UnsupportedTypeException(sprintf('Record type "%d" is not a supported type.', $type));
145
        }
146
147 1
        $phpType = constant($constantName);
148
149 1
        if (!is_int($phpType)) {
150
            throw new \InvalidArgumentException(sprintf('Constant "%s" is not an integer.', $constantName));
151
        }
152
153 1
        return $phpType;
154
    }
155
}
156