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 ( ac0a5a...f325ed )
by François
03:12
created

Pool::getId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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