Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"phrity/http": "^1.1",
"phrity/net-uri": "^2.1",
"phrity/net-stream": "^2.3",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.1 || ^2.0",
"psr/log": "^1.0 || ^2.0 || ^3.0"
},
Expand Down
11 changes: 11 additions & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

# Websocket: Changelog

## `v3.7`

> PHP version `^8.1`

### `3.7.0`

* Configuration class for various settings (@sirn-se)
* Identity interface and implementation (@sirn-se)
* Using Nyholm PSR HTTP (intermediate solution) (@sirn-se)
* Preparations for v4 (@sirn-se)

## `v3.6`

> PHP version `^8.1`
Expand Down
80 changes: 54 additions & 26 deletions docs/Class_Synopsis.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ abstract class WebSocket\Message\Message imlements Stringable

class WebSocket\Client imlements WebSocket\Runtime\IdentityInterface, Psr\Log\LoggerAwareInterface, Stringable
{
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\ListenerTrait;
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\SendMethodsTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(Psr\Http\Message\UriInterface|string $uri);
public method __construct(Psr\Http\Message\UriInterface|string $uri, WebSocket\Configuration|null $configuration = null);
public method __toString(): string;
public method addHeader(string $name, string $content): self;
public method addMiddleware(WebSocket\Middleware\MiddlewareInterface $middleware): self;
Expand Down Expand Up @@ -65,13 +65,33 @@ class WebSocket\Client imlements WebSocket\Runtime\IdentityInterface, Psr\Log\Lo
public method stop(): void;
}

class WebSocket\Configuration imlements Psr\Log\LoggerAwareInterface, Stringable
{
use WebSocket\Trait\StringableTrait;

public method __construct(Psr\Log\LoggerInterface|null $logger = null, Phrity\Net\Context|null $context = null, int|float|null $timeout = null, int|null $frameSize = null, bool|null $persistent = null, int|null $maxConnections = null);
public method __toString(): string;
public method getContext(): Phrity\Net\Context;
public method getFrameSize(): int;
public method getLogger(): Psr\Log\LoggerInterface;
public method getMaxConnections(): int|null;
public method getTimeout(): int|float;
public method isPersistent(): bool;
public method setContext(Phrity\Net\Context $context): void;
public method setFrameSize(int $frameSize): void;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
public method setMaxConnections(int|null $maxConnections): void;
public method setPersistent(bool $persistent): void;
public method setTimeout(int|float $timeout): void;
}

class WebSocket\Connection imlements WebSocket\Runtime\IdentityInterface, Psr\Log\LoggerAwareInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\SendMethodsTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(Phrity\Net\SocketStream $stream, bool $pushMasked, bool $pullMaskedRequired, bool $ssl = false, Phrity\Http\HttpFactory|null $httpFactory = null);
public method __construct(Phrity\Net\SocketStream $stream, bool $pushMasked, bool $pullMaskedRequired, bool $ssl = false, Phrity\Http\HttpFactory|null $httpFactory = null, WebSocket\Configuration|null $configuration = null);
public method __destruct();
public method __toString(): string;
public method addMiddleware(WebSocket\Middleware\MiddlewareInterface $middleware): self;
Expand Down Expand Up @@ -174,13 +194,14 @@ class WebSocket\Frame\Frame imlements Stringable

class WebSocket\Frame\FrameHandler imlements Psr\Log\LoggerAwareInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\OpcodeTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(Phrity\Net\SocketStream $stream, bool $pushMasked, bool $pullMaskedRequired);
public method __construct(Phrity\Net\SocketStream $stream, bool $pushMasked, bool $pullMaskedRequired, WebSocket\Configuration|null $configuration = null);
public method pull(): WebSocket\Frame\Frame;
public method push(WebSocket\Frame\Frame $frame): int;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

class WebSocket\Http\DefaultHttpFactory extends Phrity\Http\HttpFactory
Expand Down Expand Up @@ -234,10 +255,10 @@ class WebSocket\Message\Close extends WebSocket\Message\Message

class WebSocket\Message\MessageHandler imlements Psr\Log\LoggerAwareInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(WebSocket\Frame\FrameHandler $frameHandler);
public method __construct(WebSocket\Frame\FrameHandler $frameHandler, WebSocket\Configuration|null $configuration = null);
public method pull(): WebSocket\Message\Message;
public method push(WebSocket\Message\Message $message, int $size = WebSocket\Message\MessageHandler::DEFAULT_SIZE): WebSocket\Message\Message;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
Expand All @@ -259,7 +280,7 @@ class WebSocket\Message\Text extends WebSocket\Message\Message

class WebSocket\Middleware\Callback imlements Psr\Log\LoggerAwareInterface, WebSocket\Middleware\ProcessHttpIncomingInterface, WebSocket\Middleware\ProcessHttpOutgoingInterface, WebSocket\Middleware\ProcessIncomingInterface, WebSocket\Middleware\ProcessOutgoingInterface, WebSocket\Middleware\ProcessTickInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(Closure|null $incoming = null, Closure|null $outgoing = null, Closure|null $httpIncoming = null, Closure|null $httpOutgoing = null, Closure|null $tick = null);
Expand All @@ -268,28 +289,31 @@ class WebSocket\Middleware\Callback imlements Psr\Log\LoggerAwareInterface, WebS
public method processIncoming(WebSocket\Middleware\ProcessStack $stack, WebSocket\Connection $connection): WebSocket\Message\Message;
public method processOutgoing(WebSocket\Middleware\ProcessStack $stack, WebSocket\Connection $connection, WebSocket\Message\Message $message): WebSocket\Message\Message;
public method processTick(WebSocket\Middleware\ProcessTickStack $stack, WebSocket\Connection $connection): void;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

class WebSocket\Middleware\CloseHandler imlements Psr\Log\LoggerAwareInterface, WebSocket\Middleware\ProcessIncomingInterface, WebSocket\Middleware\ProcessOutgoingInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct();
public method processIncoming(WebSocket\Middleware\ProcessStack $stack, WebSocket\Connection $connection): WebSocket\Message\Message;
public method processOutgoing(WebSocket\Middleware\ProcessStack $stack, WebSocket\Connection $connection, WebSocket\Message\Message $message): WebSocket\Message\Message;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

class WebSocket\Middleware\CompressionExtension imlements Psr\Log\LoggerAwareInterface, WebSocket\Middleware\ProcessHttpOutgoingInterface, WebSocket\Middleware\ProcessHttpIncomingInterface, WebSocket\Middleware\ProcessIncomingInterface, WebSocket\Middleware\ProcessOutgoingInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(WebSocket\Middleware\CompressionExtension\CompressorInterface $compressors);
public method processHttpIncoming(WebSocket\Middleware\ProcessHttpStack $stack, WebSocket\Connection $connection): Psr\Http\Message\MessageInterface;
public method processHttpOutgoing(WebSocket\Middleware\ProcessHttpStack $stack, WebSocket\Connection $connection, Psr\Http\Message\MessageInterface $message): Psr\Http\Message\MessageInterface;
public method processIncoming(WebSocket\Middleware\ProcessStack $stack, WebSocket\Connection $connection): WebSocket\Message\Message;
public method processOutgoing(WebSocket\Middleware\ProcessStack $stack, WebSocket\Connection $connection, WebSocket\Message\Message $message): WebSocket\Message\Message;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

class WebSocket\Middleware\CompressionExtension\DeflateCompressor imlements WebSocket\Middleware\CompressionExtension\CompressorInterface, Stringable
Expand All @@ -307,19 +331,20 @@ class WebSocket\Middleware\CompressionExtension\DeflateCompressor imlements WebS

class WebSocket\Middleware\FollowRedirect imlements Psr\Log\LoggerAwareInterface, WebSocket\Middleware\ProcessHttpIncomingInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(int $limit = 10);
public method processHttpIncoming(WebSocket\Middleware\ProcessHttpStack $stack, WebSocket\Connection $connection): Psr\Http\Message\MessageInterface;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

class WebSocket\Middleware\MiddlewareHandler imlements Psr\Log\LoggerAwareInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(WebSocket\Message\MessageHandler $messageHandler, WebSocket\Http\HttpHandler $httpHandler);
public method __construct(WebSocket\Message\MessageHandler $messageHandler, WebSocket\Http\HttpHandler $httpHandler, WebSocket\Configuration|null $configuration = null);
public method add(WebSocket\Middleware\MiddlewareInterface $middleware): self;
public method processHttpIncoming(WebSocket\Connection $connection): Psr\Http\Message\MessageInterface;
public method processHttpOutgoing(WebSocket\Connection $connection, Psr\Http\Message\MessageInterface $message): Psr\Http\Message\MessageInterface;
Expand All @@ -331,21 +356,23 @@ class WebSocket\Middleware\MiddlewareHandler imlements Psr\Log\LoggerAwareInterf

class WebSocket\Middleware\PingInterval imlements Psr\Log\LoggerAwareInterface, WebSocket\Middleware\ProcessOutgoingInterface, WebSocket\Middleware\ProcessTickInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(int|float|null $interval = null);
public method processOutgoing(WebSocket\Middleware\ProcessStack $stack, WebSocket\Connection $connection, WebSocket\Message\Message $message): WebSocket\Message\Message;
public method processTick(WebSocket\Middleware\ProcessTickStack $stack, WebSocket\Connection $connection): void;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

class WebSocket\Middleware\PingResponder imlements Psr\Log\LoggerAwareInterface, WebSocket\Middleware\ProcessIncomingInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct();
public method processIncoming(WebSocket\Middleware\ProcessStack $stack, WebSocket\Connection $connection): WebSocket\Message\Message;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

class WebSocket\Middleware\ProcessHttpStack imlements Stringable
Expand Down Expand Up @@ -376,22 +403,23 @@ class WebSocket\Middleware\ProcessTickStack imlements Stringable

class WebSocket\Middleware\SubprotocolNegotiation imlements Psr\Log\LoggerAwareInterface, WebSocket\Middleware\ProcessHttpOutgoingInterface, WebSocket\Middleware\ProcessHttpIncomingInterface, Stringable
{
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(array $subprotocols, bool $require = false);
public method processHttpIncoming(WebSocket\Middleware\ProcessHttpStack $stack, WebSocket\Connection $connection): Psr\Http\Message\MessageInterface;
public method processHttpOutgoing(WebSocket\Middleware\ProcessHttpStack $stack, WebSocket\Connection $connection, Psr\Http\Message\MessageInterface $message): Psr\Http\Message\MessageInterface;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

class WebSocket\Server imlements WebSocket\Runtime\IdentityInterface, Psr\Log\LoggerAwareInterface, Stringable
{
use WebSocket\Trait\ConfigurationTrait;
use WebSocket\Trait\ListenerTrait;
use WebSocket\Trait\LoggerAwareTrait;
use WebSocket\Trait\SendMethodsTrait;
use WebSocket\Trait\StringableTrait;

public method __construct(int $port = 80, bool $ssl = false);
public method __construct(int $port = 80, bool $ssl = false, WebSocket\Configuration|null $configuration = null);
public method __toString(): string;
public method addMiddleware(WebSocket\Middleware\MiddlewareInterface $middleware): self;
public method disconnect(): void;
Expand Down Expand Up @@ -482,6 +510,13 @@ inteface WebSocket\Runtime\IdentityInterface
public method getIdentity(): string;
}

trait WebSocket\Trait\ConfigurationTrait
{
public method getConfiguration(): WebSocket\Configuration;
public method initConfiguration(WebSocket\Configuration|null $configuration = null): self;
public method setConfiguration(WebSocket\Configuration $configuration): self;
}

trait WebSocket\Trait\ListenerTrait
{
public method onBinary(Closure $closure): self;
Expand All @@ -496,13 +531,6 @@ trait WebSocket\Trait\ListenerTrait
public method onTick(Closure $closure): self;
}

trait WebSocket\Trait\LoggerAwareTrait
{
public method attachLogger(mixed $instance): void;
public method initLogger(Psr\Log\LoggerInterface|null $logger = null): void;
public method setLogger(Psr\Log\LoggerInterface $logger): void;
}

trait WebSocket\Trait\OpcodeTrait
{
}
Expand Down
112 changes: 33 additions & 79 deletions docs/Client.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,33 @@

The client can read and write on a WebSocket stream.


## Subscribe operation

If you want to subscribe to messages sent by server at any point, use the listener functions.

```php
$client = new WebSocket\Client("wss://echo.websocket.org/");
$client
// Add standard middlewares
->addMiddleware(new WebSocket\Middleware\CloseHandler())
->addMiddleware(new WebSocket\Middleware\PingResponder())
// Listen to incoming Text messages
->onText(function (WebSocket\Client $client, WebSocket\Connection $connection, WebSocket\Message\Message $message) {
// Act on incoming message
echo "Got message: {$message->getContent()} \n";
// Possibly respond to server
$client->text("I got your your message");
})
->start();
```
Optionally, `start()` can take timeout argument as int or float.


## Basic operation

Set up a WebSocket client for request/response strategy.
Manually pulling messages using `receive()` method is not recommended.

```php
$client = new WebSocket\Client("wss://echo.websocket.org/");
Expand All @@ -27,26 +51,6 @@ echo "Got message: {$message->getContent()} \n";
$client->close();
```

## Subscribe operation

If you want to subscribe to messages sent by server at any point, use the listener functions.

```php
$client = new WebSocket\Client("wss://echo.websocket.org/");
$client
// Add standard middlewares
->addMiddleware(new WebSocket\Middleware\CloseHandler())
->addMiddleware(new WebSocket\Middleware\PingResponder())
// Listen to incoming Text messages
->onText(function (WebSocket\Client $client, WebSocket\Connection $connection, WebSocket\Message\Message $message) {
// Act on incoming message
echo "Got message: {$message->getContent()} \n";
// Possibly respond to server
$client->text("I got your your message");
})
->start();
```
Optionally, `start()` can take timeout argument as int or float.

## Middlewares

Expand Down Expand Up @@ -137,71 +141,21 @@ $client->close(1000, "Closing now");

The Client takes one argument: [URI](http://tools.ietf.org/html/rfc3986) as a class implementing [UriInterface](https://www.php-fig.org/psr/psr-7/#35-psrhttpmessageuriinterface) or as string.
The client support `ws` (`tcp`) and `wss` (`ssl`) schemas, depending on SSL configuration.
Other options are available runtime by calling configuration methods.

### Logger

Client support adding any [PSR-4 compatible](https://www.php-fig.org/psr/psr-3/) logger.

```php
$client->setLogger(Psr\Log\LoggerInterface $logger);
```

### Timeout

Timeout for various operations can be specified in seconds.
This affects how long Client will wait for connection, read and write operations, and listener scope.
Default is `60` seconds. Minimum is `0` seconds. Accepts int or float value.
Avoid setting very low values as it will cause a read loop to use all
available processing power even when there's nothing to read.
Other options are available using the Configuration class.

```php
$client->setTimeout(300); // set timeout in seconds
$client->getTimeout(); // => current timeout in seconds
```

### Frame size

Defines the maximum payload per frame size in bytes.
Default is `4096` bytes. Minimum is `1` byte.
Do not change unless you have a strong reason to do so.

```php
$client->setFrameSize(1024); // set maximum payload frame size in bytes
$client->getFrameSize(); // => current maximum payload frame size in bytes
```

### Persistent connection
- Logger
- Context
- Timeout
- Frame size
- Persistency

If set to true, the underlying connection will be kept open if possible.
This means that if Client closes and is then restarted, it may use the same connection.
Do not change unless you have a strong reason to do so.

```php
$client->setPersistent(true);
```

### Context

Client support adding [context options and parameters](https://www.php.net/manual/en/context.php)
using the [Phrity\Net\Context](https://github.com/sirn-se/phrity-net-stream?tab=readme-ov-file#context-class) class.

```php
$context = new Phrity\Net\Context();
$context->setOptions([
"ssl" => [
"verify_peer" => false,
"verify_peer_name" => false,
],
]);
$client->setContext($context); // set context
$client->getContext(); // => currently used Phrity\Net\Context
```
Read more on [Configuration](Configuration.md).

### HTTP factories

By default the Client uses a minimal [PSR-7 HTTP message](https://www.php-fig.org/psr/psr-7/) implementation.
Other (more complete) implementations can be used by setting [PSR-17 HTTP factories](https://www.php-fig.org/psr/psr-17/) on the Client.
By default the Client wraps a [PSR-7 HTTP message](https://www.php-fig.org/psr/psr-7/) implementation.
Other implementations can be used by setting [PSR-17 HTTP factories](https://www.php-fig.org/psr/psr-17/) on the Client.

Set a configured HttpFactory class on the Client.
```php
Expand Down
Loading