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 ( ca105e...9d9c7b )
by François
02:33
created

Pool::getHostName()   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
    /** @var array */
78
    private $aclGroupList;
79
80
    /** @var bool */
81
    private $forward6;
82
83
    /** @var bool */
84
    private $blockSmb;
85
86
    public function __construct($poolNumber, array $poolData)
87
    {
88
        $this->setId(self::validate($poolData, 'id'));
89
        $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...
90
        $this->setHostName(self::validate($poolData, 'hostName'));
91
        $this->setDefaultGateway(self::validate($poolData, 'defaultGateway', false, false));
92
        $this->setRange(new IP(self::validate($poolData, 'range')));
93
        $this->setRange6(new IP(self::validate($poolData, 'range6')));
94
        $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...
95
        $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...
96
        $this->setUseNat(self::validate($poolData, 'useNat', false, false));
97
        $this->setExtIf(self::validate($poolData, 'extIf'));
98
        $this->setTwoFactor(self::validate($poolData, 'twoFactor', false, false));
99
        $this->setClientToClient(self::validate($poolData, 'clientToClient', false, false));
100
        $this->setManagementIp(new IP(sprintf('127.42.%d.1', $poolNumber)));
101
        $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...
102
        $this->setEnableLog(self::validate($poolData, 'enableLog', false, false));
103
        $this->setEnableAcl(self::validate($poolData, 'enableAcl', false, false));
104
        $this->setAclGroupList(self::validate($poolData, 'aclGroupList', 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...
105
        $this->setBlockSmb(self::validate($poolData, 'blockSmb', false, false));
106
        $this->setForward6(self::validate($poolData, 'forward6', false, true));
107
        $this->populateInstances();
108
    }
109
110
    public function setId($id)
111
    {
112
        self::validateSimpleString($id);
113
        $this->id = $id;
114
    }
115
116
    public function getId()
117
    {
118
        return $this->id;
119
    }
120
121
    public function setName($poolName)
122
    {
123
        self::validateString($poolName);
124
        $this->poolName = $poolName;
125
    }
126
127
    public function getName()
128
    {
129
        return $this->poolName;
130
    }
131
132
    public function setHostName($hostName)
133
    {
134
        self::validateString($hostName);
135
        $this->hostName = $hostName;
136
    }
137
138
    public function getHostName()
139
    {
140
        return $this->hostName;
141
    }
142
143
    public function setDefaultGateway($defaultGateway)
144
    {
145
        $this->defaultGateway = (bool) $defaultGateway;
146
    }
147
148
    public function getDefaultGateway()
149
    {
150
        return $this->defaultGateway;
151
    }
152
153
    public function setRange(IP $range)
154
    {
155
        $this->range = $range;
156
    }
157
158
    public function getRange()
159
    {
160
        return $this->range;
161
    }
162
163
    public function setRange6(IP $range6)
164
    {
165
        $this->range6 = $range6;
166
    }
167
168
    public function getRange6()
169
    {
170
        return $this->range6;
171
    }
172
173
    public function setRoutes(array $routes)
174
    {
175
        $this->routes = [];
176
177
        foreach ($routes as $route) {
178
            $this->routes[] = new IP($route);
179
        }
180
    }
181
182
    public function getRoutes()
183
    {
184
        return $this->routes;
185
    }
186
187
    public function setDns(array $dns)
188
    {
189
        $this->dns = [];
190
191
        foreach ($dns as $server) {
192
            $this->dns[] = new IP($server);
193
        }
194
    }
195
196
    public function getDns()
197
    {
198
        return $this->dns;
199
    }
200
201
    public function setUseNat($useNat)
202
    {
203
        $this->useNat = (bool) $useNat;
204
    }
205
206
    public function getUseNat()
207
    {
208
        return $this->useNat;
209
    }
210
211
    public function setExtIf($extIf)
212
    {
213
        self::validateString($extIf);
214
        $this->extIf = $extIf;
215
    }
216
217
    public function getExtIf()
218
    {
219
        return $this->extIf;
220
    }
221
222
    public function setTwoFactor($twoFactor)
223
    {
224
        $this->twoFactor = (bool) $twoFactor;
225
    }
226
227
    public function getTwoFactor()
228
    {
229
        return $this->twoFactor;
230
    }
231
232
    public function setClientToClient($clientToClient)
233
    {
234
        $this->clientToClient = (bool) $clientToClient;
235
    }
236
237
    public function getClientToClient()
238
    {
239
        return $this->clientToClient;
240
    }
241
242
    public function setManagementIp(IP $managementIp)
243
    {
244
        $this->managementIp = $managementIp;
245
    }
246
247
    public function getManagementIp()
248
    {
249
        return $this->managementIp;
250
    }
251
252
    public function setListen(IP $listen)
253
    {
254
        $this->listen = $listen;
255
    }
256
257
    public function getListen()
258
    {
259
        return $this->listen;
260
    }
261
262
    public function getInstances()
263
    {
264
        return $this->instances;
265
    }
266
267
    public function setEnableLog($enableLog)
268
    {
269
        $this->enableLog = (bool) $enableLog;
270
    }
271
272
    public function getEnableLog()
273
    {
274
        return $this->enableLog;
275
    }
276
277
    public function setEnableAcl($enableAcl)
278
    {
279
        $this->enableAcl = (bool) $enableAcl;
280
    }
281
282
    public function getEnableAcl()
283
    {
284
        return $this->enableAcl;
285
    }
286
287
    public function setAclGroupList(array $aclGroupList)
288
    {
289
        foreach ($aclGroupList as $aclGroup) {
290
            self::validateString($aclGroup);
291
        }
292
293
        $this->aclGroupList = array_values($aclGroupList);
294
    }
295
296
    public function getAclGroupList()
297
    {
298
        return $this->aclGroupList;
299
    }
300
301
    public function setBlockSmb($blockSmb)
302
    {
303
        $this->blockSmb = (bool) $blockSmb;
304
    }
305
306
    public function getBlockSmb()
307
    {
308
        return $this->blockSmb;
309
    }
310
311
    public function setForward6($forward6)
312
    {
313
        $this->forward6 = (bool) $forward6;
314
    }
315
316
    public function getForward6()
317
    {
318
        return $this->forward6;
319
    }
320
321
    private function populateInstances()
322
    {
323
        $instanceCount = self::getNetCount($this->getRange()->getPrefix());
324
        $splitRange = $this->getRange()->split($instanceCount);
325
        $splitRange6 = $this->getRange6()->split($instanceCount);
326
327
        for ($i = 0; $i < $instanceCount; ++$i) {
328
            // protocol is udp unless it is the last instance when there is
329
            // not just one instance
330
            if (1 === $instanceCount || $i !== $instanceCount - 1) {
331
                $proto = 'udp';
332
                $port = 1194 + $i;
333
            } else {
334
                $proto = 'tcp';
335
                $port = 1194;
336
            }
337
338
            $this->instances[] = new Instance(
339
                [
340
                    'range' => $splitRange[$i],
341
                    'range6' => $splitRange6[$i],
342
                    'dev' => sprintf('tun-%s-%d', $this->getId(), $i),
343
                    'proto' => $proto,
344
                    'port' => $port,
345
                    'managementPort' => 11940 + $i,
346
                ]
347
            );
348
        }
349
    }
350
351
    /**
352
     * Depending on the prefix we will divide it in a number of nets to
353
     * balance the load over the instances, it is recommended to use a least
354
     * a /24.
355
     *
356
     * A /24 or 'bigger' will be split in 4 networks, everything 'smaller'
357
     * will be either be split in 2 networks or remain 1 network.
358
     */
359
    private static function getNetCount($prefix)
360
    {
361
        switch ($prefix) {
362
            case 32:    // 1 IP
363
            case 31:    // 2 IPs
364
                throw new RuntimeException('not enough available IPs in range');
365
            case 30:    // 4 IPs (1 usable for client, no splitting)
366
            case 29:    // 8 IPs (5 usable for clients, no splitting)
367
                return 1;
368
            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...
369
            case 27:    // 32 IPs
370
            case 26:    // 64 IPs
371
            case 25:    // 128 IPs
372
                return 2;
373
            case 24:
374
                return 4;
375
        }
376
377
        return 8;
378
    }
379
380
    public function toArray()
381
    {
382
        $routesList = [];
383
        foreach ($this->getRoutes() as $route) {
384
            $routesList[] = $route->getAddressPrefix();
385
        }
386
387
        $dnsList = [];
388
        foreach ($this->getDns() as $dns) {
389
            $dnsList[] = $dns->getAddress();
390
        }
391
392
        $instancesList = [];
393
        foreach ($this->getInstances() as $instance) {
394
            $instancesList[] = $instance->toArray();
395
        }
396
397
        return [
398
            'aclGroupList' => $this->getAclGroupList(),
399
            'clientToClient' => $this->getClientToClient(),
400
            'defaultGateway' => $this->getDefaultGateway(),
401
            'dns' => $dnsList,
402
            'enableAcl' => $this->getEnableAcl(),
403
            'enableLog' => $this->getEnableLog(),
404
            'extIf' => $this->getExtIf(),
405
            'hostName' => $this->getHostName(),
406
            'id' => $this->getId(),
407
            'instances' => $instancesList,
408
            'listen' => $this->getListen()->getAddress(),
409
            'managementIp' => $this->getManagementIp()->getAddress(),
410
            'name' => $this->getName(),
411
            'range' => $this->getRange()->getAddressPrefix(),
412
            'range6' => $this->getRange6()->getAddressPrefix(),
413
            'routes' => $routesList,
414
            'twoFactor' => $this->getTwoFactor(),
415
            'useNat' => $this->getUseNat(),
416
        ];
417
    }
418
419
    private static function validate(array $configData, $configName, $requiredField = true, $defaultValue = false)
420
    {
421
        if (!array_key_exists($configName, $configData)) {
422
            if ($requiredField) {
423
                throw new RuntimeException(sprintf('missing configuration field "%s"', $configName));
424
            }
425
426
            return $defaultValue;
427
        }
428
429
        return $configData[$configName];
430
    }
431
432
    private static function validateString($input)
433
    {
434
        if (!is_string($input)) {
435
            throw new InvalidArgumentException('parameter must be string');
436
        }
437
        if (0 >= strlen($input)) {
438
            throw new DomainException('parameter must be non-empty string');
439
        }
440
    }
441
442
    private static function validateSimpleString($input)
443
    {
444
        self::validateString($input);
445
        $matchPattern = '/^[a-zA-Z0-9]+$/';
446
        if (1 !== preg_match($matchPattern, $input)) {
447
            throw new DomainException(
448
                sprintf('parameter must match pattern "%s"', $matchPattern)
449
            );
450
        }
451
    }
452
}
453