GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 5e22a5...75d35a )
by François
03:03
created

Pool::getRange6()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
/**
3
 * Copyright 2016 François Kooman <[email protected]>.
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
namespace fkooman\VPN\Server;
19
20
use RuntimeException;
21
use InvalidArgumentException;
22
use DomainException;
23
24
class Pool
25
{
26
    /** @var string */
27
    private $id;
28
29
    /** @var string */
30
    private $poolName;
31
32
    /** @var string */
33
    private $hostName;
34
35
    /** @var bool */
36
    private $defaultGateway;
37
38
    /** @var IP */
39
    private $range;
40
41
    /** @var IP */
42
    private $range6;
43
44
    /** @var array */
45
    private $routes;
46
47
    /** @var array */
48
    private $dns;
49
50
    /** @var bool */
51
    private $useNat;
52
53
    /** @var string */
54
    private $extIf;
55
56
    /** @var bool */
57
    private $twoFactor;
58
59
    /** @var bool */
60
    private $clientToClient;
61
62
    /** @var IP */
63
    private $managementIp;
64
65
    /** @var IP */
66
    private $listen;
67
68
    /** @var array */
69
    private $instances;
70
71
    /** @var bool */
72
    private $enableLog;
73
74
    /** @var bool */
75
    private $enableAcl;
76
77
    public function __construct($poolNumber, array $poolData)
78
    {
79
        $this->setId(self::validate($poolData, 'id'));
80
        $this->setName(self::validate($poolData, 'name', false, $this->getId()));
0 ignored issues
show
Documentation introduced by
$this->getId() is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
81
        $this->setHostName(self::validate($poolData, 'hostName'));
82
        $this->setDefaultGateway(self::validate($poolData, 'defaultGateway', false, false));
83
        $this->setRange(new IP(self::validate($poolData, 'range')));
84
        $this->setRange6(new IP(self::validate($poolData, 'range6')));
85
        $this->setRoutes(self::validate($poolData, 'routes', false, []));
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
86
        $this->setDns(self::validate($poolData, 'dns', false, []));
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
87
        $this->setUseNat(self::validate($poolData, 'useNat', false, false));
88
        $this->setExtIf(self::validate($poolData, 'extIf'));
89
        $this->setTwoFactor(self::validate($poolData, 'twoFactor', false, false));
90
        $this->setClientToClient(self::validate($poolData, 'clientToClient', false, false));
91
        $this->setManagementIp(new IP(sprintf('127.42.%d.1', $poolNumber)));
92
        $this->setListen(new IP(self::validate($poolData, 'listen', false, '::')));
0 ignored issues
show
Documentation introduced by
'::' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
93
        $this->setEnableLog(self::validate($poolData, 'enableLog', false, false));
94
        $this->setEnableAcl(self::validate($poolData, 'enableAcl', false, false));
95
        $this->populateInstances();
96
    }
97
98
    public function setId($id)
99
    {
100
        self::validateSimpleString($id);
101
        $this->id = $id;
102
    }
103
104
    public function getId()
105
    {
106
        return $this->id;
107
    }
108
109
    public function setName($poolName)
110
    {
111
        self::validateString($poolName);
112
        $this->poolName = $poolName;
113
    }
114
115
    public function getName()
116
    {
117
        return $this->poolName;
118
    }
119
120
    public function setHostName($hostName)
121
    {
122
        self::validateString($hostName);
123
        $this->hostName = $hostName;
124
    }
125
126
    public function getHostName()
127
    {
128
        return $this->hostName;
129
    }
130
131
    public function setDefaultGateway($defaultGateway)
132
    {
133
        $this->defaultGateway = (bool) $defaultGateway;
134
    }
135
136
    public function getDefaultGateway()
137
    {
138
        return $this->defaultGateway;
139
    }
140
141
    public function setRange(IP $range)
142
    {
143
        $this->range = $range;
144
    }
145
146
    public function getRange()
147
    {
148
        return $this->range;
149
    }
150
151
    public function setRange6(IP $range6)
152
    {
153
        $this->range6 = $range6;
154
    }
155
156
    public function getRange6()
157
    {
158
        return $this->range6;
159
    }
160
161
    public function setRoutes(array $routes)
162
    {
163
        $this->routes = [];
164
165
        foreach ($routes as $route) {
166
            $this->routes[] = new IP($route);
167
        }
168
    }
169
170
    public function getRoutes()
171
    {
172
        return $this->routes;
173
    }
174
175
    public function setDns(array $dns)
176
    {
177
        $this->dns = [];
178
179
        foreach ($dns as $server) {
180
            $this->dns[] = new IP($server);
181
        }
182
    }
183
184
    public function getDns()
185
    {
186
        return $this->dns;
187
    }
188
189
    public function setUseNat($useNat)
190
    {
191
        $this->useNat = (bool) $useNat;
192
    }
193
194
    public function getUseNat()
195
    {
196
        return $this->useNat;
197
    }
198
199
    public function setExtIf($extIf)
200
    {
201
        self::validateString($extIf);
202
        $this->extIf = $extIf;
203
    }
204
205
    public function getExtIf()
206
    {
207
        return $this->extIf;
208
    }
209
210
    public function setTwoFactor($twoFactor)
211
    {
212
        $this->twoFactor = (bool) $twoFactor;
213
    }
214
215
    public function getTwoFactor()
216
    {
217
        return $this->twoFactor;
218
    }
219
220
    public function setClientToClient($clientToClient)
221
    {
222
        $this->clientToClient = (bool) $clientToClient;
223
    }
224
225
    public function getClientToClient()
226
    {
227
        return $this->clientToClient;
228
    }
229
230
    public function setManagementIp(IP $managementIp)
231
    {
232
        $this->managementIp = $managementIp;
233
    }
234
235
    public function getManagementIp()
236
    {
237
        return $this->managementIp;
238
    }
239
240
    public function setListen(IP $listen)
241
    {
242
        $this->listen = $listen;
243
    }
244
245
    public function getListen()
246
    {
247
        return $this->listen;
248
    }
249
250
    public function getInstances()
251
    {
252
        return $this->instances;
253
    }
254
255
    public function setEnableLog($enableLog)
256
    {
257
        $this->enableLog = (bool) $enableLog;
258
    }
259
260
    public function getEnableLog()
261
    {
262
        return $this->enableLog;
263
    }
264
265
    public function setEnableAcl($enableAcl)
266
    {
267
        $this->enableAcl = (bool) $enableAcl;
268
    }
269
270
    public function getEnableAcl()
271
    {
272
        return $this->enableAcl;
273
    }
274
275
    private function populateInstances()
276
    {
277
        $instanceCount = self::getNetCount($this->getRange()->getPrefix());
278
        $splitRange = $this->getRange()->split($instanceCount);
279
        $splitRange6 = $this->getRange6()->split($instanceCount);
280
281
        for ($i = 0; $i < $instanceCount; ++$i) {
282
            // protocol is udp unless it is the last instance when there is
283
            // not just one instance
284
            if (1 === $instanceCount || $i !== $instanceCount - 1) {
285
                $proto = 'udp';
286
                $port = 1194 + $i;
287
            } else {
288
                $proto = 'tcp';
289
                $port = 1194;
290
            }
291
292
            $this->instances[] = new Instance(
293
                [
294
                    'range' => $splitRange[$i],
295
                    'range6' => $splitRange6[$i],
296
                    'dev' => sprintf('tun-%s-%d', $this->getId(), $i),
297
                    'proto' => $proto,
298
                    'port' => $port,
299
                    'managementPort' => 11940 + $i,
300
                ]
301
            );
302
        }
303
    }
304
305
    /**
306
     * Depending on the prefix we will divide it in a number of nets to
307
     * balance the load over the instances, it is recommended to use a least
308
     * a /24.
309
     *
310
     * A /24 or 'bigger' will be split in 4 networks, everything 'smaller'
311
     * will be either be split in 2 networks or remain 1 network.
312
     */
313
    private static function getNetCount($prefix)
314
    {
315
        switch ($prefix) {
316
            case 32:    // 1 IP
317
            case 31:    // 2 IPs
318
                throw new RuntimeException('not enough available IPs in range');
319
            case 30:    // 4 IPs (1 usable for client, no splitting)
320
            case 29:    // 8 IPs (5 usable for clients, no splitting)
321
                return 1;
322
            case 28:    // 16 IPs (12 usable for clients)
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
323
            case 27:    // 32 IPs
324
            case 26:    // 64 IPs
325
            case 25:    // 128 IPs
326
                return 2;
327
            case 24:
328
                return 4;
329
        }
330
331
        return 8;
332
    }
333
334
    public function toArray()
335
    {
336
        $routesList = [];
337
        foreach ($this->getRoutes() as $route) {
338
            $routesList[] = $route->getAddressPrefix();
339
        }
340
341
        $dnsList = [];
342
        foreach ($this->getDns() as $dns) {
343
            $dnsList[] = $dns->getAddress();
344
        }
345
346
        $instancesList = [];
347
        foreach ($this->getInstances() as $instance) {
348
            $instancesList[] = $instance->toArray();
349
        }
350
351
        return [
352
            'clientToClient' => $this->getClientToClient(),
353
            'defaultGateway' => $this->getDefaultGateway(),
354
            'dns' => $dnsList,
355
            'enableAcl' => $this->getEnableAcl(),
356
            'enableLog' => $this->getEnableLog(),
357
            'extIf' => $this->getExtIf(),
358
            'hostName' => $this->getHostName(),
359
            'id' => $this->getId(),
360
            'instances' => $instancesList,
361
            'listen' => $this->getListen()->getAddress(),
362
            'managementIp' => $this->getManagementIp()->getAddress(),
363
            'name' => $this->getName(),
364
            'range' => $this->getRange()->getAddressPrefix(),
365
            'range6' => $this->getRange6()->getAddressPrefix(),
366
            'routes' => $routesList,
367
            'twoFactor' => $this->getTwoFactor(),
368
            'useNat' => $this->getUseNat(),
369
        ];
370
    }
371
372
    private static function validate(array $configData, $configName, $requiredField = true, $defaultValue = false)
373
    {
374
        if (!array_key_exists($configName, $configData)) {
375
            if ($requiredField) {
376
                throw new RuntimeException(sprintf('missing configuration field "%s"', $configName));
377
            }
378
379
            return $defaultValue;
380
        }
381
382
        return $configData[$configName];
383
    }
384
385
    private static function validateString($input)
386
    {
387
        if (!is_string($input)) {
388
            throw new InvalidArgumentException('parameter must be string');
389
        }
390
        if (0 >= strlen($input)) {
391
            throw new DomainException('parameter must be non-empty string');
392
        }
393
    }
394
395
    private static function validateSimpleString($input)
396
    {
397
        self::validateString($input);
398
        $matchPattern = '/^[a-zA-Z0-9]+$/';
399
        if (1 !== preg_match($matchPattern, $input)) {
400
            throw new DomainException(
401
                sprintf('parameter must match pattern "%s"', $matchPattern)
402
            );
403
        }
404
    }
405
}
406