Commit inicial con archivos existentes
This commit is contained in:
19
vendor/ratchet/pawl/LICENSE
vendored
Executable file
19
vendor/ratchet/pawl/LICENSE
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2014 Chris Boden
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
84
vendor/ratchet/pawl/README.md
vendored
Executable file
84
vendor/ratchet/pawl/README.md
vendored
Executable file
@@ -0,0 +1,84 @@
|
||||
# Pawl
|
||||
|
||||
[](http://socketo.me/reports/pawl/index.html)
|
||||
[](https://github.com/ratchetphp/Pawl/actions)
|
||||
|
||||
An asynchronous WebSocket client in PHP
|
||||
|
||||
#### Install via composer:
|
||||
composer require ratchet/pawl
|
||||
|
||||
#### Usage
|
||||
Pawl as a standalone app: Connect to an echo server, send a message, display output, close connection:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
\Ratchet\Client\connect('wss://echo.websocket.org:443')->then(function($conn) {
|
||||
$conn->on('message', function($msg) use ($conn) {
|
||||
echo "Received: {$msg}\n";
|
||||
$conn->close();
|
||||
});
|
||||
|
||||
$conn->send('Hello World!');
|
||||
}, function ($e) {
|
||||
echo "Could not connect: {$e->getMessage()}\n";
|
||||
});
|
||||
```
|
||||
|
||||
#### Classes
|
||||
|
||||
There are 3 primary classes to be aware of and use in Pawl:
|
||||
|
||||
##### Connector:
|
||||
|
||||
Makes HTTP requests to servers returning a promise that, if successful, will resolve to a WebSocket object.
|
||||
A connector is configured via its constructor and a request is made by invoking the class. Multiple connections can be established through a single connector. The invoke mehtod has 3 parameters:
|
||||
* **$url**: String; A valid uri string (starting with ws:// or wss://) to connect to (also accepts PSR-7 Uri object)
|
||||
* **$subProtocols**: Array; An optional indexed array of WebSocket sub-protocols to negotiate to the server with. The connection will fail if the client and server can not agree on one if any are provided
|
||||
* **$headers**: Array; An optional associative array of additional headers requests to use when initiating the handshake. A common header to set is `Origin`
|
||||
|
||||
##### WebSocket:
|
||||
|
||||
This is the object used to interact with a WebSocket server. It has two methods: `send` and `close`.
|
||||
It has two public properties: `request` and `response` which are PSR-7 objects representing the client and server side HTTP handshake headers used to establish the WebSocket connection.
|
||||
|
||||
##### Message:
|
||||
|
||||
This is the object received from a WebSocket server. It has a `__toString` method which is how most times you will want to access the data received.
|
||||
If you need to do binary messaging you will most likely need to use methods on the object.
|
||||
|
||||
#### Example
|
||||
|
||||
A more in-depth example using explicit interfaces: Requesting sub-protocols, and sending custom headers while using a specific React Event Loop:
|
||||
```php
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
$reactConnector = new \React\Socket\Connector([
|
||||
'dns' => '8.8.8.8',
|
||||
'timeout' => 10
|
||||
]);
|
||||
$loop = \React\EventLoop\Loop::get();
|
||||
$connector = new \Ratchet\Client\Connector($loop, $reactConnector);
|
||||
|
||||
$connector('ws://127.0.0.1:9000', ['protocol1', 'subprotocol2'], ['Origin' => 'http://localhost'])
|
||||
->then(function(\Ratchet\Client\WebSocket $conn) {
|
||||
$conn->on('message', function(\Ratchet\RFC6455\Messaging\MessageInterface $msg) use ($conn) {
|
||||
echo "Received: {$msg}\n";
|
||||
$conn->close();
|
||||
});
|
||||
|
||||
$conn->on('close', function($code = null, $reason = null) {
|
||||
echo "Connection closed ({$code} - {$reason})\n";
|
||||
});
|
||||
|
||||
$conn->send('Hello World!');
|
||||
}, function(\Exception $e) use ($loop) {
|
||||
echo "Could not connect: {$e->getMessage()}\n";
|
||||
$loop->stop();
|
||||
});
|
||||
```
|
||||
25
vendor/ratchet/pawl/composer.json
vendored
Executable file
25
vendor/ratchet/pawl/composer.json
vendored
Executable file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "ratchet/pawl"
|
||||
, "description": "Asynchronous WebSocket client"
|
||||
, "keywords": ["WebSocket", "client", "Ratchet", "async", "websocket client"]
|
||||
, "license": "MIT"
|
||||
, "autoload": {
|
||||
"psr-4": {
|
||||
"Ratchet\\Client\\": "src"
|
||||
}
|
||||
, "files": ["src/functions_include.php"]
|
||||
}
|
||||
, "require": {
|
||||
"php": ">=7.4"
|
||||
, "evenement/evenement": "^3.0 || ^2.0"
|
||||
, "guzzlehttp/psr7": "^2.0"
|
||||
, "ratchet/rfc6455": "^0.3.1 || ^0.4.0"
|
||||
, "react/socket": "^1.9"
|
||||
}
|
||||
, "require-dev": {
|
||||
"phpunit/phpunit": "^9.3 || ^5.7 || ^4.8"
|
||||
}
|
||||
, "suggest": {
|
||||
"reactivex/rxphp": "~2.0"
|
||||
}
|
||||
}
|
||||
158
vendor/ratchet/pawl/src/Connector.php
vendored
Executable file
158
vendor/ratchet/pawl/src/Connector.php
vendored
Executable file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
namespace Ratchet\Client;
|
||||
use Ratchet\RFC6455\Handshake\ClientNegotiator;
|
||||
use React\EventLoop\Loop;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\Socket\ConnectionInterface;
|
||||
use React\Socket\ConnectorInterface;
|
||||
use React\Promise\Deferred;
|
||||
use function React\Promise\reject;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use GuzzleHttp\Psr7 as gPsr;
|
||||
|
||||
class Connector {
|
||||
protected $_loop;
|
||||
protected $_connector;
|
||||
protected $_negotiator;
|
||||
|
||||
public function __construct(?LoopInterface $loop = null, ?ConnectorInterface $connector = null) {
|
||||
$this->_loop = $loop ?: Loop::get();
|
||||
|
||||
if (null === $connector) {
|
||||
$connector = new \React\Socket\Connector([
|
||||
'timeout' => 20
|
||||
], $this->_loop);
|
||||
}
|
||||
|
||||
$this->_connector = $connector;
|
||||
$this->_negotiator = new ClientNegotiator(new gPsr\HttpFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param array $subProtocols
|
||||
* @param array $headers
|
||||
* @return \React\Promise\PromiseInterface
|
||||
*/
|
||||
public function __invoke($url, array $subProtocols = [], array $headers = []) {
|
||||
try {
|
||||
$request = $this->generateRequest($url, $subProtocols, $headers);
|
||||
$uri = $request->getUri();
|
||||
} catch (\Exception $e) {
|
||||
return reject($e);
|
||||
}
|
||||
$secure = 'wss' === substr($url, 0, 3);
|
||||
$connector = $this->_connector;
|
||||
|
||||
$port = $uri->getPort() ?: ($secure ? 443 : 80);
|
||||
|
||||
$scheme = $secure ? 'tls' : 'tcp';
|
||||
|
||||
$uriString = $scheme . '://' . $uri->getHost() . ':' . $port;
|
||||
|
||||
$connecting = $connector->connect($uriString);
|
||||
|
||||
$futureWsConn = new Deferred(function ($_, $reject) use ($url, $connecting) {
|
||||
$reject(new \RuntimeException(
|
||||
'Connection to ' . $url . ' cancelled during handshake'
|
||||
));
|
||||
|
||||
// either close active connection or cancel pending connection attempt
|
||||
$connecting->then(function (ConnectionInterface $connection) {
|
||||
$connection->close();
|
||||
});
|
||||
$connecting->cancel();
|
||||
});
|
||||
|
||||
$connecting->then(function(ConnectionInterface $conn) use ($request, $subProtocols, $futureWsConn) {
|
||||
$earlyClose = function() use ($futureWsConn) {
|
||||
$futureWsConn->reject(new \RuntimeException('Connection closed before handshake'));
|
||||
};
|
||||
|
||||
$stream = $conn;
|
||||
|
||||
$stream->on('close', $earlyClose);
|
||||
$futureWsConn->promise()->then(function() use ($stream, $earlyClose) {
|
||||
$stream->removeListener('close', $earlyClose);
|
||||
}, function (\Exception $exception) use ($futureWsConn) {
|
||||
$futureWsConn->reject($exception);
|
||||
});
|
||||
|
||||
$buffer = '';
|
||||
$headerParser = function($data) use ($stream, &$headerParser, &$buffer, $futureWsConn, $request, $subProtocols) {
|
||||
$buffer .= $data;
|
||||
if (false == strpos($buffer, "\r\n\r\n")) {
|
||||
return;
|
||||
}
|
||||
|
||||
$stream->removeListener('data', $headerParser);
|
||||
|
||||
$response = gPsr\Message::parseResponse($buffer);
|
||||
|
||||
if (!$this->_negotiator->validateResponse($request, $response)) {
|
||||
$futureWsConn->reject(new \DomainException(gPsr\Message::toString($response)));
|
||||
$stream->close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$acceptedProtocol = $response->getHeader('Sec-WebSocket-Protocol');
|
||||
if ((count($subProtocols) > 0) && 1 !== count(array_intersect($subProtocols, $acceptedProtocol))) {
|
||||
$futureWsConn->reject(new \DomainException('Server did not respond with an expected Sec-WebSocket-Protocol'));
|
||||
$stream->close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$futureWsConn->resolve(new WebSocket($stream, $response, $request));
|
||||
|
||||
$futureWsConn->promise()->then(function(WebSocket $conn) use ($stream) {
|
||||
$stream->emit('data', [$conn->response->getBody()->getContents(), $stream]);
|
||||
});
|
||||
};
|
||||
|
||||
$stream->on('data', $headerParser);
|
||||
$stream->write(gPsr\Message::toString($request));
|
||||
}, array($futureWsConn, 'reject'));
|
||||
|
||||
return $futureWsConn->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param array $subProtocols
|
||||
* @param array $headers
|
||||
* @throws \InvalidArgumentException
|
||||
* @return \Psr\Http\Message\RequestInterface
|
||||
*/
|
||||
protected function generateRequest($url, array $subProtocols, array $headers) {
|
||||
$uri = gPsr\Utils::uriFor($url);
|
||||
|
||||
$scheme = $uri->getScheme();
|
||||
|
||||
if (!in_array($scheme, ['ws', 'wss'])) {
|
||||
throw new \InvalidArgumentException(sprintf('Cannot connect to invalid URL (%s)', $url));
|
||||
}
|
||||
|
||||
$uri = $uri->withScheme('wss' === $scheme ? 'HTTPS' : 'HTTP');
|
||||
|
||||
$headers += ['User-Agent' => 'Ratchet-Pawl/0.4.1'];
|
||||
|
||||
$request = array_reduce(array_keys($headers), function(RequestInterface $request, $header) use ($headers) {
|
||||
return $request->withHeader($header, $headers[$header]);
|
||||
}, $this->_negotiator->generateRequest($uri));
|
||||
|
||||
if (!$request->getHeader('Origin')) {
|
||||
$request = $request->withHeader('Origin', str_replace('ws', 'http', $scheme) . '://' . $uri->getHost());
|
||||
}
|
||||
|
||||
if (count($subProtocols) > 0) {
|
||||
$protocols = implode(',', $subProtocols);
|
||||
if ($protocols != "") {
|
||||
$request = $request->withHeader('Sec-WebSocket-Protocol', $protocols);
|
||||
}
|
||||
}
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
157
vendor/ratchet/pawl/src/WebSocket.php
vendored
Executable file
157
vendor/ratchet/pawl/src/WebSocket.php
vendored
Executable file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
namespace Ratchet\Client;
|
||||
use Evenement\EventEmitterTrait;
|
||||
use Evenement\EventEmitterInterface;
|
||||
use React\Socket\ConnectionInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Ratchet\RFC6455\Messaging\MessageBuffer;
|
||||
use Ratchet\RFC6455\Messaging\CloseFrameChecker;
|
||||
use Ratchet\RFC6455\Messaging\MessageInterface;
|
||||
use Ratchet\RFC6455\Messaging\FrameInterface;
|
||||
use Ratchet\RFC6455\Messaging\Frame;
|
||||
|
||||
class WebSocket implements EventEmitterInterface {
|
||||
use EventEmitterTrait;
|
||||
|
||||
/**
|
||||
* The request headers sent to establish the connection
|
||||
* @var \Psr\Http\Message\RequestInterface
|
||||
*/
|
||||
public $request;
|
||||
|
||||
/**
|
||||
* The response headers received from the server to establish the connection
|
||||
* @var \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public $response;
|
||||
|
||||
/**
|
||||
* @var \React\Socket\ConnectionInterface
|
||||
*/
|
||||
protected $_stream;
|
||||
|
||||
/**
|
||||
* @var \Closure
|
||||
*/
|
||||
protected $_close;
|
||||
|
||||
/**
|
||||
* WebSocket constructor.
|
||||
* @param \React\Socket\ConnectionInterface $stream
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* @param \Psr\Http\Message\RequestInterface $request
|
||||
* @event message
|
||||
* @event ping
|
||||
* @event pong
|
||||
* @event close
|
||||
* @event error
|
||||
*/
|
||||
public function __construct(ConnectionInterface $stream, ResponseInterface $response, RequestInterface $request) {
|
||||
$this->_stream = $stream;
|
||||
$this->response = $response;
|
||||
$this->request = $request;
|
||||
|
||||
$self = $this;
|
||||
$this->_close = function($code = null, $reason = null) use ($self) {
|
||||
static $sent = false;
|
||||
|
||||
if ($sent) {
|
||||
return;
|
||||
}
|
||||
$sent = true;
|
||||
|
||||
$self->emit('close', [$code, $reason, $self]);
|
||||
};
|
||||
|
||||
$reusableUAException = new \UnderflowException;
|
||||
|
||||
$streamer = new MessageBuffer(
|
||||
new CloseFrameChecker,
|
||||
function(MessageInterface $msg) {
|
||||
$this->emit('message', [$msg, $this]);
|
||||
},
|
||||
function(FrameInterface $frame) use (&$streamer) {
|
||||
switch ($frame->getOpcode()) {
|
||||
case Frame::OP_CLOSE:
|
||||
$frameContents = $frame->getPayload();
|
||||
|
||||
$reason = '';
|
||||
$code = unpack('n', substr($frameContents, 0, 2));
|
||||
$code = reset($code);
|
||||
|
||||
if (($frameLen = strlen($frameContents)) > 2) {
|
||||
$reason = substr($frameContents, 2, $frameLen);
|
||||
}
|
||||
|
||||
$closeFn = $this->_close;
|
||||
$closeFn($code, $reason);
|
||||
|
||||
return $this->_stream->end($streamer->newFrame($frame->getPayload(), true, Frame::OP_CLOSE)->maskPayload()->getContents());
|
||||
case Frame::OP_PING:
|
||||
$this->emit('ping', [$frame, $this]);
|
||||
return $this->send($streamer->newFrame($frame->getPayload(), true, Frame::OP_PONG));
|
||||
case Frame::OP_PONG:
|
||||
return $this->emit('pong', [$frame, $this]);
|
||||
default:
|
||||
return $this->close(Frame::CLOSE_PROTOCOL);
|
||||
}
|
||||
},
|
||||
false,
|
||||
function() use ($reusableUAException) {
|
||||
return $reusableUAException;
|
||||
}
|
||||
);
|
||||
|
||||
$stream->on('data', [$streamer, 'onData']);
|
||||
|
||||
$stream->on('close', function () {
|
||||
$close = $this->_close;
|
||||
$close(Frame::CLOSE_ABNORMAL, 'Underlying connection closed');
|
||||
});
|
||||
|
||||
$stream->on('error', function($error) {
|
||||
$this->emit('error', [$error, $this]);
|
||||
});
|
||||
|
||||
$stream->on('drain', function () {
|
||||
$this->emit('drain');
|
||||
});
|
||||
}
|
||||
|
||||
public function send($msg) {
|
||||
if ($msg instanceof MessageInterface) {
|
||||
foreach ($msg as $frame) {
|
||||
$frame->maskPayload();
|
||||
}
|
||||
} else {
|
||||
if (!($msg instanceof Frame)) {
|
||||
$msg = new Frame($msg);
|
||||
}
|
||||
$msg->maskPayload();
|
||||
}
|
||||
|
||||
return $this->_stream->write($msg->getContents());
|
||||
}
|
||||
|
||||
public function close($code = 1000, $reason = '') {
|
||||
$frame = new Frame(pack('n', $code) . $reason, true, Frame::OP_CLOSE);
|
||||
$frame->maskPayload();
|
||||
$this->_stream->write($frame->getContents());
|
||||
|
||||
$closeFn = $this->_close;
|
||||
$closeFn($code, $reason);
|
||||
|
||||
$this->_stream->end();
|
||||
}
|
||||
|
||||
public function pause()
|
||||
{
|
||||
$this->_stream->pause();
|
||||
}
|
||||
|
||||
public function resume()
|
||||
{
|
||||
$this->_stream->resume();
|
||||
}
|
||||
}
|
||||
17
vendor/ratchet/pawl/src/functions.php
vendored
Executable file
17
vendor/ratchet/pawl/src/functions.php
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace Ratchet\Client;
|
||||
use React\EventLoop\LoopInterface;
|
||||
|
||||
/**
|
||||
* @param string $url
|
||||
* @param array $subProtocols
|
||||
* @param array $headers
|
||||
* @param LoopInterface|null $loop
|
||||
* @return \React\Promise\PromiseInterface<\Ratchet\Client\WebSocket>
|
||||
*/
|
||||
function connect($url, array $subProtocols = [], $headers = [], ?LoopInterface $loop = null) {
|
||||
$connector = new Connector($loop);
|
||||
$connection = $connector($url, $subProtocols, $headers);
|
||||
|
||||
return $connection;
|
||||
}
|
||||
5
vendor/ratchet/pawl/src/functions_include.php
vendored
Executable file
5
vendor/ratchet/pawl/src/functions_include.php
vendored
Executable file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
if (!function_exists('Ratchet\Client\connect')) {
|
||||
require __DIR__ . '/functions.php';
|
||||
}
|
||||
Reference in New Issue
Block a user