This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | namespace PHPDaemon\BoundSocket; |
||
3 | |||
4 | use PHPDaemon\Core\Daemon; |
||
5 | use PHPDaemon\Core\Debug; |
||
6 | use PHPDaemon\Core\Timer; |
||
7 | use PHPDaemon\Core\EventLoop; |
||
8 | |||
9 | /** |
||
10 | * UDP |
||
11 | * |
||
12 | * @package Core |
||
13 | * |
||
14 | * @author Vasily Zorin <[email protected]> |
||
15 | */ |
||
16 | class UDP extends Generic |
||
17 | { |
||
18 | /** |
||
19 | * Hostname |
||
20 | * @var string |
||
21 | */ |
||
22 | protected $host; |
||
23 | |||
24 | /** |
||
25 | * Port |
||
26 | * @var integer |
||
27 | */ |
||
28 | protected $port; |
||
29 | |||
30 | /** |
||
31 | * Listener mode? |
||
32 | * @var boolean |
||
33 | */ |
||
34 | protected $listenerMode = true; |
||
35 | |||
36 | /** |
||
37 | * Default port |
||
38 | * @var integer |
||
39 | */ |
||
40 | protected $defaultPort; |
||
41 | |||
42 | /** |
||
43 | * Reuse? |
||
44 | * @var boolean |
||
45 | */ |
||
46 | protected $reuse = true; |
||
47 | |||
48 | /** |
||
49 | * Ports map |
||
50 | * @var array [portNumber => Connection] |
||
51 | */ |
||
52 | protected $portsMap = []; |
||
53 | |||
54 | /** |
||
55 | * Sets default port |
||
56 | * @param integer $port Port |
||
57 | * @return void |
||
58 | */ |
||
59 | public function setDefaultPort($port) |
||
60 | { |
||
61 | $this->defaultPort = $port; |
||
62 | } |
||
63 | |||
64 | /** |
||
65 | * Send UDP packet |
||
66 | * @param string $data Data |
||
67 | * @param integer $flags Flags |
||
68 | * @param string $host Host |
||
69 | * @param integer $port Port |
||
70 | * @return integer |
||
71 | */ |
||
72 | public function sendTo($data, $flags, $host, $port) |
||
73 | { |
||
74 | return socket_sendto($this->fd, $data, mb_orig_strlen($data), $flags, $host, $port); |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Unassigns addr |
||
79 | * @param string $addr Address |
||
80 | * @return void |
||
81 | */ |
||
82 | public function unassignAddr($addr) |
||
83 | { |
||
84 | unset($this->portsMap[$addr]); |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * Sets reuse |
||
89 | * @param integer $reuse Port |
||
0 ignored issues
–
show
|
|||
90 | * @return void |
||
91 | */ |
||
92 | public function setReuse($reuse = true) |
||
93 | { |
||
94 | $this->reuse = $reuse; |
||
0 ignored issues
–
show
It seems like
$reuse can also be of type integer . However, the property $reuse is declared as type boolean . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
![]() |
|||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Bind given addreess |
||
99 | * @return boolean Success. |
||
100 | */ |
||
101 | public function bindSocket() |
||
102 | { |
||
103 | $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); |
||
104 | View Code Duplication | if (!$sock) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
105 | $errno = socket_last_error(); |
||
106 | Daemon::$process->log(get_class($this) . ': Couldn\'t create UDP-socket (' . $errno . ' - ' . socket_strerror($errno) . ').'); |
||
107 | return false; |
||
108 | } |
||
109 | if (!isset($this->port)) { |
||
110 | if (isset($this->defaultPort)) { |
||
111 | $this->port = $this->defaultPort; |
||
112 | View Code Duplication | } else { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
113 | Daemon::log(get_class($this) . ' (' . get_class($this->pool) . '): no port defined for \'' . $this->uri['uri'] . '\''); |
||
114 | } |
||
115 | } |
||
116 | View Code Duplication | if ($this->reuse) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
117 | if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) { |
||
118 | $errno = socket_last_error(); |
||
119 | Daemon::$process->log(get_class($this) . ': Couldn\'t set option REUSEADDR to socket (' . $errno . ' - ' . socket_strerror($errno) . ').'); |
||
120 | return false; |
||
121 | } |
||
122 | if (defined('SO_REUSEPORT') && !@socket_set_option($sock, SOL_SOCKET, SO_REUSEPORT, 1)) { |
||
123 | $errno = socket_last_error(); |
||
124 | Daemon::$process->log(get_class($this) . ': Couldn\'t set option REUSEPORT to socket (' . $errno . ' - ' . socket_strerror($errno) . ').'); |
||
125 | return false; |
||
126 | } |
||
127 | } |
||
128 | View Code Duplication | if (!@socket_bind($sock, $this->host, $this->port)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
129 | $errno = socket_last_error(); |
||
130 | $addr = $this->host . ':' . $this->port; |
||
131 | Daemon::$process->log(get_class($this) . ': Couldn\'t bind UDP-socket \'' . $addr . '\' (' . $errno . ' - ' . socket_strerror($errno) . ').'); |
||
132 | return false; |
||
133 | } |
||
134 | socket_getsockname($sock, $this->host, $this->port); |
||
135 | $addr = $this->host . ':' . $this->port; |
||
0 ignored issues
–
show
$addr is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
136 | socket_set_nonblock($sock); |
||
137 | $this->setFd($sock); |
||
138 | return true; |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Called when socket is bound |
||
143 | * @return boolean Success |
||
144 | */ |
||
145 | protected function onBound() |
||
146 | { |
||
147 | if (!$this->ev) { |
||
148 | Daemon::log(get_class($this) . '::' . __METHOD__ . ': Couldn\'t set event on bound socket: ' . Debug::dump($this->fd)); |
||
149 | return false; |
||
150 | } |
||
151 | return true; |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * Enable socket events |
||
156 | * @return void |
||
157 | */ |
||
158 | View Code Duplication | public function enable() |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
159 | { |
||
160 | if ($this->enabled) { |
||
161 | return; |
||
162 | } |
||
163 | if (!$this->fd) { |
||
164 | return; |
||
165 | } |
||
166 | $this->enabled = true; |
||
167 | |||
168 | if ($this->ev === null) { |
||
169 | if ($this->eventLoop === null) { |
||
170 | // @TODO нужно перенести куда-то выше, не годиться тут инициировать |
||
171 | $this->eventLoop = EventLoop::$instance; |
||
172 | } |
||
173 | |||
174 | $this->ev = $this->eventLoop->event($this->fd, \Event::READ | \Event::PERSIST, [$this, 'onReadUdp']); |
||
0 ignored issues
–
show
It seems like
$this->eventLoop->event(...ay($this, 'onReadUdp')) of type object<Event> is incompatible with the declared type object<EventListener\Event> of property $ev .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
175 | $this->onBound(); |
||
176 | } else { |
||
177 | $this->onAcceptEv(); |
||
0 ignored issues
–
show
|
|||
178 | } |
||
179 | $this->ev->add(); |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Called when we got UDP packet |
||
184 | * @param resource $stream Descriptor |
||
0 ignored issues
–
show
Should the type for parameter
$stream not be resource|null ?
This check looks for It makes a suggestion as to what type it considers more descriptive. Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
185 | * @param integer $events Events |
||
186 | * @param mixed $arg Attached variable |
||
187 | * @return boolean Success. |
||
188 | */ |
||
189 | public function onReadUdp($stream = null, $events = 0, $arg = null) |
||
0 ignored issues
–
show
|
|||
190 | { |
||
191 | if (Daemon::$process->reload) { |
||
192 | return false; |
||
193 | } |
||
194 | |||
195 | if ($this->pool->maxConcurrency) { |
||
196 | if ($this->pool->count() >= $this->pool->maxConcurrency) { |
||
197 | $this->overload = true; |
||
0 ignored issues
–
show
The property
overload does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
198 | return false; |
||
199 | } |
||
200 | } |
||
201 | |||
202 | $host = null; |
||
203 | do { |
||
204 | $l = @socket_recvfrom($this->fd, $buf, 10240, MSG_DONTWAIT, $host, $port); |
||
205 | if (!$l) { |
||
206 | break; |
||
207 | } |
||
208 | $key = '[' . $host . ']:' . $port; |
||
209 | if (!isset($this->portsMap[$key])) { |
||
210 | if ($this->pool->allowedClients !== null) { |
||
211 | if (!self::netMatch($this->pool->allowedClients, $host)) { |
||
0 ignored issues
–
show
The property
allowedClients does not seem to exist in PHPDaemon\Network\Pool .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
212 | Daemon::log('Connection is not allowed (' . $host . ')'); |
||
213 | } |
||
214 | continue; |
||
215 | } |
||
216 | $class = $this->pool->connectionClass; |
||
217 | $conn = new $class(null, $this->pool); |
||
218 | $conn->setDgram(true); |
||
219 | $conn->onWriteEv(null); |
||
220 | $conn->setPeername($host, $port); |
||
221 | $conn->setParentSocket($this); |
||
222 | $this->portsMap[$key] = $conn; |
||
223 | $conn->timeoutRef = setTimeout(function ($timer) use ($conn) { |
||
224 | $conn->finish(); |
||
225 | $timer->finish(); |
||
226 | }, $conn->timeout * 1e6); |
||
227 | $conn->onUdpPacket($buf); |
||
228 | } else { |
||
229 | $conn = $this->portsMap[$key]; |
||
230 | $conn->onUdpPacket($buf); |
||
231 | Timer::setTimeout($conn->timeoutRef); |
||
232 | } |
||
233 | } while (true); |
||
234 | return $host !== null; |
||
235 | } |
||
236 | } |
||
237 |
This check looks for
@param
annotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive.
Most often this is a case of a parameter that can be null in addition to its declared types.