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\Clients\Asterisk; |
||
3 | |||
4 | use PHPDaemon\Core\CallbackWrapper; |
||
5 | use PHPDaemon\Core\Daemon; |
||
6 | use PHPDaemon\Network\ClientConnection; |
||
7 | use PHPDaemon\Structures\StackCallbacks; |
||
8 | |||
9 | /** |
||
10 | * Asterisk Call Manager Connection |
||
11 | */ |
||
12 | class Connection extends ClientConnection |
||
13 | { |
||
14 | /** |
||
15 | * @TODO DESCR |
||
16 | */ |
||
17 | const CONN_STATE_START = 0; |
||
18 | |||
19 | /** |
||
20 | * @TODO DESCR |
||
21 | */ |
||
22 | const CONN_STATE_GOT_INITIAL_PACKET = 0.1; |
||
23 | |||
24 | /** |
||
25 | * @TODO DESCR |
||
26 | */ |
||
27 | const CONN_STATE_AUTH = 1; |
||
28 | |||
29 | /** |
||
30 | * @TODO DESCR |
||
31 | */ |
||
32 | const CONN_STATE_LOGIN_PACKET_SENT = 1.1; |
||
33 | |||
34 | /** |
||
35 | * @TODO DESCR |
||
36 | */ |
||
37 | const CONN_STATE_CHALLENGE_PACKET_SENT = 1.2; |
||
38 | |||
39 | /** |
||
40 | * @TODO DESCR |
||
41 | */ |
||
42 | const CONN_STATE_LOGIN_PACKET_SENT_AFTER_CHALLENGE = 1.3; |
||
43 | |||
44 | /** |
||
45 | * @TODO DESCR |
||
46 | */ |
||
47 | const CONN_STATE_HANDSHAKED_OK = 2.1; |
||
48 | |||
49 | /** |
||
50 | * @TODO DESCR |
||
51 | */ |
||
52 | const CONN_STATE_HANDSHAKED_ERROR = 2.2; |
||
53 | |||
54 | /** |
||
55 | * @TODO DESCR |
||
56 | */ |
||
57 | const INPUT_STATE_START = 0; |
||
58 | |||
59 | /** |
||
60 | * @TODO DESCR |
||
61 | */ |
||
62 | const INPUT_STATE_END_OF_PACKET = 1; |
||
63 | |||
64 | /** |
||
65 | * @TODO DESCR |
||
66 | */ |
||
67 | const INPUT_STATE_PROCESSING = 2; |
||
68 | |||
69 | /** |
||
70 | * @var string EOL |
||
71 | */ |
||
72 | public $EOL = "\r\n"; |
||
73 | |||
74 | /** |
||
75 | * @var string The username to access the interface |
||
76 | */ |
||
77 | public $username; |
||
78 | |||
79 | /** |
||
80 | * @var string The password defined in manager interface of server |
||
81 | */ |
||
82 | public $secret; |
||
83 | |||
84 | /** |
||
85 | * @var float Connection's state |
||
86 | */ |
||
87 | public $state = self::CONN_STATE_START; |
||
88 | |||
89 | /** |
||
90 | * @var integer Input state |
||
91 | */ |
||
92 | public $instate = self::INPUT_STATE_START; |
||
93 | |||
94 | /** |
||
95 | * @var array Received packets |
||
96 | */ |
||
97 | public $packets = []; |
||
98 | |||
99 | /** |
||
100 | * @var integer For composite response on action |
||
101 | */ |
||
102 | public $cnt = 0; |
||
103 | |||
104 | /** |
||
105 | * @var array Stack of callbacks called when response received |
||
106 | */ |
||
107 | public $callbacks = []; |
||
108 | |||
109 | /** |
||
110 | * Assertions for callbacks. |
||
111 | * Assertion: if more events may follow as response this is a main part or full |
||
112 | * an action complete event indicating that all data has been sent |
||
113 | * @var array |
||
114 | */ |
||
115 | public $assertions = []; |
||
116 | |||
117 | /** |
||
118 | * @var callable Callback. Called when received response on challenge action |
||
119 | */ |
||
120 | public $onChallenge; |
||
121 | |||
122 | /** |
||
123 | * Execute the given callback when/if the connection is handshaked |
||
124 | * @param callable Callback |
||
125 | * @return void |
||
126 | */ |
||
127 | View Code Duplication | public function onConnected($cb) |
|
0 ignored issues
–
show
|
|||
128 | { |
||
129 | if ($this->state === self::CONN_STATE_HANDSHAKED_ERROR) { |
||
130 | $cb($this); |
||
131 | } elseif ($this->state === self::CONN_STATE_HANDSHAKED_OK) { |
||
132 | $cb($this); |
||
133 | } else { |
||
134 | if (!$this->onConnected) { |
||
135 | $this->onConnected = new StackCallbacks(); |
||
136 | } |
||
137 | |||
138 | $this->onConnected->push($cb); |
||
139 | } |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Called when the connection is handshaked (at low-level), and peer is ready to recv. data |
||
144 | * @return void |
||
145 | */ |
||
146 | public function onReady() |
||
147 | { |
||
148 | if ($this->url === null) { |
||
149 | return; |
||
150 | } |
||
151 | |||
152 | if ($this->connected && !$this->busy) { |
||
153 | $this->pool->servConnFree[$this->url]->attach($this); |
||
154 | } |
||
155 | |||
156 | $url = parse_url($this->url); |
||
157 | |||
158 | $this->username = $url['user']; |
||
159 | $this->secret = $url['pass']; |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Called when the worker is going to shutdown |
||
164 | * @return boolean Ready to shutdown? |
||
165 | */ |
||
166 | public function gracefulShutdown() |
||
167 | { |
||
168 | if ($this->finished) { |
||
169 | return !$this->writing; |
||
170 | } |
||
171 | |||
172 | $this->logoff(); |
||
173 | |||
174 | $this->finish(); |
||
175 | |||
176 | return false; |
||
177 | } |
||
178 | |||
179 | /** |
||
180 | * Called when session finishes |
||
181 | * @return void |
||
182 | */ |
||
183 | public function onFinish() |
||
184 | { |
||
185 | $this->state = self::CONN_STATE_START; |
||
0 ignored issues
–
show
The property
$state was declared of type double , but self::CONN_STATE_START is of type integer . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||
186 | |||
187 | parent::onFinish(); |
||
188 | |||
189 | $this->event('disconnect'); |
||
190 | } |
||
191 | |||
192 | /** |
||
193 | * Called when new data received |
||
194 | * @return void |
||
195 | */ |
||
196 | public function onRead() |
||
197 | { |
||
198 | if ($this->state === self::CONN_STATE_START) { |
||
199 | if (($ver = $this->readline()) === null) { |
||
200 | return; |
||
201 | } |
||
202 | $this->pool->setAmiVersion($this->addr, $ver); |
||
203 | $this->state = self::CONN_STATE_GOT_INITIAL_PACKET; |
||
204 | $this->auth(); |
||
205 | } |
||
206 | |||
207 | while (($line = $this->readline()) !== null) { |
||
208 | //Daemon::log('>>> '.$line); |
||
209 | if ($line === '') { |
||
210 | $this->instate = self::INPUT_STATE_END_OF_PACKET; |
||
211 | $packet =& $this->packets[$this->cnt]; |
||
212 | ++$this->cnt; |
||
213 | } else { |
||
214 | $this->instate = self::INPUT_STATE_PROCESSING; |
||
215 | list($header, $value) = Pool::extract($line); |
||
216 | $this->packets[$this->cnt][$header] = $value; |
||
217 | } |
||
218 | |||
219 | if ((int)$this->state === self::CONN_STATE_AUTH) { |
||
220 | if ($this->instate === self::INPUT_STATE_END_OF_PACKET) { |
||
221 | if ($packet['response'] === 'success') { |
||
222 | if ($this->state === self::CONN_STATE_CHALLENGE_PACKET_SENT) { |
||
223 | if (is_callable($this->onChallenge)) { |
||
224 | $func = $this->onChallenge; |
||
225 | $func($this, $packet['challenge']); |
||
0 ignored issues
–
show
The variable
$packet does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
226 | } |
||
227 | 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. ![]() |
|||
228 | if ($packet['message'] === 'authentication accepted') { |
||
229 | $this->state = self::CONN_STATE_HANDSHAKED_OK; |
||
230 | |||
231 | Daemon::$process->log( |
||
232 | __METHOD__ . ': Authentication ok. Connected to ' . |
||
233 | parse_url($this->addr, PHP_URL_HOST) |
||
234 | ); |
||
235 | |||
236 | if ($this->onConnected) { |
||
237 | $this->connected = true; |
||
238 | $this->onConnected->executeAll($this); |
||
239 | $this->onConnected = null; |
||
240 | } |
||
241 | |||
242 | $this->event('connected'); |
||
243 | } |
||
244 | } |
||
245 | 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. ![]() |
|||
246 | $this->state = self::CONN_STATE_HANDSHAKED_ERROR; |
||
247 | |||
248 | Daemon::$process->log( |
||
249 | __METHOD__ . ': Authentication failed. Connection to ' . |
||
250 | parse_url($this->addr, PHP_URL_HOST) . ' failed.' |
||
251 | ); |
||
252 | |||
253 | if ($this->onConnected) { |
||
254 | $this->connected = false; |
||
255 | $this->onConnected->executeAll($this); |
||
256 | $this->onConnected = null; |
||
257 | } |
||
258 | |||
259 | $this->finish(); |
||
260 | } |
||
261 | |||
262 | $this->packets = []; |
||
263 | } |
||
264 | } elseif ($this->state === self::CONN_STATE_HANDSHAKED_OK) { |
||
265 | if ($this->instate === self::INPUT_STATE_END_OF_PACKET) { |
||
266 | // Event |
||
267 | if (isset($packet['event']) && !isset($packet['actionid'])) { |
||
268 | $this->event('event_' . $packet['event'], $packet); |
||
269 | $this->event('event', $packet); |
||
270 | } // Response |
||
271 | elseif (isset($packet['actionid'])) { |
||
272 | $action_id =& $packet['actionid']; |
||
273 | |||
274 | if (isset($this->callbacks[$action_id])) { |
||
275 | if (isset($this->assertions[$action_id])) { |
||
276 | $this->packets[$action_id][] = $packet; |
||
277 | |||
278 | $assertations = count( |
||
279 | array_uintersect_uassoc( |
||
280 | $this->assertions[$action_id], |
||
281 | $packet, |
||
282 | 'strcasecmp', |
||
283 | 'strcasecmp' |
||
284 | ) |
||
285 | ); |
||
286 | if ($assertations === count($this->assertions[$action_id])) { |
||
287 | if (is_callable($this->callbacks[$action_id])) { |
||
288 | $this->callbacks[$action_id]($this, $this->packets[$action_id]); |
||
289 | unset($this->callbacks[$action_id]); |
||
290 | } |
||
291 | |||
292 | unset($this->assertions[$action_id]); |
||
293 | unset($this->packets[$action_id]); |
||
294 | } |
||
295 | } else { |
||
296 | if (is_callable($this->callbacks[$action_id])) { |
||
297 | $this->callbacks[$action_id]($this, $packet); |
||
298 | unset($this->callbacks[$action_id]); |
||
299 | } |
||
300 | } |
||
301 | } |
||
302 | } |
||
303 | |||
304 | unset($packet); |
||
305 | unset($this->packets[$this->cnt - 1]); |
||
306 | } |
||
307 | } |
||
308 | } |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Send authentication packet |
||
313 | * @return void |
||
314 | */ |
||
315 | protected function auth() |
||
316 | { |
||
317 | if ($this->state !== self::CONN_STATE_GOT_INITIAL_PACKET) { |
||
318 | return; |
||
319 | } |
||
320 | |||
321 | if ($this->pool->config->authtype->value === 'md5') { |
||
322 | $this->challenge(function ($conn, $challenge) { |
||
323 | $packet = "Action: Login\r\n" |
||
324 | . "AuthType: MD5\r\n" |
||
325 | . "Username: " . $this->username . "\r\n" |
||
326 | . "Key: " . md5($challenge . $this->secret) . "\r\n" |
||
327 | . "Events: on\r\n" |
||
328 | . "\r\n"; |
||
329 | $this->state = self::CONN_STATE_LOGIN_PACKET_SENT_AFTER_CHALLENGE; |
||
330 | $conn->write($packet); |
||
331 | }); |
||
332 | } else { |
||
333 | $this->login(); |
||
334 | } |
||
335 | } |
||
336 | |||
337 | /** |
||
338 | * Action: Login |
||
339 | * Synopsis: Login Manager |
||
340 | * Privilege: <none> |
||
341 | * |
||
342 | * @return void |
||
343 | */ |
||
344 | protected function login() |
||
345 | { |
||
346 | $this->state = self::CONN_STATE_LOGIN_PACKET_SENT; |
||
347 | $this->write( |
||
348 | "Action: login\r\n" |
||
349 | . "Username: " . $this->username . "\r\n" |
||
350 | . "Secret: " . $this->secret . "\r\n" |
||
351 | . "Events: on\r\n" |
||
352 | . "\r\n" |
||
353 | ); |
||
354 | } |
||
355 | |||
356 | /** |
||
357 | * Action: Challenge |
||
358 | * Synopsis: Generate Challenge for MD5 Auth |
||
359 | * Privilege: <none> |
||
360 | * |
||
361 | * @param callable $cb |
||
362 | * @return void |
||
363 | */ |
||
364 | protected function challenge($cb) |
||
365 | { |
||
366 | $this->onChallenge = $cb; |
||
367 | $this->state = self::CONN_STATE_CHALLENGE_PACKET_SENT; |
||
368 | $this->write( |
||
369 | "Action: Challenge\r\n" |
||
370 | . "AuthType: MD5\r\n" |
||
371 | . "\r\n" |
||
372 | ); |
||
373 | } |
||
374 | |||
375 | /** |
||
376 | * Action: SIPpeers |
||
377 | * Synopsis: List SIP peers (text format) |
||
378 | * Privilege: system,reporting,all |
||
379 | * Description: Lists SIP peers in text format with details on current status. |
||
380 | * Peerlist will follow as separate events, followed by a final event called |
||
381 | * PeerlistComplete. |
||
382 | * Variables: |
||
383 | * ActionID: <id> Action ID for this transaction. Will be returned. |
||
384 | * |
||
385 | * @param callable $cb Callback called when response received |
||
386 | * @callback $cb ( Connection $conn, array $packet ) |
||
387 | * @return void |
||
388 | */ |
||
389 | public function getSipPeers($cb) |
||
390 | { |
||
391 | $this->command("Action: SIPpeers\r\n", $cb, ['event' => 'peerlistcomplete']); |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * Action: IAXpeerlist |
||
396 | * Synopsis: List IAX Peers |
||
397 | * Privilege: system,reporting,all |
||
398 | * |
||
399 | * @param callable $cb Callback called when response received |
||
400 | * @callback $cb ( Connection $conn, array $packet ) |
||
401 | * @return void |
||
402 | */ |
||
403 | public function getIaxPeers($cb) |
||
404 | { |
||
405 | $this->command("Action: IAXpeerlist\r\n", $cb, ['event' => 'peerlistcomplete']); |
||
406 | } |
||
407 | |||
408 | /** |
||
409 | * Action: GetConfig |
||
410 | * Synopsis: Retrieve configuration |
||
411 | * Privilege: system,config,all |
||
412 | * Description: A 'GetConfig' action will dump the contents of a configuration |
||
413 | * file by category and contents or optionally by specified category only. |
||
414 | * Variables: (Names marked with * are required) |
||
415 | * *Filename: Configuration filename (e.g. foo.conf) |
||
416 | * Category: Category in configuration file |
||
417 | * |
||
418 | * @param string $filename Filename |
||
419 | * @param callable $cb Callback called when response received |
||
420 | * @callback $cb ( Connection $conn, array $packet ) |
||
421 | * @return void |
||
422 | */ |
||
423 | public function getConfig($filename, $cb) |
||
424 | { |
||
425 | $this->command("Action: GetConfig\r\nFilename: " . trim($filename) . "\r\n", $cb); |
||
426 | } |
||
427 | |||
428 | /** |
||
429 | * Action: GetConfigJSON |
||
430 | * Synopsis: Retrieve configuration |
||
431 | * Privilege: system,config,all |
||
432 | * Description: A 'GetConfigJSON' action will dump the contents of a configuration |
||
433 | * file by category and contents in JSON format. This only makes sense to be used |
||
434 | * using rawman over the HTTP interface. |
||
435 | * Variables: |
||
436 | * Filename: Configuration filename (e.g. foo.conf) |
||
437 | * |
||
438 | * @param string $filename Filename |
||
439 | * @param callable $cb Callback called when response received |
||
440 | * @callback $cb ( Connection $conn, array $packet ) |
||
441 | * @return void |
||
442 | */ |
||
443 | public function getConfigJSON($filename, $cb) |
||
444 | { |
||
445 | $this->command("Action: GetConfigJSON\r\nFilename: " . trim($filename) . "\r\n", $cb); |
||
446 | } |
||
447 | |||
448 | /** |
||
449 | * Action: Setvar |
||
450 | * Synopsis: Set Channel Variable |
||
451 | * Privilege: call,all |
||
452 | * Description: Set a global or local channel variable. |
||
453 | * Variables: (Names marked with * are required) |
||
454 | * Channel: Channel to set variable for |
||
455 | * *Variable: Variable name |
||
456 | * *Value: Value |
||
457 | * |
||
458 | * @param string $channel |
||
459 | * @param string $variable |
||
460 | * @param string $value |
||
461 | * @param callable $cb |
||
462 | * @callback $cb ( Connection $conn, array $packet ) |
||
463 | * @return void |
||
464 | */ |
||
465 | public function setVar($channel, $variable, $value, $cb) |
||
466 | { |
||
467 | $cmd = "Action: SetVar\r\n"; |
||
468 | |||
469 | if ($channel) { |
||
470 | $cmd .= "Channel: " . trim($channel) . "\r\n"; |
||
471 | } |
||
472 | |||
473 | if (isset($variable, $value)) { |
||
474 | $cmd .= "Variable: " . trim($variable) . "\r\n" |
||
475 | . "Value: " . trim($value) . "\r\n"; |
||
476 | |||
477 | $this->command($cmd, $cb); |
||
478 | } |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * Action: CoreShowChannels |
||
483 | * Synopsis: List currently active channels |
||
484 | * Privilege: system,reporting,all |
||
485 | * Description: List currently defined channels and some information |
||
486 | * about them. |
||
487 | * Variables: |
||
488 | * ActionID: Optional Action id for message matching. |
||
489 | * |
||
490 | * @param callable $cb |
||
491 | * @callback $cb ( Connection $conn, array $packet ) |
||
492 | * @return void |
||
493 | */ |
||
494 | public function coreShowChannels($cb) |
||
495 | { |
||
496 | $this->command( |
||
497 | "Action: CoreShowChannels\r\n", |
||
498 | $cb, |
||
499 | ['event' => 'coreshowchannelscomplete', 'eventlist' => 'complete'] |
||
500 | ); |
||
501 | } |
||
502 | |||
503 | /** |
||
504 | * Action: Status |
||
505 | * Synopsis: Lists channel status |
||
506 | * Privilege: system,call,reporting,all |
||
507 | * Description: Lists channel status along with requested channel vars. |
||
508 | * Variables: (Names marked with * are required) |
||
509 | *Channel: Name of the channel to query for status |
||
510 | * Variables: Comma ',' separated list of variables to include |
||
511 | * ActionID: Optional ID for this transaction |
||
512 | * Will return the status information of each channel along with the |
||
513 | * value for the specified channel variables. |
||
514 | * |
||
515 | * @param callable $cb |
||
516 | * @param string $channel |
||
0 ignored issues
–
show
Should the type for parameter
$channel not be string|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. ![]() |
|||
517 | * @callback $cb ( Connection $conn, array $packet ) |
||
518 | * @return void |
||
519 | */ |
||
520 | public function status($cb, $channel = null) |
||
521 | { |
||
522 | $cmd = "Action: Status\r\n"; |
||
523 | |||
524 | if ($channel !== null) { |
||
525 | $cmd .= 'Channel: ' . trim($channel) . "\r\n"; |
||
526 | } |
||
527 | |||
528 | $this->command($cmd, $cb, ['event' => 'statuscomplete']); |
||
529 | } |
||
530 | |||
531 | /** |
||
532 | * Action: Redirect |
||
533 | * Synopsis: Redirect (transfer) a call |
||
534 | * Privilege: call,all |
||
535 | * Description: Redirect (transfer) a call. |
||
536 | * Variables: (Names marked with * are required) |
||
537 | * *Channel: Channel to redirect |
||
538 | * ExtraChannel: Second call leg to transfer (optional) |
||
539 | * *Exten: Extension to transfer to |
||
540 | * *Context: Context to transfer to |
||
541 | * *Priority: Priority to transfer to |
||
542 | * ActionID: Optional Action id for message matching. |
||
543 | * |
||
544 | * @param array $params |
||
545 | * @param callable $cb Callback called when response received |
||
546 | * @callback $cb ( Connection $conn, array $packet ) |
||
547 | * @return void |
||
548 | */ |
||
549 | public function redirect(array $params, $cb) |
||
550 | { |
||
551 | $this->command("Action: Redirect\r\n" . $this->implodeParams($params), $cb); |
||
552 | } |
||
553 | |||
554 | /** |
||
555 | * Action: Originate |
||
556 | * Synopsis: Originate a call |
||
557 | * Privilege: call,all |
||
558 | * Description: first the Channel is rung. Then, when that answers, the Extension is dialled within the Context |
||
559 | * to initiate the other end of the call. |
||
560 | * Variables: (Names marked with * are required) |
||
561 | * *Channel: Channel on which to originate the call (The same as you specify in the Dial application command) |
||
562 | * *Context: Context to use on connect (must use Exten & Priority with it) |
||
563 | * *Exten: Extension to use on connect (must use Context & Priority with it) |
||
564 | * *Priority: Priority to use on connect (must use Context & Exten with it) |
||
565 | * Timeout: Timeout (in milliseconds) for the originating connection to happen(defaults to 30000 milliseconds) |
||
566 | * *CallerID: CallerID to use for the call |
||
567 | * Variable: Channels variables to set (max 32). Variables will be set for both channels (local and connected). |
||
568 | * Account: Account code for the call |
||
569 | * Application: Application to use on connect (use Data for parameters) |
||
570 | * Data : Data if Application parameter is used |
||
571 | * ActionID: Optional Action id for message matching. |
||
572 | * |
||
573 | * @param array $params |
||
574 | * @param callable $cb Callback called when response received |
||
575 | * @callback $cb ( Connection $conn, array $packet ) |
||
576 | * @return void |
||
577 | */ |
||
578 | public function originate(array $params, $cb) |
||
579 | { |
||
580 | $params['Async'] = 1; |
||
581 | |||
582 | $this->command("Action: Originate\r\n" . $this->implodeParams($params), $cb); |
||
583 | } |
||
584 | |||
585 | /** |
||
586 | * Action: ExtensionState |
||
587 | * Synopsis: Get an extension's state. |
||
588 | * Description: function can be used to retrieve the state from any hinted extension. |
||
589 | * Variables: (Names marked with * are required) |
||
590 | * *Exten: Extension to get state |
||
591 | * Context: Context for exten |
||
592 | * ActionID: Optional Action id for message matching. |
||
593 | * |
||
594 | * @param array $params |
||
595 | * @param callable $cb Callback called when response received |
||
596 | * @callback $cb ( Connection $conn, array $packet ) |
||
597 | * @return void |
||
598 | */ |
||
599 | public function extensionState(array $params, $cb) |
||
600 | { |
||
601 | $this->command("Action: ExtensionState\r\n" . $this->implodeParams($params), $cb); |
||
602 | } |
||
603 | |||
604 | /** |
||
605 | * Action: Ping |
||
606 | * Description: A 'Ping' action will ellicit a 'Pong' response. Used to keep the |
||
607 | * manager connection open. |
||
608 | * Variables: NONE |
||
609 | * |
||
610 | * @param callable $cb Callback called when response received |
||
611 | * @callback $cb ( Connection $conn, array $packet ) |
||
612 | * @return void |
||
613 | */ |
||
614 | public function ping($cb) |
||
615 | { |
||
616 | $this->command("Action: Ping\r\n", $cb); |
||
617 | } |
||
618 | |||
619 | /** |
||
620 | * For almost any actions in Action: ListCommands |
||
621 | * Privilege: depends on $action |
||
622 | * |
||
623 | * @param string $action Action |
||
624 | * @param callable $cb Callback called when response received |
||
625 | * @param array $params Parameters |
||
0 ignored issues
–
show
Should the type for parameter
$params not be null|array ?
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. ![]() |
|||
626 | * @param array $assertion If more events may follow as response this is a main part or full an action complete event indicating that all data has been sent |
||
0 ignored issues
–
show
Should the type for parameter
$assertion not be null|array ?
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. ![]() |
|||
627 | * @callback $cb ( Connection $conn, array $packet ) |
||
628 | * @return void |
||
629 | */ |
||
630 | public function action($action, $cb, array $params = null, array $assertion = null) |
||
631 | { |
||
632 | $action = trim($action); |
||
633 | |||
634 | $this->command("Action: {$action}\r\n" . ($params ? $this->implodeParams($params) : ''), $cb, $assertion); |
||
635 | } |
||
636 | |||
637 | /** |
||
638 | * Action: Logoff |
||
639 | * Synopsis: Logoff Manager |
||
640 | * Privilege: <none> |
||
641 | * Description: Logoff this manager session |
||
642 | * Variables: NONE |
||
643 | * |
||
644 | * @param callable $cb Optional callback called when response received |
||
0 ignored issues
–
show
Should the type for parameter
$cb not be callable|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. ![]() |
|||
645 | * @callback $cb ( Connection $conn, array $packet ) |
||
646 | * @return void |
||
647 | */ |
||
648 | public function logoff($cb = null) |
||
649 | { |
||
650 | $this->command("Action: Logoff\r\n", $cb); |
||
0 ignored issues
–
show
It seems like
$cb defined by parameter $cb on line 648 can also be of type null ; however, PHPDaemon\Clients\Asterisk\Connection::command() does only seem to accept callable , maybe add an additional type check?
This check looks at variables that have been passed in as parameters and are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble. ![]() |
|||
651 | } |
||
652 | |||
653 | /** |
||
654 | * Called when event occured |
||
655 | * @deprecated Replaced with ->bind('event', ...) |
||
656 | * @param callable $cb Callback |
||
657 | * @return void |
||
658 | */ |
||
659 | public function onEvent($cb) |
||
660 | { |
||
661 | $this->bind('event', $cb); |
||
662 | } |
||
663 | |||
664 | /** |
||
665 | * Sends arbitrary command |
||
666 | * @param string $packet A packet for sending by the connected client to Asterisk |
||
667 | * @param callable $cb Callback called when response received |
||
668 | * @param array $assertion If more events may follow as response this is a main part or full an action complete event indicating that all data has been sent |
||
0 ignored issues
–
show
Should the type for parameter
$assertion not be array|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. ![]() |
|||
669 | */ |
||
670 | protected function command($packet, $cb, $assertion = null) |
||
671 | { |
||
672 | if ($this->finished) { |
||
673 | throw new ConnectionFinished; |
||
674 | } |
||
675 | |||
676 | if ($this->state !== self::CONN_STATE_HANDSHAKED_OK) { |
||
677 | return; |
||
678 | } |
||
679 | |||
680 | $actionId = Daemon::uniqid(); |
||
681 | |||
682 | if (!is_callable($cb, true)) { |
||
683 | $cb = false; |
||
684 | } |
||
685 | |||
686 | $this->callbacks[$actionId] = CallbackWrapper::wrap($cb); |
||
0 ignored issues
–
show
It seems like
$cb defined by false on line 683 can also be of type false ; however, PHPDaemon\Core\CallbackWrapper::wrap() does only seem to accept callable , did you maybe forget to handle an error condition?
This check looks for type mismatches where the missing type is Consider the follow example <?php
function getDate($date)
{
if ($date !== null) {
return new DateTime($date);
}
return false;
}
This function either returns a new ![]() |
|||
687 | |||
688 | if ($assertion !== null) { |
||
689 | $this->assertions[$actionId] = $assertion; |
||
690 | } |
||
691 | |||
692 | $this->write($packet); |
||
693 | $this->write('ActionID: ' . $actionId . "\r\n\r\n"); |
||
694 | } |
||
695 | |||
696 | /** |
||
697 | * Generate AMI packet string from associative array provided |
||
698 | * @param array $params |
||
699 | * @return string |
||
700 | */ |
||
701 | protected function implodeParams(array $params) |
||
702 | { |
||
703 | $s = ''; |
||
704 | |||
705 | foreach ($params as $header => $value) { |
||
706 | $s .= trim($header) . ": " . trim($value) . "\r\n"; |
||
707 | } |
||
708 | |||
709 | return $s; |
||
710 | } |
||
711 | } |
||
712 |
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.