Skip to content

Commit

Permalink
Merge pull request #126 from Textalk/v1.5-master
Browse files Browse the repository at this point in the history
Version 1.5.0
  • Loading branch information
sirn-se authored Dec 13, 2020
2 parents c5c14d2 + d5d3ba1 commit ded6832
Show file tree
Hide file tree
Showing 42 changed files with 1,278 additions and 220 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ php:
- 7.4
- 7.3
- 7.2
- 7.1

before_script:
- make install build
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ It does not include convenience operations such as listeners and implicit error

- [Client](docs/Client.md)
- [Server](docs/Server.md)
- [Message](docs/Message.md)
- [Examples](docs/Examples.md)
- [Changelog](docs/Changelog.md)
- [Contributing](docs/Contributing.md)
Expand All @@ -23,7 +24,8 @@ Preferred way to install is with [Composer](https://getcomposer.org/).
composer require textalk/websocket
```

* Current version support PHP versions `^7.1`.
* Current version support PHP versions `^7.2|8.0`.
* For PHP `7.1` support use version `1.4`.
* For PHP `^5.4` and `7.0` support use version `1.3`.

## Client
Expand All @@ -33,7 +35,7 @@ It internally supports Upgrade handshake and implicit close and ping/pong operat

```php
$client = new WebSocket\Client("ws://echo.websocket.org/");
$client->send("Hello WebSocket.org!");
$client->text("Hello WebSocket.org!");
echo $client->receive();
$client->close();
```
Expand All @@ -50,7 +52,7 @@ If you require this kind of server behavior, you need to build it on top of prov
$server = new WebSocket\Server();
$server->accept();
$message = $server->receive();
$server->send($message);
$server->text($message);
$server->close();
```

Expand All @@ -61,4 +63,4 @@ $server->close();
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.
Michael Slezak, Pierre Seznec, rmeisler, Nickolay V. Shmyrev, Christoph Kempen.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
}
},
"require": {
"php": "^7.1 | ^8.0",
"php": "^7.2 | ^8.0",
"psr/log": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^7.0|^8.0|^9.0",
"phpunit/phpunit": "^8.0|^9.0",
"php-coveralls/php-coveralls": "^2.0",
"squizlabs/php_codesniffer": "^3.5"
}
Expand Down
17 changes: 16 additions & 1 deletion docs/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
[Client](Client.md)[Server](Server.md)[Examples](Examples.md) • Changelog • [Contributing](Contributing.md)
[Client](Client.md)[Server](Server.md)[Message](Message.md)[Examples](Examples.md) • Changelog • [Contributing](Contributing.md)

# Websocket: Changelog

## `v1.5`

> PHP version `^7.2`
### `1.5.0`

* Convenience send methods; text(), binary(), ping(), pong() (@sirn-se)
* Optional Message instance as receive() method return (@sirn-se)
* Opcode filter for receive() method (@sirn-se)
* Added PHP `8.0` support (@webpatser)
* Dropped PHP `7.1` support (@sirn-se)
* Fix for unordered fragmented messages (@sirn-se)
* Improved error handling on stream calls (@sirn-se)
* Various code re-write (@sirn-se)

## `v1.4`

> PHP version `^7.1`
Expand Down
57 changes: 50 additions & 7 deletions docs/Client.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Client • [Server](Server.md)[Examples](Examples.md)[Changelog](Changelog.md)[Contributing](Contributing.md)
Client • [Server](Server.md)[Message](Message.md)[Examples](Examples.md)[Changelog](Changelog.md)[Contributing](Contributing.md)

# Websocket: Client

Expand All @@ -12,11 +12,18 @@ WebSocket\Client {

public __construct(string $uri, array $options = [])
public __destruct()
public __toString() : string

public text(string $payload) : void
public binary(string $payload) : void
public ping(string $payload = '') : void
public pong(string $payload = '') : void
public send(mixed $payload, string $opcode = 'text', bool $masked = true) : void
public receive() : mixed
public close(int $status = 1000, mixed $message = 'ttfn') : mixed

public getName() : string|null
public getPier() : string|null
public getLastOpcode() : string
public getCloseStatus() : int
public isConnected() : bool
Expand All @@ -35,7 +42,7 @@ 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!");
$client->text("Hello WebSocket.org!");
echo $client->receive();
$client->close();
```
Expand All @@ -60,29 +67,65 @@ while (true) {
$client->close();
```

### Filtering received messages

By default the `receive()` method return messages of 'text' and 'binary' opcode.
The filter option allows you to specify which message types to return.

```php
$client = new WebSocket\Client("ws://echo.websocket.org/", ['filter' => ['text']]);
$client->receive(); // Only return 'text' messages

$client = new WebSocket\Client("ws://echo.websocket.org/", ['filter' => ['text', 'binary', 'ping', 'pong', 'close']]);
$client->receive(); // Return all messages
```

### Sending messages

There are convenience methods to send messages with different opcodes.
```php
$client = new WebSocket\Client("ws://echo.websocket.org/");

// Convenience methods
$client->text('A plain text message'); // Send an opcode=text message
$client->binary($binary_string); // Send an opcode=binary message
$client->ping(); // Send an opcode=ping frame
$client->pong(); // Send an unsolicited opcode=pong frame

// Generic send method
$client->send($payload); // Sent as masked opcode=text
$client->send($payload, 'binary'); // Sent as masked opcode=binary
$client->send($payload, 'binary', false); // Sent as unmasked opcode=binary
```

## 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).
* `filter` - Array of opcodes to return on receive, default `['text', 'binary']`
* `fragment_size` - Maximum payload size. Default 4096 chars.
* `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.
* `return_obj` - Return a [Message](Message.md) instance on receive, default false
* `timeout` - Time out in seconds. Default 5 seconds.

```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' => [
'context' => $context, // Attach stream context created above
'filter' => ['text', 'binary', 'ping'], // Specify message types for receive() to return
'headers' => [ // Additional headers, used to specify subprotocol
'Sec-WebSocket-Protocol' => 'soap',
'origin' => 'localhost',
],
'logger' => $my_psr3_logger, // Attach a PSR3 compatible logger
'return_obj' => true, // Return Message insatnce rather than just text
'timeout' => 60, // 1 minute time out
]);
```

Expand Down
8 changes: 6 additions & 2 deletions docs/Contributing.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[Client](Client.md)[Server](Server.md)[Examples](Examples.md)[Changelog](Changelog.md) • Contributing
[Client](Client.md)[Server](Server.md)[Message](Message.md)[Examples](Examples.md)[Changelog](Changelog.md) • Contributing

# Websocket: Contributing

Expand Down Expand Up @@ -34,7 +34,11 @@ make cs-check

## Unit testing

Unit tests with [PHPUnit](https://phpunit.readthedocs.io/).
Unit tests with [PHPUnit](https://phpunit.readthedocs.io/), coverage with [Coveralls](https://github.com/php-coveralls/php-coveralls)
```
# Run unit tests
make test
# Create coverage
make coverage
```
2 changes: 1 addition & 1 deletion docs/Examples.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[Client](Client.md)[Server](Server.md) • Examples • [Changelog](Changelog.md)[Contributing](Contributing.md)
[Client](Client.md)[Server](Server.md)[Message](Message.md)Examples • [Changelog](Changelog.md)[Contributing](Contributing.md)

# Websocket: Examples

Expand Down
60 changes: 60 additions & 0 deletions docs/Message.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[Client](Client.md)[Server](Server.md) • Message • [Examples](Examples.md)[Changelog](Changelog.md)[Contributing](Contributing.md)

# Websocket: Messages

If option `return_obj` is set to `true` on [client](Client.md) or [server](Server.md),
the `receive()` method will return a Message instance instead of a string.

Available classes correspond to opcode;
* WebSocket\Message\Text
* WebSocket\Message\Binary
* WebSocket\Message\Ping
* WebSocket\Message\Pong
* WebSocket\Message\Close

Additionally;
* WebSocket\Message\Message - abstract base class for all messages above
* WebSocket\Message\Factory - Factory class to create Msssage instances

## Message abstract class synopsis

```php
WebSocket\Message\Message {

public __construct(string $payload = '')
public __toString() : string

public getOpcode() : string
public getLength() : int
public getTimestamp() : DateTime
public getContent() : string
public setContent(string $payload = '') : void
public hasContent() : bool
}
```

## Factory class synopsis

```php
WebSocket\Message\Factory {

public create(string $opcode, string $payload = '') : Message
}
```

## Example

Receving a Message and echo some methods.

```php
$client = new WebSocket\Client('ws://echo.websocket.org/', ['return_obj' => true]);
$client->text('Hello WebSocket.org!');
// Echo return same message as sent
$message = $client->receive();
echo $message->getOpcode(); // -> "text"
echo $message->getLength(); // -> 20
echo $message->getContent(); // -> "Hello WebSocket.org!"
echo $message->hasContent(); // -> true
echo $message->getTimestamp()->format('H:i:s'); // -> 19:37:18
$client->close();
```
53 changes: 48 additions & 5 deletions docs/Server.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[Client](Client.md) • Server • [Examples](Examples.md)[Changelog](Changelog.md)[Contributing](Contributing.md)
[Client](Client.md) • Server • [Message](Message.md)[Examples](Examples.md)[Changelog](Changelog.md)[Contributing](Contributing.md)

# Websocket: Server

Expand All @@ -15,8 +15,13 @@ WebSocket\Server {

public __construct(array $options = [])
public __destruct()
public __toString() : string

public accept() : bool
public text(string $payload) : void
public binary(string $payload) : void
public ping(string $payload = '') : void
public pong(string $payload = '') : void
public send(mixed $payload, string $opcode = 'text', bool $masked = true) : void
public receive() : mixed
public close(int $status = 1000, mixed $message = 'ttfn') : mixed
Expand All @@ -26,6 +31,8 @@ WebSocket\Server {
public getRequest() : array
public getHeader(string $header_name) : string|null

public getName() : string|null
public getPier() : string|null
public getLastOpcode() : string
public getCloseStatus() : int
public isConnected() : bool
Expand All @@ -46,7 +53,7 @@ This example reads a single message from a client, and respond with the same mes
$server = new WebSocket\Server();
$server->accept();
$message = $server->receive();
$server->send($message);
$server->text($message);
$server->close();
```

Expand All @@ -70,19 +77,55 @@ while ($server->accept()) {
$server->close();
```

### Filtering received messages

By default the `receive()` method return messages of 'text' and 'binary' opcode.
The filter option allows you to specify which message types to return.

```php
$server = new WebSocket\Server(['filter' => ['text']]);
$server->receive(); // only return 'text' messages

$server = new WebSocket\Server(['filter' => ['text', 'binary', 'ping', 'pong', 'close']]);
$server->receive(); // return all messages
```

### Sending messages

There are convenience methods to send messages with different opcodes.
```php
$server = new WebSocket\Server();

// Convenience methods
$server->text('A plain text message'); // Send an opcode=text message
$server->binary($binary_string); // Send an opcode=binary message
$server->ping(); // Send an opcode=ping frame
$server->pong(); // Send an unsolicited opcode=pong frame

// Generic send method
$server->send($payload); // Sent as masked opcode=text
$server->send($payload, 'binary'); // Sent as masked opcode=binary
$server->send($payload, 'binary', false); // Sent as unmasked opcode=binary
```

## 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.
* `filter` - Array of opcodes to return on receive, default `['text', 'binary']`
* `fragment_size` - Maximum payload size. Default 4096 chars.
* `logger` - A [PSR-3](https://www.php-fig.org/psr/psr-3/) compatible logger.
* `port` - The server port to listen to. Default 8000.
* `return_obj` - Return a [Message](Message.md) instance on receive, default false
* `timeout` - Time out in seconds. Default 5 seconds.

```php
$server = new WebSocket\Server([
'filter' => ['text', 'binary', 'ping'], // Specify message types for receive() to return
'logger' => $my_psr3_logger, // Attach a PSR3 compatible logger
'port' => 9000, // Listening port
'return_obj' => true, // Return Message insatnce rather than just text
'timeout' => 60, // 1 minute time out
'port' => 9000,
]);
```

Expand Down
Loading

0 comments on commit ded6832

Please sign in to comment.