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 ( a726e2...7d41ca )
by François
02:27
created

Pool::getRoutes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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