Completed
Push — master ( 0cd2cd...e2ec22 )
by Sam
02:48
created

Encoder::encodeSOA()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 1
dl 0
loc 12
ccs 10
cts 10
cp 1
crap 1
rs 9.9332
c 0
b 0
f 0
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;
13
14
class Encoder
15
{
16
    /**
17
     * @param Message $message
18
     *
19
     * @return string
20
     *
21
     * @throws UnsupportedTypeException
22
     */
23 7
    public static function encodeMessage(Message $message): string
24
    {
25
        return
26 7
            self::encodeHeader($message->getHeader()).
27 7
            self::encodeResourceRecords($message->getQuestions()).
28 7
            self::encodeResourceRecords($message->getAnswers()).
29 7
            self::encodeResourceRecords($message->getAuthoritatives()).
30 7
            self::encodeResourceRecords($message->getAdditionals());
31
    }
32
33
    /**
34
     * Encode a domain name as a sequence of labels.
35
     *
36
     * @param $domain
37
     *
38
     * @return string
39
     */
40 12
    public static function encodeDomainName($domain): string
41
    {
42 12
        if ('.' === $domain) {
43 1
            return chr(0);
44
        }
45
46 12
        $domain = rtrim($domain, '.').'.';
47 12
        $res = '';
48
49 12
        foreach (explode('.', $domain) as $label) {
50 12
            $res .= chr(strlen($label)).$label;
51
        }
52
53 12
        return $res;
54
    }
55
56
    /**
57
     * @param ResourceRecord[] $resourceRecords
58
     *
59
     * @return string
60
     *
61
     * @throws UnsupportedTypeException
62
     */
63 9
    public static function encodeResourceRecords(array $resourceRecords): string
64
    {
65 9
        $records = array_map('self::encodeResourceRecord', $resourceRecords);
66
67 9
        return implode('', $records);
68
    }
69
70
    /**
71
     * @param ResourceRecord $rr
72
     *
73
     * @return string
74
     *
75
     * @throws UnsupportedTypeException
76
     */
77 8
    public static function encodeResourceRecord(ResourceRecord $rr): string
78
    {
79 8
        $encoded = self::encodeDomainName($rr->getName());
80 8
        if ($rr->isQuestion()) {
81 7
            return $encoded.pack('nn', $rr->getType(), $rr->getClass());
82
        }
83
84 7
        $data = RdataEncoder::encodeRdata($rr->getType(), $rr->getRdata());
85 6
        $encoded .= pack('nnNn', $rr->getType(), $rr->getClass(), $rr->getTtl(), strlen($data));
86
87 6
        return $encoded.$data;
88
    }
89
90
    /**
91
     * @param Header $header
92
     *
93
     * @return string
94
     */
95 8
    public static function encodeHeader(Header $header): string
96
    {
97 8
        return pack(
98 8
            'nnnnnn',
99 8
            $header->getId(),
100 8
            self::encodeFlags($header),
101 8
            $header->getQuestionCount(),
102 8
            $header->getAnswerCount(),
103 8
            $header->getNameServerCount(),
104 8
            $header->getAdditionalRecordsCount()
105
        );
106
    }
107
108
    /**
109
     * Encode the bit field of the Header between "ID" and "QDCOUNT".
110
     *
111
     * @param Header $header
112
     *
113
     * @return int
114
     */
115 8
    private static function encodeFlags(Header $header): int
116
    {
117
        return 0x0 |
118 8
            ($header->isResponse() & 0x1) << 15 |
119 8
            ($header->getOpcode() & 0xf) << 11 |
120 8
            ($header->isAuthoritative() & 0x1) << 10 |
121 8
            ($header->isTruncated() & 0x1) << 9 |
122 8
            ($header->isRecursionDesired() & 0x1) << 8 |
123 8
            ($header->isRecursionAvailable() & 0x1) << 7 |
124 8
            ($header->getZ() & 0x7) << 4 |
125 8
            ($header->getRcode() & 0xf);
126
    }
127
}
128