Passed
Push — master ( 1b54b9...ff455f )
by Sam
10:10 queued 11s
created

HIP::fromText()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.072

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 1
dl 0
loc 15
ccs 8
cts 10
cp 0.8
crap 3.072
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of Badcow DNS Library.
7
 *
8
 * (c) Samuel Williams <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Badcow\DNS\Rdata;
15
16
use Badcow\DNS\Message;
17
use Badcow\DNS\Parser\ParseException;
18
use Badcow\DNS\Parser\Tokens;
19
use Badcow\DNS\Validator;
20
21
/**
22
 * {@link https://tools.ietf.org/html/rfc8005}.
23
 */
24
class HIP implements RdataInterface
25
{
26
    use RdataTrait;
27
28
    const TYPE = 'HIP';
29
    const TYPE_CODE = 55;
30
31
    /**
32
     * @var int
33
     */
34
    private $publicKeyAlgorithm;
35
36
    /**
37
     * @var string
38
     */
39
    private $hostIdentityTag;
40
41
    /**
42
     * @var string
43
     */
44
    private $publicKey;
45
46
    /**
47
     * @var string[]
48
     */
49
    private $rendezvousServers = [];
50
51
    /**
52
     * @return int
53
     */
54 1
    public function getPublicKeyAlgorithm(): int
55
    {
56 1
        return $this->publicKeyAlgorithm;
57
    }
58
59
    /**
60
     * @param int $publicKeyAlgorithm
61
     */
62 4
    public function setPublicKeyAlgorithm(int $publicKeyAlgorithm): void
63
    {
64 4
        $this->publicKeyAlgorithm = $publicKeyAlgorithm;
65 4
    }
66
67
    /**
68
     * @return string
69
     */
70 1
    public function getHostIdentityTag(): string
71
    {
72 1
        return $this->hostIdentityTag;
73
    }
74
75
    /**
76
     * @param string $hostIdentityTag
77
     */
78 4
    public function setHostIdentityTag(string $hostIdentityTag): void
79
    {
80 4
        $this->hostIdentityTag = $hostIdentityTag;
81 4
    }
82
83
    /**
84
     * @return string
85
     */
86 1
    public function getPublicKey(): string
87
    {
88 1
        return $this->publicKey;
89
    }
90
91
    /**
92
     * @param string $publicKey
93
     */
94 4
    public function setPublicKey(string $publicKey): void
95
    {
96 4
        $this->publicKey = $publicKey;
97 4
    }
98
99
    /**
100
     * @param string $server
101
     */
102 4
    public function addRendezvousServer(string $server): void
103
    {
104 4
        if (!Validator::fullyQualifiedDomainName($server)) {
105
            throw new \InvalidArgumentException('Rendezvous Server must be a fully-qualified domain name.');
106
        }
107
108 4
        $this->rendezvousServers[] = $server;
109 4
    }
110
111
    /**
112
     * @return string[]
113
     */
114 1
    public function getRendezvousServers(): array
115
    {
116 1
        return $this->rendezvousServers;
117
    }
118
119
    /**
120
     * Clear all rendezvous servers from the record.
121
     */
122
    public function clearRendezvousServer(): void
123
    {
124
        $this->rendezvousServers = [];
125
    }
126
127
    /**
128
     * {@inheritdoc}
129
     */
130 1
    public function toText(): string
131
    {
132 1
        return sprintf('%d %s %s %s',
133 1
            $this->publicKeyAlgorithm,
134 1
            bin2hex($this->hostIdentityTag),
135 1
            base64_encode($this->publicKey),
136 1
            implode(Tokens::SPACE, $this->rendezvousServers)
137
        );
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143 1
    public function toWire(): string
144
    {
145 1
        $rdata = pack('CCn',
146 1
            strlen($this->hostIdentityTag),
147 1
            $this->publicKeyAlgorithm,
148 1
            strlen($this->publicKey)
149
        );
150
151 1
        $rdata .= $this->hostIdentityTag;
152 1
        $rdata .= $this->publicKey;
153 1
        foreach ($this->rendezvousServers as $server) {
154 1
            $rdata .= Message::encodeName($server);
155
        }
156
157 1
        return $rdata;
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     *
163
     * @throws ParseException
164
     */
165 1
    public function fromText(string $text): void
166
    {
167 1
        $rdata = explode(Tokens::SPACE, $text);
168 1
        $this->setPublicKeyAlgorithm((int) array_shift($rdata));
169
170 1
        if (false === $hostIdentityTag = @hex2bin((string) array_shift($rdata))) {
171
            throw new ParseException(sprintf('Unable to parse host identity tag of rdata string "%s".', $text));
172
        }
173 1
        $this->setHostIdentityTag($hostIdentityTag);
174
175 1
        if (false === $publicKey = base64_decode((string) array_shift($rdata), true)) {
176
            throw new ParseException(sprintf('Unable to parse public key of rdata string "%s".', $text));
177
        }
178 1
        $this->setPublicKey($publicKey);
179 1
        array_map([$this, 'addRendezvousServer'], $rdata);
180 1
    }
181
182
    /**
183
     * {@inheritdoc}
184
     */
185 1
    public function fromWire(string $rdata, int &$offset = 0, ?int $rdLength = null): void
186
    {
187 1
        $end = $offset + ($rdLength ?? strlen($rdata));
188 1
        $integers = unpack('C<hitLen>/C<algorithm>/n<pkLen>', $rdata, $offset);
189 1
        $offset += 4;
190 1
        $hitLen = (int) $integers['<hitLen>'];
191 1
        $pkLen = (int) $integers['<pkLen>'];
192
193 1
        $this->setPublicKeyAlgorithm((int) $integers['<algorithm>']);
194
195 1
        $this->setHostIdentityTag(substr($rdata, $offset, $hitLen));
196 1
        $offset += $hitLen;
197
198 1
        $this->setPublicKey(substr($rdata, $offset, $pkLen));
199 1
        $offset += $pkLen;
200
201 1
        while ($offset < $end) {
202 1
            $this->addRendezvousServer(Message::decodeName($rdata, $offset));
203
        }
204 1
    }
205
}
206