From d6c5a9989910ee7c57574d7ebc1706d09c9c5f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Jensen?= Date: Tue, 3 Nov 2020 21:53:14 +0100 Subject: [PATCH] Documentation --- .gitignore | 1 + .travis.yml | 1 - README.md | 272 ++----------------------------------- COPYING => docs/COPYING.md | 4 +- docs/Changelog.md | 87 ++++++++++++ docs/Client.md | 98 +++++++++++++ docs/Contributing.md | 41 ++++++ docs/Server.md | 97 +++++++++++++ lib/Base.php | 38 +++--- lib/Client.php | 12 +- lib/Server.php | 16 +-- tests/mock/MockSocket.php | 4 +- 12 files changed, 375 insertions(+), 296 deletions(-) rename COPYING => docs/COPYING.md (90%) create mode 100644 docs/Changelog.md create mode 100644 docs/Client.md create mode 100644 docs/Contributing.md create mode 100644 docs/Server.md diff --git a/.gitignore b/.gitignore index dbca5a6..379ab4b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +.phpunit.result.cache build/ composer.lock composer.phar diff --git a/.travis.yml b/.travis.yml index 0cde3bc..216d280 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: php php: - - 8.0 - 7.4 - 7.3 - 7.2 diff --git a/README.md b/README.md index 4538447..d230780 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,14 @@ This library contains WebSocket client and server for PHP. The client and server provides methods for reading and writing to WebSocket streams. It does not include convenience operations such as listeners and implicit error handling. +## Documentation + +- [Client](docs/Server.md) +- [Server](docs/Server.md) +- [Changelog](docs/Changelog.md) +- [Contributing](docs/Contributing.md) +- [License](docs/COPYING.md) + ## Installing Preferred way to install is with [Composer](https://getcomposer.org/). @@ -15,40 +23,15 @@ Preferred way to install is with [Composer](https://getcomposer.org/). composer require textalk/websocket ``` -Current version support PHP versions `^7.1`. -For PHP `^5.4` and `^7.0` support use version `1.3`. +* Current version support PHP versions `^7.2`. +* For PHP `7.1` support use version `1.4`. +* For PHP `^5.4` and `7.0` support use version `1.3`. ## Client -The client can read and write on a WebSocket stream. +The [client](docs/Server.md) can read and write on a WebSocket stream. It internally supports Upgrade handshake and implicit close and ping/pong operations. -### Class synopsis - -```php -WebSocket\Client { - - public __construct(string $uri, array $options = []) - public __destruct() - - public send(mixed $payload, string $opcode = 'text', bool $masked = true) : void - public receive() : mixed - public close(int $status = 1000, mixed $message = 'ttfn') : mixed - - public getLastOpcode() : string - public getCloseStatus() : int - public isConnected() : bool - public setTimeout(int $seconds) : void - public setFragmentSize(int $fragment_size) : self - public getFragmentSize() : int - public setLogger(Psr\Log\LoggerInterface $logger = null) : void -} -``` - -### Example: Simple send-receive operation - -This example send a single message to a server, and output the response. - ```php $client = new WebSocket\Client("ws://echo.websocket.org/"); $client->send("Hello WebSocket.org!"); @@ -56,92 +39,14 @@ echo $client->receive(); $client->close(); ``` -### Example: Listening to a server - -To continuously listen to incoming messages, you need to put the receive operation within a loop. -Note that these functions **always** throw exception on any failure, including recoverable failures such as connection time out. -By consuming exceptions, the code will re-connect the socket in next loop iteration. - -```php -$client = new WebSocket\Client("ws://echo.websocket.org/"); -while (true) { - try { - $message = $client->receive(); - // Act on received message - // Break while loop to stop listening - } catch (\WebSocket\ConnectionException $e) { - // Possibly log errors - } -} -$client->close(); -``` - -### Constructor options - -The `$options` parameter in constructor accepts an associative array of options. - -* `timeout` - Time out in seconds. Default 5 seconds. -* `fragment_size` - Maximum payload size. Default 4096 chars. -* `context` - A stream context created using [stream_context_create](https://www.php.net/manual/en/function.stream-context-create). -* `headers` - Additional headers as associative array name => content. -* `logger` - A [PSR-3](https://www.php-fig.org/psr/psr-3/) compatible logger. -* `persistent` - Connection is re-used between requests until time out is reached. Default false. - -```php -$context = stream_context_create(); -stream_context_set_option($context, 'ssl', 'verify_peer', false); -stream_context_set_option($context, 'ssl', 'verify_peer_name', false); - -$client = new WebSocket\Client("ws://echo.websocket.org/", [ - 'timeout' => 60, // 1 minute time out - 'context' => $context, - 'headers' => [ - 'Sec-WebSocket-Protocol' => 'soap', - 'origin' => 'localhost', - ], -]); -``` - ## Server -The library contains a rudimentary single stream/single thread server. +The library contains a rudimentary single stream/single thread [server](docs/Server.md). It internally supports Upgrade handshake and implicit close and ping/pong operations. Note that it does **not** support threading or automatic association ot continuous client requests. If you require this kind of server behavior, you need to build it on top of provided server implementation. -### Class synopsis - -```php -WebSocket\Server { - - public __construct(array $options = []) - public __destruct() - - public accept() : bool - public send(mixed $payload, string $opcode = 'text', bool $masked = true) : void - public receive() : mixed - public close(int $status = 1000, mixed $message = 'ttfn') : mixed - - public getPort() : int - public getPath() : string - public getRequest() : array - public getHeader(string $header_name) : string|null - - public getLastOpcode() : string - public getCloseStatus() : int - public isConnected() : bool - public setTimeout(int $seconds) : void - public setFragmentSize(int $fragment_size) : self - public getFragmentSize() : int - public setLogger(Psr\Log\LoggerInterface $logger = null) : void -} -``` - -### Example: Simple receive-send operation - -This example reads a single message from a client, and respond with the same message. - ```php $server = new WebSocket\Server(); $server->accept(); @@ -150,160 +55,9 @@ $server->send($message); $server->close(); ``` -### Example: Listening to clients - -To continuously listen to incoming messages, you need to put the receive operation within a loop. -Note that these functions **always** throw exception on any failure, including recoverable failures such as connection time out. -By consuming exceptions, the code will re-connect the socket in next loop iteration. - -```php -$server = new WebSocket\Server(); -while ($server->accept()) { - try { - $message = $server->receive(); - // Act on received message - // Break while loop to stop listening - } catch (\WebSocket\ConnectionException $e) { - // Possibly log errors - } -} -$server->close(); -``` - -### Constructor options - -The `$options` parameter in constructor accepts an associative array of options. - -* `timeout` - Time out in seconds. Default 5 seconds. -* `port` - The server port to listen to. Default 8000. -* `fragment_size` - Maximum payload size. Default 4096 chars. -* `logger` - A [PSR-3](https://www.php-fig.org/psr/psr-3/) compatible logger. - -```php -$server = new WebSocket\Server([ - 'timeout' => 60, // 1 minute time out - 'port' => 9000, -]); -``` - -## Exceptions - -* `WebSocket\BadOpcodeException` - Thrown if provided opcode is invalid. -* `WebSocket\BadUriException` - Thrown if provided URI is invalid. -* `WebSocket\ConnectionException` - Thrown on any socket I/O failure. -* `WebSocket\TimeoutExeception` - Thrown when the socket experiences a time out. - - -## Development and contribution - -Requirements on pull requests; -* All tests **MUST** pass. -* Code coverage **MUST** remain on 100%. -* Code **MUST** adhere to PSR-1 and PSR-12 code standards. - -Install or update dependencies using [Composer](https://getcomposer.org/). -``` -# Install dependencies -make install - -# Update dependencies -make update -``` - -This project uses [PSR-1](https://www.php-fig.org/psr/psr-1/) and [PSR-12](https://www.php-fig.org/psr/psr-12/) code standards. -``` -# Check code standard adherence -make cs-check -``` - -Unit tests with [PHPUnit](https://phpunit.readthedocs.io/). -``` -# Run unit tests -make test -``` - -## License ([ISC](http://en.wikipedia.org/wiki/ISC_license)) - -Copyright (C) 2014-2020 Textalk/Abicart and contributors. - -Websocket PHP is free software: Permission to use, copy, modify, and/or distribute this software -for any purpose with or without fee is hereby granted, provided that the above copyright notice and -this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE -AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -See [Copying](COPYING). - ### Contributors Fredrik Liljegren, Armen Baghumian Sankbarani, Ruslan Bekenev, Joshua Thijssen, Simon Lipp, Quentin Bellus, Patrick McCarren, swmcdonnell, Ignas Bernotas, Mark Herhold, Andreas Palm, Sören Jensen, pmaasz, Alexey Stavrov, Michael Slezak, Pierre Seznec, rmeisler, Nickolay V. Shmyrev. - - -## Changelog - -1.4.1 - - * Ping/Pong, handled internally to avoid breaking fragmented messages (@nshmyrev, @sirn-se) - * Fix for persistent connections (@rmeisler) - * Fix opcode bitmask (@peterjah) - -1.4.0 - - * Dropped support of old PHP versions (@sirn-se) - * Added PSR-3 Logging support (@sirn-se) - * Persistent connection option (@slezakattack) - * TimeoutException on connection time out (@slezakattack) - -1.3.1 - - * Allow control messages without payload (@Logioniz) - * Error code in ConnectionException (@sirn-se) - -1.3.0 - - * Implements ping/pong frames (@pmccarren @Logioniz) - * Close behaviour (@sirn-se) - * Various fixes concerning connection handling (@sirn-se) - * Overhaul of Composer, Travis and Coveralls setup, PSR code standard and unit tests (@sirn-se) - -1.2.0 - - * Adding stream context options (to set e.g. SSL `allow_self_signed`). - -1.1.2 - - * Fixed error message on broken frame. - -1.1.1 - - * Adding license information. - -1.1.0 - - * Supporting huge payloads. - -1.0.3 - - * Bugfix: Correcting address in error-message - -1.0.2 - - * Bugfix: Add port in request-header. - -1.0.1 - - * Fixing a bug from empty payloads. - -1.0.0 - - * Release as production ready. - * Adding option to set/override headers. - * Supporting basic authentication from user:pass in URL. diff --git a/COPYING b/docs/COPYING.md similarity index 90% rename from COPYING rename to docs/COPYING.md index cd2a38d..ba96480 100644 --- a/COPYING +++ b/docs/COPYING.md @@ -1,6 +1,8 @@ +# Websocket: License + Websocket PHP is free software released under the following license: -ISC License +[ISC License](http://en.wikipedia.org/wiki/ISC_license) Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear diff --git a/docs/Changelog.md b/docs/Changelog.md new file mode 100644 index 0000000..4c6952f --- /dev/null +++ b/docs/Changelog.md @@ -0,0 +1,87 @@ +# Websocket: Changelog + +- [Client](Client.md) +- [Server](Server.md) +- Changelog +- [Contributing](Contributing.md) +- [License](COPYING.md) + +## 1.4 + +PHP version `^7.1` + +### 1.4.1 + + * Ping/Pong, handled internally to avoid breaking fragmented messages (@nshmyrev, @sirn-se) + * Fix for persistent connections (@rmeisler) + * Fix opcode bitmask (@peterjah) + +### 1.4.0 + + * Dropped support of old PHP versions (@sirn-se) + * Added PSR-3 Logging support (@sirn-se) + * Persistent connection option (@slezakattack) + * TimeoutException on connection time out (@slezakattack) + +## 1.3 + +PHP version `^5.4` and `^7.0` + +### 1.3.1 + + * Allow control messages without payload (@Logioniz) + * Error code in ConnectionException (@sirn-se) + +### 1.3.0 + + * Implements ping/pong frames (@pmccarren @Logioniz) + * Close behaviour (@sirn-se) + * Various fixes concerning connection handling (@sirn-se) + * Overhaul of Composer, Travis and Coveralls setup, PSR code standard and unit tests (@sirn-se) + +## 1.2 + +PHP version `^5.4` and `^7.0` + +### 1.2.0 + + * Adding stream context options (to set e.g. SSL `allow_self_signed`). + +## 1.1 + +PHP version `^5.4` and `^7.0` + +### 1.1.2 + + * Fixed error message on broken frame. + +### 1.1.1 + + * Adding license information. + +### 1.1.0 + + * Supporting huge payloads. + +## 1.0 + +PHP version `^5.4` and `^7.0` + +### 1.0.3 + + * Bugfix: Correcting address in error-message + +### 1.0.2 + + * Bugfix: Add port in request-header. + +### 1.0.1 + + * Fixing a bug from empty payloads. + +### 1.0.0 + + * Release as production ready. + * Adding option to set/override headers. + * Supporting basic authentication from user:pass in URL. + diff --git a/docs/Client.md b/docs/Client.md new file mode 100644 index 0000000..a099ec7 --- /dev/null +++ b/docs/Client.md @@ -0,0 +1,98 @@ +# Websocket: Client + +- Client +- [Server](Server.md) +- [Change log](Changelog.md) +- [Contributing](Contributing.md) +- [License](COPYING.md) + +## Client + +The client can read and write on a WebSocket stream. +It internally supports Upgrade handshake and implicit close and ping/pong operations. + +### Class synopsis + +```php +WebSocket\Client { + + public __construct(string $uri, array $options = []) + public __destruct() + + public send(mixed $payload, string $opcode = 'text', bool $masked = true) : void + public receive() : mixed + public close(int $status = 1000, mixed $message = 'ttfn') : mixed + + public getLastOpcode() : string + public getCloseStatus() : int + public isConnected() : bool + public setTimeout(int $seconds) : void + public setFragmentSize(int $fragment_size) : self + public getFragmentSize() : int + public setLogger(Psr\Log\LoggerInterface $logger = null) : void +} +``` + +### Example: Simple send-receive operation + +This example send a single message to a server, and output the response. + +```php +$client = new WebSocket\Client("ws://echo.websocket.org/"); +$client->send("Hello WebSocket.org!"); +echo $client->receive(); +$client->close(); +``` + +### Example: Listening to a server + +To continuously listen to incoming messages, you need to put the receive operation within a loop. +Note that these functions **always** throw exception on any failure, including recoverable failures such as connection time out. +By consuming exceptions, the code will re-connect the socket in next loop iteration. + +```php +$client = new WebSocket\Client("ws://echo.websocket.org/"); +while (true) { + try { + $message = $client->receive(); + // Act on received message + // Break while loop to stop listening + } catch (\WebSocket\ConnectionException $e) { + // Possibly log errors + } +} +$client->close(); +``` + +### Constructor options + +The `$options` parameter in constructor accepts an associative array of options. + +* `timeout` - Time out in seconds. Default 5 seconds. +* `fragment_size` - Maximum payload size. Default 4096 chars. +* `context` - A stream context created using [stream_context_create](https://www.php.net/manual/en/function.stream-context-create). +* `headers` - Additional headers as associative array name => content. +* `logger` - A [PSR-3](https://www.php-fig.org/psr/psr-3/) compatible logger. +* `persistent` - Connection is re-used between requests until time out is reached. Default false. + +```php +$context = stream_context_create(); +stream_context_set_option($context, 'ssl', 'verify_peer', false); +stream_context_set_option($context, 'ssl', 'verify_peer_name', false); + +$client = new WebSocket\Client("ws://echo.websocket.org/", [ + 'timeout' => 60, // 1 minute time out + 'context' => $context, + 'headers' => [ + 'Sec-WebSocket-Protocol' => 'soap', + 'origin' => 'localhost', + ], +]); +``` + +## Exceptions + +* `WebSocket\BadOpcodeException` - Thrown if provided opcode is invalid. +* `WebSocket\BadUriException` - Thrown if provided URI is invalid. +* `WebSocket\ConnectionException` - Thrown on any socket I/O failure. +* `WebSocket\TimeoutExeception` - Thrown when the socket experiences a time out. diff --git a/docs/Contributing.md b/docs/Contributing.md new file mode 100644 index 0000000..6d7ea9f --- /dev/null +++ b/docs/Contributing.md @@ -0,0 +1,41 @@ +# Websocket: Contributing + +- [Client](Client.md) +- [Server](Server.md) +- [Changelog](Changelog.md) +- Contributing +- [License](COPYING.md) + +### Contribution Requirements + +Requirements on pull requests; +* All tests **MUST** pass. +* Code coverage **MUST** remain on 100%. +* Code **MUST** adhere to PSR-1 and PSR-12 code standards. + +### Dependency management + +Install or update dependencies using [Composer](https://getcomposer.org/). + +``` +# Install dependencies +make install + +# Update dependencies +make update +``` + +### Code standard + +This project uses [PSR-1](https://www.php-fig.org/psr/psr-1/) and [PSR-12](https://www.php-fig.org/psr/psr-12/) code standards. +``` +# Check code standard adherence +make cs-check +``` + +### Unit testing + +Unit tests with [PHPUnit](https://phpunit.readthedocs.io/). +``` +# Run unit tests +make test diff --git a/docs/Server.md b/docs/Server.md new file mode 100644 index 0000000..5fc64b3 --- /dev/null +++ b/docs/Server.md @@ -0,0 +1,97 @@ +# Websocket: Server + +- [Client](Client.md) +- Server +- [Change log](Changelog.md) +- [Contributing](Contributing.md) +- [License](COPYING.md) + +## Server + +The library contains a rudimentary single stream/single thread server. +It internally supports Upgrade handshake and implicit close and ping/pong operations. + +Note that it does **not** support threading or automatic association ot continuous client requests. +If you require this kind of server behavior, you need to build it on top of provided server implementation. + +### Class synopsis + +```php +WebSocket\Server { + + public __construct(array $options = []) + public __destruct() + + public accept() : bool + public send(mixed $payload, string $opcode = 'text', bool $masked = true) : void + public receive() : mixed + public close(int $status = 1000, mixed $message = 'ttfn') : mixed + + public getPort() : int + public getPath() : string + public getRequest() : array + public getHeader(string $header_name) : string|null + + public getLastOpcode() : string + public getCloseStatus() : int + public isConnected() : bool + public setTimeout(int $seconds) : void + public setFragmentSize(int $fragment_size) : self + public getFragmentSize() : int + public setLogger(Psr\Log\LoggerInterface $logger = null) : void +} +``` + +### Example: Simple receive-send operation + +This example reads a single message from a client, and respond with the same message. + +```php +$server = new WebSocket\Server(); +$server->accept(); +$message = $server->receive(); +$server->send($message); +$server->close(); +``` + +### Example: Listening to clients + +To continuously listen to incoming messages, you need to put the receive operation within a loop. +Note that these functions **always** throw exception on any failure, including recoverable failures such as connection time out. +By consuming exceptions, the code will re-connect the socket in next loop iteration. + +```php +$server = new WebSocket\Server(); +while ($server->accept()) { + try { + $message = $server->receive(); + // Act on received message + // Break while loop to stop listening + } catch (\WebSocket\ConnectionException $e) { + // Possibly log errors + } +} +$server->close(); +``` + +### Constructor options + +The `$options` parameter in constructor accepts an associative array of options. + +* `timeout` - Time out in seconds. Default 5 seconds. +* `port` - The server port to listen to. Default 8000. +* `fragment_size` - Maximum payload size. Default 4096 chars. +* `logger` - A [PSR-3](https://www.php-fig.org/psr/psr-3/) compatible logger. + +```php +$server = new WebSocket\Server([ + 'timeout' => 60, // 1 minute time out + 'port' => 9000, +]); +``` + +## Exceptions + +* `WebSocket\BadOpcodeException` - Thrown if provided opcode is invalid. +* `WebSocket\ConnectionException` - Thrown on any socket I/O failure. +* `WebSocket\TimeoutExeception` - Thrown when the socket experiences a time out. diff --git a/lib/Base.php b/lib/Base.php index 52abeee..05058c5 100644 --- a/lib/Base.php +++ b/lib/Base.php @@ -22,33 +22,33 @@ class Base implements LoggerAwareInterface protected $close_status = null; protected $logger; - protected static $opcodes = array( + protected static $opcodes = [ 'continuation' => 0, 'text' => 1, 'binary' => 2, 'close' => 8, 'ping' => 9, 'pong' => 10, - ); + ]; - public function getLastOpcode() + public function getLastOpcode(): ?string { return $this->last_opcode; } - public function getCloseStatus() + public function getCloseStatus(): ?int { return $this->close_status; } - public function isConnected() + public function isConnected(): bool { return $this->socket && (get_resource_type($this->socket) == 'stream' || get_resource_type($this->socket) == 'persistent stream'); } - public function setTimeout($timeout) + public function setTimeout($timeout): void { $this->options['timeout'] = $timeout; @@ -57,23 +57,23 @@ public function setTimeout($timeout) } } - public function setFragmentSize($fragment_size) + public function setFragmentSize($fragment_size): self { $this->options['fragment_size'] = $fragment_size; return $this; } - public function getFragmentSize() + public function getFragmentSize(): int { return $this->options['fragment_size']; } - public function setLogger(LoggerInterface $logger = null) + public function setLogger(LoggerInterface $logger = null): void { $this->logger = $logger ?: new NullLogger(); } - public function send($payload, $opcode = 'text', $masked = true) + public function send($payload, $opcode = 'text', $masked = true): void { if (!$this->isConnected()) { $this->connect(); @@ -101,7 +101,7 @@ public function send($payload, $opcode = 'text', $masked = true) $this->logger->info("Sent '{$opcode}' message"); } - protected function sendFragment($final, $payload, $opcode, $masked) + protected function sendFragment($final, $payload, $opcode, $masked): void { // Binary string for header. $frame_head_binstr = ''; @@ -155,7 +155,7 @@ protected function sendFragment($final, $payload, $opcode, $masked) $this->write($frame); } - public function receive() + public function receive(): string { if (!$this->isConnected()) { $this->connect(); @@ -171,7 +171,7 @@ public function receive() return $payload; } - protected function receiveFragment() + protected function receiveFragment(): array { // Just read the main fragment information first. $data = $this->read(2); @@ -283,10 +283,10 @@ protected function receiveFragment() * @param integer $status http://tools.ietf.org/html/rfc6455#section-7.4 * @param string $message A closing message, max 125 bytes. */ - public function close($status = 1000, $message = 'ttfn') + public function close($status = 1000, $message = 'ttfn'): void { if (!$this->isConnected()) { - return null; + return; } $status_binstr = sprintf('%016b', $status); $status_str = ''; @@ -300,7 +300,7 @@ public function close($status = 1000, $message = 'ttfn') $this->receive(); // Receiving a close frame will close the socket now. } - protected function write($data) + protected function write($data): void { $length = strlen($data); $written = fwrite($this->socket, $data); @@ -316,7 +316,7 @@ protected function write($data) $this->logger->debug("Wrote {$written} of {$length} bytes."); } - protected function read($length) + protected function read($length): string { $data = ''; while (strlen($data) < $length) { @@ -333,7 +333,7 @@ protected function read($length) return $data; } - protected function throwException($message, $code = 0) + protected function throwException($message, $code = 0): void { $meta = stream_get_meta_data($this->socket); $json_meta = json_encode($meta); @@ -352,7 +352,7 @@ protected function throwException($message, $code = 0) /** * Helper to convert a binary to a string of '0' and '1'. */ - protected static function sprintB($string) + protected static function sprintB($string): string { $return = ''; for ($i = 0; $i < strlen($string); $i++) { diff --git a/lib/Client.php b/lib/Client.php index 5dec6bb..0bb5dcb 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -33,7 +33,7 @@ class Client extends Base * - fragment_size: Set framgemnt size. Default: 4096 * - headers: Associative array of headers to set/override. */ - public function __construct($uri, $options = array()) + public function __construct($uri, $options = []) { $this->options = array_merge(self::$default_options, $options); $this->socket_uri = $uri; @@ -51,7 +51,7 @@ public function __destruct() /** * Perform WebSocket handshake */ - protected function connect() + protected function connect(): void { $url_parts = parse_url($this->socket_uri); if (empty($url_parts) || empty($url_parts['scheme']) || empty($url_parts['host'])) { @@ -76,7 +76,7 @@ protected function connect() $path_with_query .= '#' . $fragment; } - if (!in_array($scheme, array('ws', 'wss'))) { + if (!in_array($scheme, ['ws', 'wss'])) { $error = "Url should have scheme ws or wss, not '{$scheme}' from URI '{$this->socket_uri}'."; $this->logger->error($error); throw new BadUriException($error); @@ -124,14 +124,14 @@ protected function connect() $key = self::generateKey(); // Default headers - $headers = array( + $headers = [ 'Host' => $host . ":" . $port, 'User-Agent' => 'websocket-client-php', 'Connection' => 'Upgrade', 'Upgrade' => 'websocket', 'Sec-WebSocket-Key' => $key, 'Sec-WebSocket-Version' => '13', - ); + ]; // Handle basic authentication. if ($user || $pass) { @@ -194,7 +194,7 @@ function ($key, $value) { * * @return string Random string */ - protected static function generateKey() + protected static function generateKey(): string { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"$&/()=[]{}0123456789'; $key = ''; diff --git a/lib/Server.php b/lib/Server.php index 6b23d6d..1ff1940 100644 --- a/lib/Server.php +++ b/lib/Server.php @@ -32,7 +32,7 @@ class Server extends Base * - fragment_size: Set framgemnt size. Default: 4096 * - port: Chose port for listening. Default 8000. */ - public function __construct(array $options = array()) + public function __construct(array $options = []) { $this->options = array_merge(self::$default_options, $options); $this->port = $this->options['port']; @@ -59,22 +59,22 @@ public function __destruct() $this->socket = null; } - public function getPort() + public function getPort(): int { return $this->port; } - public function getPath() + public function getPath(): string { return $this->request_path; } - public function getRequest() + public function getRequest(): array { return $this->request; } - public function getHeader($header) + public function getHeader($header): ?string { foreach ($this->request as $row) { if (stripos($row, $header) !== false) { @@ -85,13 +85,13 @@ public function getHeader($header) return null; } - public function accept() + public function accept(): bool { $this->socket = null; return (bool)$this->listening; } - protected function connect() + protected function connect(): void { if (empty($this->options['timeout'])) { $this->socket = @stream_socket_accept($this->listening); @@ -114,7 +114,7 @@ protected function connect() $this->logger->info("Server connected to port {$this->port}"); } - protected function performHandshake() + protected function performHandshake(): void { $request = ''; do { diff --git a/tests/mock/MockSocket.php b/tests/mock/MockSocket.php index 20fd7b9..279b3ea 100644 --- a/tests/mock/MockSocket.php +++ b/tests/mock/MockSocket.php @@ -34,13 +34,13 @@ public static function handle($function, $params = []) } // Check if all expected calls are performed - public static function isEmpty() + public static function isEmpty(): bool { return empty(self::$queue); } // Initialize call queue - public static function initialize($op_file, $asserter) + public static function initialize($op_file, $asserter): void { $file = dirname(__DIR__) . "/scripts/{$op_file}.json"; self::$queue = json_decode(file_get_contents($file), true);