init
This commit is contained in:
4
vendor/valga/fbns-react/.gitignore
vendored
Executable file
4
vendor/valga/fbns-react/.gitignore
vendored
Executable file
@@ -0,0 +1,4 @@
|
||||
/.idea/
|
||||
/vendor/
|
||||
/composer.lock
|
||||
/.php_cs.cache
|
||||
20
vendor/valga/fbns-react/.php_cs
vendored
Executable file
20
vendor/valga/fbns-react/.php_cs
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
return \PhpCsFixer\Config::create()
|
||||
->setFinder(
|
||||
\PhpCsFixer\Finder::create()
|
||||
->in('src')
|
||||
)
|
||||
->setRules([
|
||||
'@Symfony' => true,
|
||||
// Override @Symfony rules
|
||||
'pre_increment' => false,
|
||||
'blank_line_before_statement' => ['statements' => ['return']],
|
||||
'phpdoc_align' => ['tags' => ['param', 'throws']],
|
||||
'phpdoc_annotation_without_dot' => false,
|
||||
// Custom rules
|
||||
'phpdoc_add_missing_param_annotation' => ['only_untyped' => false],
|
||||
'ordered_imports' => true,
|
||||
'phpdoc_order' => true,
|
||||
'array_syntax' => ['syntax' => 'short'],
|
||||
]);
|
||||
21
vendor/valga/fbns-react/LICENSE
vendored
Executable file
21
vendor/valga/fbns-react/LICENSE
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Abyr Valg <valga.github@abyrga.ru>
|
||||
|
||||
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/valga/fbns-react/README.md
vendored
Executable file
84
vendor/valga/fbns-react/README.md
vendored
Executable file
@@ -0,0 +1,84 @@
|
||||
# fbns-react
|
||||
|
||||
A PHP client for the FBNS built on top of ReactPHP.
|
||||
|
||||
## Requirements
|
||||
|
||||
You need to install the [GMP extension](http://php.net/manual/en/book.gmp.php) to be able to run this code on x86 PHP builds.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
composer require valga/fbns-react
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```php
|
||||
// Set up a FBNS client.
|
||||
$loop = \React\EventLoop\Factory::create();
|
||||
$client = new \Fbns\Client\Lite($loop);
|
||||
|
||||
// Read saved credentials from a storage.
|
||||
$auth = new \Fbns\Client\Auth\DeviceAuth();
|
||||
try {
|
||||
$auth->read($storage->get('fbns_auth'));
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
// Connect to a broker.
|
||||
$connection = new \Fbns\Client\Connection($deviceAuth, USER_AGENT);
|
||||
$client->connect(HOSTNAME, PORT, $connection);
|
||||
|
||||
// Bind events.
|
||||
$client
|
||||
->on('connect', function (\Fbns\Client\Lite\ConnectResponsePacket $responsePacket) use ($client, $auth, $storage) {
|
||||
// Update credentials and save them to a storage for future use.
|
||||
try {
|
||||
$auth->read($responsePacket->getAuth());
|
||||
$storage->set('fbns_auth', $responsePacket->getAuth());
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
// Register an application.
|
||||
$client->register(PACKAGE_NAME, APPLICATION_ID);
|
||||
})
|
||||
->on('register', function (\Fbns\Client\Message\Register $message) use ($app) {
|
||||
// Register received token with an application.
|
||||
$app->registerPushToken($message->getToken());
|
||||
})
|
||||
->on('push', function (\Fbns\Client\Message\Push $message) use ($app) {
|
||||
// Handle received notification payload.
|
||||
$app->handlePushNotification($message->getPayload());
|
||||
});
|
||||
|
||||
// Run main loop.
|
||||
$loop->run();
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
```php
|
||||
// Set up a proxy.
|
||||
$connector = new \React\Socket\Connector($loop);
|
||||
$proxy = new \Clue\React\HttpProxy('username:password@127.0.0.1:3128', $connector);
|
||||
|
||||
// Disable SSL verification.
|
||||
$ssl = new \React\Socket\SecureConnector($proxy, $loop, ['verify_peer' => false, 'verify_peer_name' => false]);
|
||||
|
||||
// Enable logging to stdout.
|
||||
$logger = new \Monolog\Logger('fbns');
|
||||
$logger->pushHandler(new \Monolog\Handler\StreamHandler('php://stdout', \Monolog\Logger::INFO));
|
||||
|
||||
// Set up a client.
|
||||
$client = new \Fbns\Client\Lite($loop, $ssl, $logger);
|
||||
|
||||
// Persistence.
|
||||
$client->on('disconnect', function () {
|
||||
// Network connection has been closed. You can reestablish it if you want to.
|
||||
});
|
||||
$client->connect(HOSTNAME, PORT, $connection)
|
||||
->otherwise(function () {
|
||||
// Connection attempt was unsuccessful, retry with an exponential backoff.
|
||||
});
|
||||
```
|
||||
33
vendor/valga/fbns-react/bin/thrift_debug
vendored
Executable file
33
vendor/valga/fbns-react/bin/thrift_debug
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
if ($argc > 1) {
|
||||
$data = @file_get_contents($argv[1]);
|
||||
} elseif (!posix_isatty(STDIN)) {
|
||||
$data = @stream_get_contents(STDIN);
|
||||
} else {
|
||||
echo 'Usage: ', $argv[0], ' [FILE]', PHP_EOL;
|
||||
echo 'Dump the contents of Thrift FILE.', PHP_EOL;
|
||||
echo PHP_EOL;
|
||||
echo 'With no FILE read standard input.', PHP_EOL;
|
||||
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if ($data === false) {
|
||||
fwrite(STDERR, 'Failed to read the input.'.PHP_EOL);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
new \Fbns\Client\Thrift\Debug($data);
|
||||
} catch (\Exception $e) {
|
||||
fwrite(STDERR, $e->getMessage().PHP_EOL);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
45
vendor/valga/fbns-react/composer.json
vendored
Executable file
45
vendor/valga/fbns-react/composer.json
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "valga/fbns-react",
|
||||
"description": "A PHP client for the FBNS built on top of ReactPHP",
|
||||
"keywords": [
|
||||
"FBNS",
|
||||
"Client",
|
||||
"PHP"
|
||||
],
|
||||
"type": "library",
|
||||
"minimum-stability": "stable",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Abyr Valg",
|
||||
"email": "valga.github@abyrga.ru"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Fbns\\Client\\": "src/"
|
||||
}
|
||||
},
|
||||
"require": {
|
||||
"php": "~5.6|~7.0",
|
||||
"ext-mbstring": "*",
|
||||
"ext-zlib": "*",
|
||||
"evenement/evenement": "~2.0|~3.0",
|
||||
"react/event-loop": "^0.4.3",
|
||||
"react/promise": "~2.0",
|
||||
"react/socket": "~0.8",
|
||||
"binsoul/net-mqtt": "~0.2",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"monolog/monolog": "~1.23",
|
||||
"friendsofphp/php-cs-fixer": "~2.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-event": "For more efficient event loop implementation.",
|
||||
"ext-gmp": "To be able to run this code on x86 PHP builds."
|
||||
},
|
||||
"scripts": {
|
||||
"codestyle": "php-cs-fixer fix --config=.php_cs"
|
||||
}
|
||||
}
|
||||
162
vendor/valga/fbns-react/src/Auth/DeviceAuth.php
vendored
Executable file
162
vendor/valga/fbns-react/src/Auth/DeviceAuth.php
vendored
Executable file
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client\Auth;
|
||||
|
||||
use Fbns\Client\AuthInterface;
|
||||
use Fbns\Client\Json;
|
||||
|
||||
class DeviceAuth implements AuthInterface
|
||||
{
|
||||
const TYPE = 'device_auth';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $json;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $clientId;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $userId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $password;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $deviceId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $deviceSecret;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function randomUuid()
|
||||
{
|
||||
return sprintf(
|
||||
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0x0fff) | 0x4000,
|
||||
mt_rand(0, 0x3fff) | 0x8000,
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->clientId = substr($this->randomUuid(), 0, 20);
|
||||
$this->userId = 0;
|
||||
$this->password = '';
|
||||
$this->deviceSecret = '';
|
||||
$this->deviceId = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $json
|
||||
*/
|
||||
public function read($json)
|
||||
{
|
||||
$data = Json::decode($json);
|
||||
$this->json = $json;
|
||||
|
||||
if (isset($data->ck)) {
|
||||
$this->userId = $data->ck;
|
||||
} else {
|
||||
$this->userId = 0;
|
||||
}
|
||||
if (isset($data->cs)) {
|
||||
$this->password = $data->cs;
|
||||
} else {
|
||||
$this->password = '';
|
||||
}
|
||||
if (isset($data->di)) {
|
||||
$this->deviceId = $data->di;
|
||||
$this->clientId = substr($this->deviceId, 0, 20);
|
||||
} else {
|
||||
$this->deviceId = '';
|
||||
$this->clientId = substr($this->randomUuid(), 0, 20);
|
||||
}
|
||||
if (isset($data->ds)) {
|
||||
$this->deviceSecret = $data->ds;
|
||||
} else {
|
||||
$this->deviceSecret = '';
|
||||
}
|
||||
|
||||
// TODO: sr ?
|
||||
// TODO: rc ?
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->json !== null ? $this->json : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPassword()
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDeviceId()
|
||||
{
|
||||
return $this->deviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDeviceSecret()
|
||||
{
|
||||
return $this->deviceSecret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClientType()
|
||||
{
|
||||
return self::TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClientId()
|
||||
{
|
||||
return $this->clientId;
|
||||
}
|
||||
}
|
||||
41
vendor/valga/fbns-react/src/AuthInterface.php
vendored
Executable file
41
vendor/valga/fbns-react/src/AuthInterface.php
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client;
|
||||
|
||||
interface AuthInterface
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClientId();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClientType();
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getUserId();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPassword();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDeviceId();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getDeviceSecret();
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
||||
30
vendor/valga/fbns-react/src/Common/PublishAckPacket.php
vendored
Executable file
30
vendor/valga/fbns-react/src/Common/PublishAckPacket.php
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of net-mqtt.
|
||||
*
|
||||
* Copyright (c) 2015 Sebastian Mößler code@binsoul.de
|
||||
*
|
||||
* This source file is subject to the MIT license.
|
||||
*/
|
||||
|
||||
namespace Fbns\Client\Common;
|
||||
|
||||
use BinSoul\Net\Mqtt\Packet\BasePacket;
|
||||
use BinSoul\Net\Mqtt\Packet\PublishAckPacket as BasePublishAckPacket;
|
||||
use BinSoul\Net\Mqtt\PacketStream;
|
||||
|
||||
/**
|
||||
* Represents the PUBACK packet.
|
||||
*/
|
||||
class PublishAckPacket extends BasePublishAckPacket
|
||||
{
|
||||
public function read(PacketStream $stream)
|
||||
{
|
||||
BasePacket::read($stream);
|
||||
//$this->assertPacketFlags($this->getExpectedPacketFlags());
|
||||
$this->assertRemainingPacketLength(2);
|
||||
|
||||
$this->identifier = $stream->readWord();
|
||||
}
|
||||
}
|
||||
339
vendor/valga/fbns-react/src/Connection.php
vendored
Executable file
339
vendor/valga/fbns-react/src/Connection.php
vendored
Executable file
@@ -0,0 +1,339 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client;
|
||||
|
||||
use Fbns\Client\Thrift\Compact;
|
||||
use Fbns\Client\Thrift\Writer;
|
||||
|
||||
class Connection
|
||||
{
|
||||
const FBNS_CLIENT_CAPABILITIES = 439;
|
||||
const FBNS_ENDPOINT_CAPABILITIES = 128;
|
||||
const FBNS_APP_ID = '567310203415052';
|
||||
const FBNS_CLIENT_STACK = 3;
|
||||
const FBNS_PUBLISH_FORMAT = 1;
|
||||
|
||||
const CLIENT_ID = 1;
|
||||
const CLIENT_INFO = 4;
|
||||
const PASSWORD = 5;
|
||||
|
||||
const USER_ID = 1;
|
||||
const USER_AGENT = 2;
|
||||
const CLIENT_CAPABILITIES = 3;
|
||||
const ENDPOINT_CAPABILITIES = 4;
|
||||
const PUBLISH_FORMAT = 5;
|
||||
const NO_AUTOMATIC_FOREGROUND = 6;
|
||||
const MAKE_USER_AVAILABLE_IN_FOREGROUND = 7;
|
||||
const DEVICE_ID = 8;
|
||||
const IS_INITIALLY_FOREGROUND = 9;
|
||||
const NETWORK_TYPE = 10;
|
||||
const NETWORK_SUBTYPE = 11;
|
||||
const CLIENT_MQTT_SESSION_ID = 12;
|
||||
const SUBSCRIBE_TOPICS = 14;
|
||||
const CLIENT_TYPE = 15;
|
||||
const APP_ID = 16;
|
||||
const DEVICE_SECRET = 20;
|
||||
const CLIENT_STACK = 21;
|
||||
|
||||
/** @var AuthInterface */
|
||||
private $auth;
|
||||
|
||||
/** @var string */
|
||||
private $userAgent;
|
||||
/** @var int */
|
||||
private $clientCapabilities;
|
||||
/** @var int */
|
||||
private $endpointCapabilities;
|
||||
/** @var int */
|
||||
private $publishFormat;
|
||||
/** @var bool */
|
||||
private $noAutomaticForeground;
|
||||
/** @var bool */
|
||||
private $makeUserAvailableInForeground;
|
||||
/** @var bool */
|
||||
private $isInitiallyForeground;
|
||||
/** @var int */
|
||||
private $networkType;
|
||||
/** @var int */
|
||||
private $networkSubtype;
|
||||
/** @var int */
|
||||
private $clientMqttSessionId;
|
||||
/** @var int[] */
|
||||
private $subscribeTopics;
|
||||
/** @var int */
|
||||
private $appId;
|
||||
/** @var int */
|
||||
private $clientStack;
|
||||
|
||||
/**
|
||||
* Connection constructor.
|
||||
*
|
||||
* @param AuthInterface $auth
|
||||
* @param string $userAgent
|
||||
*/
|
||||
public function __construct(AuthInterface $auth, $userAgent)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
$this->userAgent = $userAgent;
|
||||
|
||||
$this->clientCapabilities = self::FBNS_CLIENT_CAPABILITIES;
|
||||
$this->endpointCapabilities = self::FBNS_ENDPOINT_CAPABILITIES;
|
||||
$this->publishFormat = self::FBNS_PUBLISH_FORMAT;
|
||||
$this->noAutomaticForeground = true;
|
||||
$this->makeUserAvailableInForeground = false;
|
||||
$this->isInitiallyForeground = false;
|
||||
$this->networkType = 1;
|
||||
$this->networkSubtype = 0;
|
||||
$this->subscribeTopics = [(int) Lite::MESSAGE_TOPIC_ID, (int) Lite::REG_RESP_TOPIC_ID];
|
||||
$this->appId = self::FBNS_APP_ID;
|
||||
$this->clientStack = self::FBNS_CLIENT_STACK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function toThrift()
|
||||
{
|
||||
$writer = new Writer();
|
||||
|
||||
$writer->writeString(self::CLIENT_ID, $this->auth->getClientId());
|
||||
|
||||
$writer->writeStruct(self::CLIENT_INFO);
|
||||
$writer->writeInt64(self::USER_ID, $this->auth->getUserId());
|
||||
$writer->writeString(self::USER_AGENT, $this->userAgent);
|
||||
$writer->writeInt64(self::CLIENT_CAPABILITIES, $this->clientCapabilities);
|
||||
$writer->writeInt64(self::ENDPOINT_CAPABILITIES, $this->endpointCapabilities);
|
||||
$writer->writeInt32(self::PUBLISH_FORMAT, $this->publishFormat);
|
||||
$writer->writeBool(self::NO_AUTOMATIC_FOREGROUND, $this->noAutomaticForeground);
|
||||
$writer->writeBool(self::MAKE_USER_AVAILABLE_IN_FOREGROUND, $this->makeUserAvailableInForeground);
|
||||
$writer->writeString(self::DEVICE_ID, $this->auth->getDeviceId());
|
||||
$writer->writeBool(self::IS_INITIALLY_FOREGROUND, $this->isInitiallyForeground);
|
||||
$writer->writeInt32(self::NETWORK_TYPE, $this->networkType);
|
||||
$writer->writeInt32(self::NETWORK_SUBTYPE, $this->networkSubtype);
|
||||
if ($this->clientMqttSessionId === null) {
|
||||
$sessionId = (int) ((microtime(true) - strtotime('Last Monday')) * 1000);
|
||||
} else {
|
||||
$sessionId = $this->clientMqttSessionId;
|
||||
}
|
||||
$writer->writeInt64(self::CLIENT_MQTT_SESSION_ID, $sessionId);
|
||||
$writer->writeList(self::SUBSCRIBE_TOPICS, Compact::TYPE_I32, $this->subscribeTopics);
|
||||
$writer->writeString(self::CLIENT_TYPE, $this->auth->getClientType());
|
||||
$writer->writeInt64(self::APP_ID, $this->appId);
|
||||
$writer->writeString(self::DEVICE_SECRET, $this->auth->getDeviceSecret());
|
||||
$writer->writeInt8(self::CLIENT_STACK, $this->clientStack);
|
||||
$writer->writeStop();
|
||||
|
||||
$writer->writeString(self::PASSWORD, $this->auth->getPassword());
|
||||
$writer->writeStop();
|
||||
|
||||
return (string) $writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUserAgent()
|
||||
{
|
||||
return $this->userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userAgent
|
||||
*/
|
||||
public function setUserAgent($userAgent)
|
||||
{
|
||||
$this->userAgent = $userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getClientCapabilities()
|
||||
{
|
||||
return $this->clientCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $clientCapabilities
|
||||
*/
|
||||
public function setClientCapabilities($clientCapabilities)
|
||||
{
|
||||
$this->clientCapabilities = $clientCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getEndpointCapabilities()
|
||||
{
|
||||
return $this->endpointCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $endpointCapabilities
|
||||
*/
|
||||
public function setEndpointCapabilities($endpointCapabilities)
|
||||
{
|
||||
$this->endpointCapabilities = $endpointCapabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isNoAutomaticForeground()
|
||||
{
|
||||
return $this->noAutomaticForeground;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $noAutomaticForeground
|
||||
*/
|
||||
public function setNoAutomaticForeground($noAutomaticForeground)
|
||||
{
|
||||
$this->noAutomaticForeground = $noAutomaticForeground;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isMakeUserAvailableInForeground()
|
||||
{
|
||||
return $this->makeUserAvailableInForeground;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $makeUserAvailableInForeground
|
||||
*/
|
||||
public function setMakeUserAvailableInForeground($makeUserAvailableInForeground)
|
||||
{
|
||||
$this->makeUserAvailableInForeground = $makeUserAvailableInForeground;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isInitiallyForeground()
|
||||
{
|
||||
return $this->isInitiallyForeground;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isInitiallyForeground
|
||||
*/
|
||||
public function setIsInitiallyForeground($isInitiallyForeground)
|
||||
{
|
||||
$this->isInitiallyForeground = $isInitiallyForeground;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getNetworkType()
|
||||
{
|
||||
return $this->networkType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $networkType
|
||||
*/
|
||||
public function setNetworkType($networkType)
|
||||
{
|
||||
$this->networkType = $networkType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getNetworkSubtype()
|
||||
{
|
||||
return $this->networkSubtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $networkSubtype
|
||||
*/
|
||||
public function setNetworkSubtype($networkSubtype)
|
||||
{
|
||||
$this->networkSubtype = $networkSubtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getClientMqttSessionId()
|
||||
{
|
||||
return $this->clientMqttSessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $clientMqttSessionId
|
||||
*/
|
||||
public function setClientMqttSessionId($clientMqttSessionId)
|
||||
{
|
||||
$this->clientMqttSessionId = $clientMqttSessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
public function getSubscribeTopics()
|
||||
{
|
||||
return $this->subscribeTopics;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $subscribeTopics
|
||||
*/
|
||||
public function setSubscribeTopics($subscribeTopics)
|
||||
{
|
||||
$this->subscribeTopics = $subscribeTopics;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getAppId()
|
||||
{
|
||||
return $this->appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $appId
|
||||
*/
|
||||
public function setAppId($appId)
|
||||
{
|
||||
$this->appId = $appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getClientStack()
|
||||
{
|
||||
return $this->clientStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $clientStack
|
||||
*/
|
||||
public function setClientStack($clientStack)
|
||||
{
|
||||
$this->clientStack = $clientStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AuthInterface
|
||||
*/
|
||||
public function getAuth()
|
||||
{
|
||||
return $this->auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AuthInterface $auth
|
||||
*/
|
||||
public function setAuth(AuthInterface $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
}
|
||||
28
vendor/valga/fbns-react/src/Json.php
vendored
Executable file
28
vendor/valga/fbns-react/src/Json.php
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client;
|
||||
|
||||
class Json
|
||||
{
|
||||
/**
|
||||
* Special decoder to keep big numbers on x86 PHP builds.
|
||||
*
|
||||
* @param string $json
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function decode($json)
|
||||
{
|
||||
$flags = 0;
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$flags |= JSON_BIGINT_AS_STRING;
|
||||
}
|
||||
$data = json_decode($json, false, 512, $flags);
|
||||
$error = json_last_error();
|
||||
if ($error !== JSON_ERROR_NONE) {
|
||||
throw new \InvalidArgumentException(sprintf('Failed to decode JSON (%d): %s.', $error, json_last_error_msg()));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
379
vendor/valga/fbns-react/src/Lite.php
vendored
Executable file
379
vendor/valga/fbns-react/src/Lite.php
vendored
Executable file
@@ -0,0 +1,379 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client;
|
||||
|
||||
use BinSoul\Net\Mqtt\DefaultMessage;
|
||||
use BinSoul\Net\Mqtt\Message;
|
||||
use Evenement\EventEmitterInterface;
|
||||
use Evenement\EventEmitterTrait;
|
||||
use Fbns\Client\Lite\ConnectResponsePacket;
|
||||
use Fbns\Client\Lite\OutgoingConnectFlow;
|
||||
use Fbns\Client\Lite\ReactMqttClient;
|
||||
use Fbns\Client\Lite\StreamParser;
|
||||
use Fbns\Client\Message\Push;
|
||||
use Fbns\Client\Message\Register;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\EventLoop\Timer\TimerInterface;
|
||||
use React\Promise\Deferred;
|
||||
use React\Promise\FulfilledPromise;
|
||||
use React\Promise\PromiseInterface;
|
||||
use React\Socket\Connector;
|
||||
use React\Socket\ConnectorInterface;
|
||||
use React\Socket\SecureConnector;
|
||||
|
||||
class Lite implements EventEmitterInterface
|
||||
{
|
||||
use EventEmitterTrait;
|
||||
|
||||
const QOS_LEVEL = 1;
|
||||
|
||||
const MESSAGE_TOPIC = '/fbns_msg';
|
||||
const MESSAGE_TOPIC_ID = '76';
|
||||
|
||||
const REG_REQ_TOPIC = '/fbns_reg_req';
|
||||
const REG_REQ_TOPIC_ID = '79';
|
||||
|
||||
const REG_RESP_TOPIC = '/fbns_reg_resp';
|
||||
const REG_RESP_TOPIC_ID = '80';
|
||||
|
||||
const ID_TO_TOPIC_ENUM = [
|
||||
self::MESSAGE_TOPIC_ID => self::MESSAGE_TOPIC,
|
||||
self::REG_REQ_TOPIC_ID => self::REG_REQ_TOPIC,
|
||||
self::REG_RESP_TOPIC_ID => self::REG_RESP_TOPIC,
|
||||
];
|
||||
|
||||
const TOPIC_TO_ID_ENUM = [
|
||||
self::MESSAGE_TOPIC => self::MESSAGE_TOPIC_ID,
|
||||
self::REG_REQ_TOPIC => self::REG_REQ_TOPIC_ID,
|
||||
self::REG_RESP_TOPIC => self::REG_RESP_TOPIC_ID,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var LoopInterface
|
||||
*/
|
||||
private $loop;
|
||||
|
||||
/**
|
||||
* @var ConnectorInterface
|
||||
*/
|
||||
private $connector;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var ReactMqttClient
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var TimerInterface
|
||||
*/
|
||||
private $keepaliveTimer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param LoopInterface $loop
|
||||
* @param ConnectorInterface|null $connector
|
||||
* @param LoggerInterface|null $logger
|
||||
*/
|
||||
public function __construct(LoopInterface $loop, ConnectorInterface $connector = null, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->loop = $loop;
|
||||
if ($connector === null) {
|
||||
$this->connector = new SecureConnector(new Connector($loop), $loop);
|
||||
} else {
|
||||
$this->connector = $connector;
|
||||
}
|
||||
if ($logger !== null) {
|
||||
$this->logger = $logger;
|
||||
} else {
|
||||
$this->logger = new NullLogger();
|
||||
}
|
||||
$this->client = new ReactMqttClient($this->connector, $this->loop, null, new StreamParser());
|
||||
|
||||
$this->client
|
||||
->on('open', function () {
|
||||
$this->logger->info('Connection has been established.');
|
||||
})
|
||||
->on('close', function () {
|
||||
$this->logger->info('Network connection has been closed.');
|
||||
$this->cancelKeepaliveTimer();
|
||||
$this->emit('disconnect', [$this]);
|
||||
})
|
||||
->on('warning', function (\Exception $e) {
|
||||
$this->logger->warning($e->getMessage());
|
||||
})
|
||||
->on('error', function (\Exception $e) {
|
||||
$this->logger->error($e->getMessage());
|
||||
$this->emit('error', [$e]);
|
||||
})
|
||||
->on('connect', function (ConnectResponsePacket $responsePacket) {
|
||||
$this->logger->info('Connected to a broker.');
|
||||
$this->setKeepaliveTimer();
|
||||
$this->emit('connect', [$responsePacket]);
|
||||
})
|
||||
->on('disconnect', function () {
|
||||
$this->logger->info('Disconnected from the broker.');
|
||||
})
|
||||
->on('message', function (Message $message) {
|
||||
$this->setKeepaliveTimer();
|
||||
$this->onMessage($message);
|
||||
})
|
||||
->on('publish', function () {
|
||||
$this->logger->info('Publish flow has been completed.');
|
||||
$this->setKeepaliveTimer();
|
||||
})
|
||||
->on('ping', function () {
|
||||
$this->logger->info('Ping flow has been completed.');
|
||||
$this->setKeepaliveTimer();
|
||||
});
|
||||
}
|
||||
|
||||
private function cancelKeepaliveTimer()
|
||||
{
|
||||
if ($this->keepaliveTimer !== null) {
|
||||
if ($this->keepaliveTimer->isActive()) {
|
||||
$this->logger->info('Existing keepalive timer has been canceled.');
|
||||
$this->keepaliveTimer->cancel();
|
||||
}
|
||||
$this->keepaliveTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private function onKeepalive()
|
||||
{
|
||||
$this->logger->info('Keepalive timer has been fired.');
|
||||
$this->cancelKeepaliveTimer();
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
private function setKeepaliveTimer()
|
||||
{
|
||||
$this->cancelKeepaliveTimer();
|
||||
$keepaliveInterval = OutgoingConnectFlow::KEEPALIVE;
|
||||
$this->logger->info(sprintf('Setting up keepalive timer to %d seconds', $keepaliveInterval));
|
||||
$this->keepaliveTimer = $this->loop->addTimer($keepaliveInterval, function () {
|
||||
$this->onKeepalive();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $payload
|
||||
*/
|
||||
private function onRegister($payload)
|
||||
{
|
||||
try {
|
||||
$message = new Register($payload);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->warning(sprintf('Failed to decode register message: %s', $e->getMessage()), [$payload]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->emit('register', [$message]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $payload
|
||||
*/
|
||||
private function onPush($payload)
|
||||
{
|
||||
try {
|
||||
$message = new Push($payload);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->warning(sprintf('Failed to decode push message: %s', $e->getMessage()), [$payload]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->emit('push', [$message]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Message $message
|
||||
*/
|
||||
private function onMessage(Message $message)
|
||||
{
|
||||
$payload = @zlib_decode($message->getPayload());
|
||||
if ($payload === false) {
|
||||
$this->logger->warning('Failed to inflate a payload.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$topic = $this->unmapTopic($message->getTopic());
|
||||
$this->logger->info(sprintf('Received a message from topic "%s".', $topic), [$payload]);
|
||||
|
||||
switch ($topic) {
|
||||
case self::MESSAGE_TOPIC:
|
||||
$this->onPush($payload);
|
||||
break;
|
||||
case self::REG_RESP_TOPIC:
|
||||
$this->onRegister($payload);
|
||||
break;
|
||||
default:
|
||||
$this->logger->warning(sprintf('Received a message from unknown topic "%s".', $topic), [$payload]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes a connection to the FBNS server.
|
||||
*
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param Connection $connection
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
private function establishConnection($host, $port, Connection $connection, $timeout)
|
||||
{
|
||||
$this->logger->info(sprintf('Connecting to %s:%d...', $host, $port));
|
||||
|
||||
return $this->client->connect($host, $port, $connection, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to a FBNS server.
|
||||
*
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param Connection $connection
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function connect($host, $port, Connection $connection, $timeout = 5)
|
||||
{
|
||||
$deferred = new Deferred();
|
||||
$this->disconnect()
|
||||
->then(function () use ($deferred, $host, $port, $connection, $timeout) {
|
||||
$this->establishConnection($host, $port, $connection, $timeout)
|
||||
->then(function () use ($deferred) {
|
||||
$deferred->resolve($this);
|
||||
})
|
||||
->otherwise(function (\Exception $error) use ($deferred) {
|
||||
$deferred->reject($error);
|
||||
});
|
||||
})
|
||||
->otherwise(function () use ($deferred) {
|
||||
$deferred->reject($this);
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
if ($this->client->isConnected()) {
|
||||
$deferred = new Deferred();
|
||||
$this->client->disconnect()
|
||||
->then(function () use ($deferred) {
|
||||
$deferred->resolve($this);
|
||||
})
|
||||
->otherwise(function () use ($deferred) {
|
||||
$deferred->reject($this);
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
} else {
|
||||
return new FulfilledPromise($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps human readable topic to its ID.
|
||||
*
|
||||
* @param string $topic
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function mapTopic($topic)
|
||||
{
|
||||
if (array_key_exists($topic, self::TOPIC_TO_ID_ENUM)) {
|
||||
$result = self::TOPIC_TO_ID_ENUM[$topic];
|
||||
$this->logger->debug(sprintf('Topic "%s" has been mapped to "%s".', $topic, $result));
|
||||
} else {
|
||||
$result = $topic;
|
||||
$this->logger->debug(sprintf('Topic "%s" does not exist in enum.', $topic));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps topic ID to human readable name.
|
||||
*
|
||||
* @param string $topic
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function unmapTopic($topic)
|
||||
{
|
||||
if (array_key_exists($topic, self::ID_TO_TOPIC_ENUM)) {
|
||||
$result = self::ID_TO_TOPIC_ENUM[$topic];
|
||||
$this->logger->debug(sprintf('Topic ID "%s" has been unmapped to "%s".', $topic, $result));
|
||||
} else {
|
||||
$result = $topic;
|
||||
$this->logger->debug(sprintf('Topic ID "%s" does not exist in enum.', $topic));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a message to a topic.
|
||||
*
|
||||
* @param string $topic
|
||||
* @param string $message
|
||||
* @param int $qosLevel
|
||||
*
|
||||
* @return \React\Promise\ExtendedPromiseInterface
|
||||
*/
|
||||
private function publish($topic, $message, $qosLevel)
|
||||
{
|
||||
$this->logger->info(sprintf('Sending message to topic "%s".', $topic), [$message]);
|
||||
$topic = $this->mapTopic($topic);
|
||||
$payload = zlib_encode($message, ZLIB_ENCODING_DEFLATE, 9);
|
||||
|
||||
return $this->client->publish(new DefaultMessage($topic, $payload, $qosLevel));
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an application.
|
||||
*
|
||||
* @param string $packageName
|
||||
* @param string|int $appId
|
||||
*
|
||||
* @return PromiseInterface
|
||||
*/
|
||||
public function register($packageName, $appId)
|
||||
{
|
||||
$this->logger->info(sprintf('Registering application "%s" (%s).', $packageName, $appId));
|
||||
$message = json_encode([
|
||||
'pkg_name' => (string) $packageName,
|
||||
'appid' => (string) $appId,
|
||||
]);
|
||||
|
||||
return $this->publish(self::REG_REQ_TOPIC, $message, self::QOS_LEVEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether underlying client is connected.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConnected()
|
||||
{
|
||||
return $this->client->isConnected();
|
||||
}
|
||||
}
|
||||
198
vendor/valga/fbns-react/src/Lite/ConnectRequestPacket.php
vendored
Executable file
198
vendor/valga/fbns-react/src/Lite/ConnectRequestPacket.php
vendored
Executable file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of net-mqtt.
|
||||
*
|
||||
* Copyright (c) 2015 Sebastian Mößler code@binsoul.de
|
||||
*
|
||||
* This source file is subject to the MIT license.
|
||||
*/
|
||||
|
||||
namespace Fbns\Client\Lite;
|
||||
|
||||
use BinSoul\Net\Mqtt\Packet;
|
||||
use BinSoul\Net\Mqtt\Packet\BasePacket;
|
||||
use BinSoul\Net\Mqtt\PacketStream;
|
||||
|
||||
/**
|
||||
* Represents the CONNECT packet.
|
||||
*/
|
||||
class ConnectRequestPacket extends BasePacket
|
||||
{
|
||||
/** @var int */
|
||||
private $protocolLevel = 3;
|
||||
/** @var string */
|
||||
private $protocolName = 'MQTToT';
|
||||
/** @var int */
|
||||
private $flags = 194;
|
||||
/** @var int */
|
||||
private $keepAlive = 900;
|
||||
/** @var string */
|
||||
private $payload;
|
||||
|
||||
protected static $packetType = Packet::TYPE_CONNECT;
|
||||
|
||||
public function read(PacketStream $stream)
|
||||
{
|
||||
parent::read($stream);
|
||||
$this->assertPacketFlags(0);
|
||||
$this->assertRemainingPacketLength();
|
||||
|
||||
$originalPosition = $stream->getPosition();
|
||||
$this->protocolName = $stream->readString();
|
||||
$this->protocolLevel = $stream->readByte();
|
||||
$this->flags = $stream->readByte();
|
||||
$this->keepAlive = $stream->readWord();
|
||||
|
||||
$payloadLength = $this->remainingPacketLength - ($stream->getPosition() - $originalPosition);
|
||||
$this->payload = $stream->read($payloadLength);
|
||||
}
|
||||
|
||||
public function write(PacketStream $stream)
|
||||
{
|
||||
$data = new PacketStream();
|
||||
|
||||
$data->writeString($this->protocolName);
|
||||
$data->writeByte($this->protocolLevel);
|
||||
$data->writeByte($this->flags);
|
||||
$data->writeWord($this->keepAlive);
|
||||
$data->write($this->payload);
|
||||
|
||||
$this->remainingPacketLength = $data->length();
|
||||
|
||||
parent::write($stream);
|
||||
$stream->write($data->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol level.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getProtocolLevel()
|
||||
{
|
||||
return $this->protocolLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol level.
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setProtocolLevel($value)
|
||||
{
|
||||
if ($value != 3) {
|
||||
throw new \InvalidArgumentException(sprintf('Unknown protocol level %d.', $value));
|
||||
}
|
||||
|
||||
$this->protocolLevel = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the payload.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPayload()
|
||||
{
|
||||
return $this->payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the payload.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setPayload($value)
|
||||
{
|
||||
$this->payload = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the flags.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flags.
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setFlags($value)
|
||||
{
|
||||
if ($value > 255) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'Expected a flags lower than 255 but got %d.',
|
||||
$value
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->flags = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the keep alive time in seconds.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getKeepAlive()
|
||||
{
|
||||
return $this->keepAlive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the keep alive time in seconds.
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setKeepAlive($value)
|
||||
{
|
||||
if ($value > 65535) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf(
|
||||
'Expected a keep alive time lower than 65535 but got %d.',
|
||||
$value
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->keepAlive = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProtocolName()
|
||||
{
|
||||
return $this->protocolName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protocol name.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setProtocolName($value)
|
||||
{
|
||||
$this->assertValidStringLength($value, false);
|
||||
|
||||
$this->protocolName = $value;
|
||||
}
|
||||
}
|
||||
145
vendor/valga/fbns-react/src/Lite/ConnectResponsePacket.php
vendored
Executable file
145
vendor/valga/fbns-react/src/Lite/ConnectResponsePacket.php
vendored
Executable file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of net-mqtt.
|
||||
*
|
||||
* Copyright (c) 2015 Sebastian Mößler code@binsoul.de
|
||||
*
|
||||
* This source file is subject to the MIT license.
|
||||
*/
|
||||
|
||||
namespace Fbns\Client\Lite;
|
||||
|
||||
use BinSoul\Net\Mqtt\Packet;
|
||||
use BinSoul\Net\Mqtt\Packet\BasePacket;
|
||||
use BinSoul\Net\Mqtt\PacketStream;
|
||||
|
||||
/**
|
||||
* Represents the CONNACK packet.
|
||||
*/
|
||||
class ConnectResponsePacket extends BasePacket
|
||||
{
|
||||
/** @var string[][] */
|
||||
private static $returnCodes = [
|
||||
0 => [
|
||||
'Connection accepted',
|
||||
'',
|
||||
],
|
||||
1 => [
|
||||
'Unacceptable protocol version',
|
||||
'The Server does not support the level of the MQTT protocol requested by the client.',
|
||||
],
|
||||
2 => [
|
||||
'Identifier rejected',
|
||||
'The client identifier is correct UTF-8 but not allowed by the server.',
|
||||
],
|
||||
3 => [
|
||||
'Server unavailable',
|
||||
'The network connection has been made but the MQTT service is unavailable',
|
||||
],
|
||||
4 => [
|
||||
'Bad user name or password',
|
||||
'The data in the user name or password is malformed.',
|
||||
],
|
||||
5 => [
|
||||
'Not authorized',
|
||||
'The client is not authorized to connect.',
|
||||
],
|
||||
];
|
||||
|
||||
/** @var int */
|
||||
private $flags = 0;
|
||||
/** @var int */
|
||||
private $returnCode;
|
||||
/** @var string */
|
||||
private $auth;
|
||||
|
||||
protected static $packetType = Packet::TYPE_CONNACK;
|
||||
|
||||
public function read(PacketStream $stream)
|
||||
{
|
||||
parent::read($stream);
|
||||
$this->assertPacketFlags(0);
|
||||
$this->assertRemainingPacketLength();
|
||||
|
||||
$originalPosition = $stream->getPosition();
|
||||
$this->flags = $stream->readByte();
|
||||
$this->returnCode = $stream->readByte();
|
||||
|
||||
$authLength = $this->remainingPacketLength - ($stream->getPosition() - $originalPosition);
|
||||
if ($authLength) {
|
||||
$this->auth = $stream->readString();
|
||||
} else {
|
||||
$this->auth = '';
|
||||
}
|
||||
}
|
||||
|
||||
public function write(PacketStream $stream)
|
||||
{
|
||||
$data = new PacketStream();
|
||||
|
||||
$data->writeByte($this->flags);
|
||||
$data->writeByte($this->returnCode);
|
||||
|
||||
if ($this->auth !== null && strlen($this->auth)) {
|
||||
$data->writeString($this->auth);
|
||||
}
|
||||
|
||||
$this->remainingPacketLength = $data->length();
|
||||
|
||||
parent::write($stream);
|
||||
$stream->write($data->getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the return code.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getReturnCode()
|
||||
{
|
||||
return $this->returnCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the connection was successful.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSuccess()
|
||||
{
|
||||
return $this->returnCode === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the connection failed.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isError()
|
||||
{
|
||||
return $this->returnCode > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the returned error code.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getErrorName()
|
||||
{
|
||||
if (isset(self::$returnCodes[$this->returnCode])) {
|
||||
return self::$returnCodes[$this->returnCode][0];
|
||||
}
|
||||
|
||||
return 'Error '.$this->returnCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAuth()
|
||||
{
|
||||
return $this->auth;
|
||||
}
|
||||
}
|
||||
74
vendor/valga/fbns-react/src/Lite/OutgoingConnectFlow.php
vendored
Executable file
74
vendor/valga/fbns-react/src/Lite/OutgoingConnectFlow.php
vendored
Executable file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of net-mqtt.
|
||||
*
|
||||
* Copyright (c) 2015 Sebastian Mößler code@binsoul.de
|
||||
*
|
||||
* This source file is subject to the MIT license.
|
||||
*/
|
||||
|
||||
namespace Fbns\Client\Lite;
|
||||
|
||||
use BinSoul\Net\Mqtt\Flow\AbstractFlow;
|
||||
use BinSoul\Net\Mqtt\Packet;
|
||||
use BinSoul\Net\Mqtt\Packet\ConnectResponsePacket;
|
||||
use Fbns\Client\Connection;
|
||||
|
||||
/**
|
||||
* Represents a flow starting with an outgoing CONNECT packet.
|
||||
*/
|
||||
class OutgoingConnectFlow extends AbstractFlow
|
||||
{
|
||||
const PROTOCOL_LEVEL = 3;
|
||||
|
||||
const PROTOCOL_NAME = 'MQTToT';
|
||||
|
||||
const KEEPALIVE = 900;
|
||||
const KEEPALIVE_TIMEOUT = 60;
|
||||
|
||||
/** @var Connection */
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*
|
||||
* @param Connection $connection
|
||||
*/
|
||||
public function __construct(Connection $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
public function getCode()
|
||||
{
|
||||
return 'connect';
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
$packet = new ConnectRequestPacket();
|
||||
$packet->setProtocolLevel(self::PROTOCOL_LEVEL);
|
||||
$packet->setProtocolName(self::PROTOCOL_NAME);
|
||||
$packet->setKeepAlive(self::KEEPALIVE);
|
||||
$packet->setFlags(194);
|
||||
$packet->setPayload(zlib_encode($this->connection->toThrift(), ZLIB_ENCODING_DEFLATE, 9));
|
||||
|
||||
return $packet;
|
||||
}
|
||||
|
||||
public function accept(Packet $packet)
|
||||
{
|
||||
return $packet->getPacketType() === Packet::TYPE_CONNACK;
|
||||
}
|
||||
|
||||
public function next(Packet $packet)
|
||||
{
|
||||
/** @var ConnectResponsePacket $packet */
|
||||
if ($packet->isSuccess()) {
|
||||
$this->succeed($packet);
|
||||
} else {
|
||||
$this->fail($packet->getErrorName());
|
||||
}
|
||||
}
|
||||
}
|
||||
74
vendor/valga/fbns-react/src/Lite/PacketFactory.php
vendored
Executable file
74
vendor/valga/fbns-react/src/Lite/PacketFactory.php
vendored
Executable file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of net-mqtt.
|
||||
*
|
||||
* Copyright (c) 2015 Sebastian Mößler code@binsoul.de
|
||||
*
|
||||
* This source file is subject to the MIT license.
|
||||
*/
|
||||
|
||||
namespace Fbns\Client\Lite;
|
||||
|
||||
use BinSoul\Net\Mqtt\Exception\UnknownPacketTypeException;
|
||||
use BinSoul\Net\Mqtt\Packet;
|
||||
use BinSoul\Net\Mqtt\Packet\DisconnectRequestPacket;
|
||||
use BinSoul\Net\Mqtt\Packet\PingRequestPacket;
|
||||
use BinSoul\Net\Mqtt\Packet\PingResponsePacket;
|
||||
use BinSoul\Net\Mqtt\Packet\PublishCompletePacket;
|
||||
use BinSoul\Net\Mqtt\Packet\PublishReceivedPacket;
|
||||
use BinSoul\Net\Mqtt\Packet\PublishReleasePacket;
|
||||
use BinSoul\Net\Mqtt\Packet\PublishRequestPacket;
|
||||
use BinSoul\Net\Mqtt\Packet\SubscribeRequestPacket;
|
||||
use BinSoul\Net\Mqtt\Packet\SubscribeResponsePacket;
|
||||
use BinSoul\Net\Mqtt\Packet\UnsubscribeRequestPacket;
|
||||
use BinSoul\Net\Mqtt\Packet\UnsubscribeResponsePacket;
|
||||
use Fbns\Client\Common\PublishAckPacket;
|
||||
|
||||
/**
|
||||
* Builds instances of the {@see Packet} interface.
|
||||
*/
|
||||
class PacketFactory
|
||||
{
|
||||
/**
|
||||
* Map of packet types to packet classes.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private static $mapping = [
|
||||
Packet::TYPE_CONNECT => ConnectRequestPacket::class,
|
||||
Packet::TYPE_CONNACK => ConnectResponsePacket::class,
|
||||
Packet::TYPE_PUBLISH => PublishRequestPacket::class,
|
||||
Packet::TYPE_PUBACK => PublishAckPacket::class,
|
||||
Packet::TYPE_PUBREC => PublishReceivedPacket::class,
|
||||
Packet::TYPE_PUBREL => PublishReleasePacket::class,
|
||||
Packet::TYPE_PUBCOMP => PublishCompletePacket::class,
|
||||
Packet::TYPE_SUBSCRIBE => SubscribeRequestPacket::class,
|
||||
Packet::TYPE_SUBACK => SubscribeResponsePacket::class,
|
||||
Packet::TYPE_UNSUBSCRIBE => UnsubscribeRequestPacket::class,
|
||||
Packet::TYPE_UNSUBACK => UnsubscribeResponsePacket::class,
|
||||
Packet::TYPE_PINGREQ => PingRequestPacket::class,
|
||||
Packet::TYPE_PINGRESP => PingResponsePacket::class,
|
||||
Packet::TYPE_DISCONNECT => DisconnectRequestPacket::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Builds a packet object for the given type.
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
* @throws UnknownPacketTypeException
|
||||
*
|
||||
* @return Packet
|
||||
*/
|
||||
public function build($type)
|
||||
{
|
||||
if (!isset(self::$mapping[$type])) {
|
||||
throw new UnknownPacketTypeException(sprintf('Unknown packet type %d.', $type));
|
||||
}
|
||||
|
||||
$class = self::$mapping[$type];
|
||||
|
||||
return new $class();
|
||||
}
|
||||
}
|
||||
120
vendor/valga/fbns-react/src/Lite/ReactFlow.php
vendored
Executable file
120
vendor/valga/fbns-react/src/Lite/ReactFlow.php
vendored
Executable file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of net-mqtt-client-react.
|
||||
*
|
||||
* Copyright (c) 2015 Sebastian Mößler code@binsoul.de
|
||||
*
|
||||
* This source file is subject to the MIT license.
|
||||
*/
|
||||
|
||||
namespace Fbns\Client\Lite;
|
||||
|
||||
use BinSoul\Net\Mqtt\Flow;
|
||||
use BinSoul\Net\Mqtt\Packet;
|
||||
use React\Promise\Deferred;
|
||||
|
||||
/**
|
||||
* Decorates flows with data required for the {@see ReactMqttClient} class.
|
||||
*/
|
||||
class ReactFlow implements Flow
|
||||
{
|
||||
/** @var Flow */
|
||||
private $decorated;
|
||||
/** @var Deferred */
|
||||
private $deferred;
|
||||
/** @var Packet */
|
||||
private $packet;
|
||||
/** @var bool */
|
||||
private $isSilent;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*
|
||||
* @param Flow $decorated
|
||||
* @param Deferred $deferred
|
||||
* @param Packet $packet
|
||||
* @param bool $isSilent
|
||||
*/
|
||||
public function __construct(Flow $decorated, Deferred $deferred, Packet $packet = null, $isSilent = false)
|
||||
{
|
||||
$this->decorated = $decorated;
|
||||
$this->deferred = $deferred;
|
||||
$this->packet = $packet;
|
||||
$this->isSilent = $isSilent;
|
||||
}
|
||||
|
||||
public function getCode()
|
||||
{
|
||||
return $this->decorated->getCode();
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
$this->packet = $this->decorated->start();
|
||||
|
||||
return $this->packet;
|
||||
}
|
||||
|
||||
public function accept(Packet $packet)
|
||||
{
|
||||
return $this->decorated->accept($packet);
|
||||
}
|
||||
|
||||
public function next(Packet $packet)
|
||||
{
|
||||
$this->packet = $this->decorated->next($packet);
|
||||
|
||||
return $this->packet;
|
||||
}
|
||||
|
||||
public function isFinished()
|
||||
{
|
||||
return $this->decorated->isFinished();
|
||||
}
|
||||
|
||||
public function isSuccess()
|
||||
{
|
||||
return $this->decorated->isSuccess();
|
||||
}
|
||||
|
||||
public function getResult()
|
||||
{
|
||||
return $this->decorated->getResult();
|
||||
}
|
||||
|
||||
public function getErrorMessage()
|
||||
{
|
||||
return $this->decorated->getErrorMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the associated deferred.
|
||||
*
|
||||
* @return Deferred
|
||||
*/
|
||||
public function getDeferred()
|
||||
{
|
||||
return $this->deferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current packet.
|
||||
*
|
||||
* @return Packet
|
||||
*/
|
||||
public function getPacket()
|
||||
{
|
||||
return $this->packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the flow should emit events.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSilent()
|
||||
{
|
||||
return $this->isSilent;
|
||||
}
|
||||
}
|
||||
695
vendor/valga/fbns-react/src/Lite/ReactMqttClient.php
vendored
Executable file
695
vendor/valga/fbns-react/src/Lite/ReactMqttClient.php
vendored
Executable file
@@ -0,0 +1,695 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of net-mqtt-client-react.
|
||||
*
|
||||
* Copyright (c) 2015 Sebastian Mößler code@binsoul.de
|
||||
*
|
||||
* This source file is subject to the MIT license.
|
||||
*/
|
||||
|
||||
namespace Fbns\Client\Lite;
|
||||
|
||||
use BinSoul\Net\Mqtt\DefaultConnection;
|
||||
use BinSoul\Net\Mqtt\DefaultIdentifierGenerator;
|
||||
use BinSoul\Net\Mqtt\DefaultMessage;
|
||||
use BinSoul\Net\Mqtt\Flow;
|
||||
use BinSoul\Net\Mqtt\Flow\IncomingPublishFlow;
|
||||
use BinSoul\Net\Mqtt\Flow\OutgoingDisconnectFlow;
|
||||
use BinSoul\Net\Mqtt\Flow\OutgoingPingFlow;
|
||||
use BinSoul\Net\Mqtt\Flow\OutgoingPublishFlow;
|
||||
use BinSoul\Net\Mqtt\Flow\OutgoingSubscribeFlow;
|
||||
use BinSoul\Net\Mqtt\Flow\OutgoingUnsubscribeFlow;
|
||||
use BinSoul\Net\Mqtt\IdentifierGenerator;
|
||||
use BinSoul\Net\Mqtt\Message;
|
||||
use BinSoul\Net\Mqtt\Packet;
|
||||
use BinSoul\Net\Mqtt\Packet\PublishRequestPacket;
|
||||
use BinSoul\Net\Mqtt\StreamParser;
|
||||
use BinSoul\Net\Mqtt\Subscription;
|
||||
use Evenement\EventEmitter;
|
||||
use Fbns\Client\Connection;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\EventLoop\Timer\TimerInterface;
|
||||
use React\Promise\Deferred;
|
||||
use React\Promise\ExtendedPromiseInterface;
|
||||
use React\Promise\RejectedPromise;
|
||||
use React\Socket\ConnectorInterface;
|
||||
use React\Stream\DuplexStreamInterface;
|
||||
|
||||
/**
|
||||
* Connects to a MQTT broker and subscribes to topics or publishes messages.
|
||||
*
|
||||
* The following events are emitted:
|
||||
* - open - The network connection to the server is established.
|
||||
* - close - The network connection to the server is closed.
|
||||
* - warning - An event of severity "warning" occurred.
|
||||
* - error - An event of severity "error" occurred.
|
||||
*
|
||||
* If a flow finishes it's result is also emitted, e.g.:
|
||||
* - connect - The client connected to the broker.
|
||||
* - disconnect - The client disconnected from the broker.
|
||||
* - subscribe - The client subscribed to a topic filter.
|
||||
* - unsubscribe - The client unsubscribed from topic filter.
|
||||
* - publish - A message was published.
|
||||
* - message - A message was received.
|
||||
*/
|
||||
class ReactMqttClient extends EventEmitter
|
||||
{
|
||||
/** @var ConnectorInterface */
|
||||
private $connector;
|
||||
/** @var LoopInterface */
|
||||
private $loop;
|
||||
/** @var DuplexStreamInterface */
|
||||
private $stream;
|
||||
/** @var StreamParser */
|
||||
private $parser;
|
||||
/** @var IdentifierGenerator */
|
||||
private $identifierGenerator;
|
||||
|
||||
/** @var string */
|
||||
private $host;
|
||||
/** @var int */
|
||||
private $port;
|
||||
/** @var Connection */
|
||||
private $connection;
|
||||
/** @var bool */
|
||||
private $isConnected = false;
|
||||
/** @var bool */
|
||||
private $isConnecting = false;
|
||||
/** @var bool */
|
||||
private $isDisconnecting = false;
|
||||
|
||||
/** @var TimerInterface[] */
|
||||
private $timer = [];
|
||||
|
||||
/** @var ReactFlow[] */
|
||||
private $receivingFlows = [];
|
||||
/** @var ReactFlow[] */
|
||||
private $sendingFlows = [];
|
||||
/** @var ReactFlow */
|
||||
private $writtenFlow;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*
|
||||
* @param ConnectorInterface $connector
|
||||
* @param LoopInterface $loop
|
||||
* @param IdentifierGenerator $identifierGenerator
|
||||
* @param StreamParser $parser
|
||||
*/
|
||||
public function __construct(
|
||||
ConnectorInterface $connector,
|
||||
LoopInterface $loop,
|
||||
IdentifierGenerator $identifierGenerator = null,
|
||||
StreamParser $parser = null
|
||||
) {
|
||||
$this->connector = $connector;
|
||||
$this->loop = $loop;
|
||||
|
||||
$this->parser = $parser;
|
||||
if ($this->parser === null) {
|
||||
$this->parser = new StreamParser();
|
||||
}
|
||||
|
||||
$this->parser->onError(function (\Exception $e) {
|
||||
$this->emitWarning($e);
|
||||
});
|
||||
|
||||
$this->identifierGenerator = $identifierGenerator;
|
||||
if ($this->identifierGenerator === null) {
|
||||
$this->identifierGenerator = new DefaultIdentifierGenerator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the host.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHost()
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the port.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPort()
|
||||
{
|
||||
return $this->port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the client is connected.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isConnected()
|
||||
{
|
||||
return $this->isConnected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the underlying stream or null if the client is not connected.
|
||||
*
|
||||
* @return DuplexStreamInterface|null
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to a broker.
|
||||
*
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param Connection $connection
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
public function connect($host, $port, Connection $connection, $timeout = 5)
|
||||
{
|
||||
if ($this->isConnected || $this->isConnecting) {
|
||||
return new RejectedPromise(new \LogicException('The client is already connected.'));
|
||||
}
|
||||
|
||||
$this->isConnecting = true;
|
||||
$this->isConnected = false;
|
||||
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
|
||||
$deferred = new Deferred();
|
||||
|
||||
$this->establishConnection($this->host, $this->port, $timeout)
|
||||
->then(function (DuplexStreamInterface $stream) use ($connection, $deferred, $timeout) {
|
||||
$this->stream = $stream;
|
||||
|
||||
$this->emit('open', [$connection, $this]);
|
||||
|
||||
$this->registerClient($connection, $timeout)
|
||||
->then(function (ConnectResponsePacket $responsePacket) use ($deferred, $connection) {
|
||||
$this->isConnecting = false;
|
||||
$this->isConnected = true;
|
||||
$this->connection = $connection;
|
||||
|
||||
$this->emit('connect', [$responsePacket, $this]);
|
||||
$deferred->resolve($responsePacket);
|
||||
})
|
||||
->otherwise(function (\Exception $e) use ($deferred, $connection) {
|
||||
$this->isConnecting = false;
|
||||
|
||||
$this->emitError($e);
|
||||
$deferred->reject($e);
|
||||
|
||||
if ($this->stream !== null) {
|
||||
$this->stream->close();
|
||||
}
|
||||
|
||||
$this->emit('close', [$connection, $this]);
|
||||
});
|
||||
})
|
||||
->otherwise(function (\Exception $e) use ($deferred) {
|
||||
$this->isConnecting = false;
|
||||
|
||||
$this->emitError($e);
|
||||
$deferred->reject($e);
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects from a broker.
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
if (!$this->isConnected || $this->isDisconnecting) {
|
||||
return new RejectedPromise(new \LogicException('The client is not connected.'));
|
||||
}
|
||||
|
||||
$this->isDisconnecting = true;
|
||||
|
||||
$deferred = new Deferred();
|
||||
|
||||
$connection = new DefaultConnection();
|
||||
$this->startFlow(new OutgoingDisconnectFlow($connection), true)
|
||||
->then(function () use ($connection, $deferred) {
|
||||
$this->isDisconnecting = false;
|
||||
$this->isConnected = false;
|
||||
|
||||
$this->emit('disconnect', [$connection, $this]);
|
||||
$deferred->resolve($connection);
|
||||
|
||||
if ($this->stream !== null) {
|
||||
$this->stream->close();
|
||||
}
|
||||
})
|
||||
->otherwise(function () use ($deferred) {
|
||||
$this->isDisconnecting = false;
|
||||
$deferred->reject($this->connection);
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribes to a topic filter.
|
||||
*
|
||||
* @param Subscription $subscription
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
public function subscribe(Subscription $subscription)
|
||||
{
|
||||
if (!$this->isConnected) {
|
||||
return new RejectedPromise(new \LogicException('The client is not connected.'));
|
||||
}
|
||||
|
||||
return $this->startFlow(new OutgoingSubscribeFlow([$subscription], $this->identifierGenerator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribes from a topic filter.
|
||||
*
|
||||
* @param Subscription $subscription
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
public function unsubscribe(Subscription $subscription)
|
||||
{
|
||||
if (!$this->isConnected) {
|
||||
return new RejectedPromise(new \LogicException('The client is not connected.'));
|
||||
}
|
||||
|
||||
return $this->startFlow(new OutgoingUnsubscribeFlow([$subscription], $this->identifierGenerator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes a message.
|
||||
*
|
||||
* @param Message $message
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
public function publish(Message $message)
|
||||
{
|
||||
if (!$this->isConnected) {
|
||||
return new RejectedPromise(new \LogicException('The client is not connected.'));
|
||||
}
|
||||
|
||||
return $this->startFlow(new OutgoingPublishFlow($message, $this->identifierGenerator));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given generator periodically and publishes the return value.
|
||||
*
|
||||
* @param int $interval
|
||||
* @param Message $message
|
||||
* @param callable $generator
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
public function publishPeriodically($interval, Message $message, callable $generator)
|
||||
{
|
||||
if (!$this->isConnected) {
|
||||
return new RejectedPromise(new \LogicException('The client is not connected.'));
|
||||
}
|
||||
|
||||
$deferred = new Deferred();
|
||||
|
||||
$this->timer[] = $this->loop->addPeriodicTimer(
|
||||
$interval,
|
||||
function () use ($message, $generator, $deferred) {
|
||||
$this->publish($message->withPayload($generator($message->getTopic())))->then(
|
||||
function ($value) use ($deferred) {
|
||||
$deferred->notify($value);
|
||||
},
|
||||
function (\Exception $e) use ($deferred) {
|
||||
$deferred->reject($e);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return $deferred->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits warnings.
|
||||
*
|
||||
* @param \Exception $e
|
||||
*/
|
||||
private function emitWarning(\Exception $e)
|
||||
{
|
||||
$this->emit('warning', [$e, $this]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits errors.
|
||||
*
|
||||
* @param \Exception $e
|
||||
*/
|
||||
private function emitError(\Exception $e)
|
||||
{
|
||||
$this->emit('error', [$e, $this]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes a network connection to a server.
|
||||
*
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
private function establishConnection($host, $port, $timeout)
|
||||
{
|
||||
$deferred = new Deferred();
|
||||
|
||||
$timer = $this->loop->addTimer(
|
||||
$timeout,
|
||||
function () use ($deferred, $timeout) {
|
||||
$exception = new \RuntimeException(sprintf('Connection timed out after %d seconds.', $timeout));
|
||||
$deferred->reject($exception);
|
||||
}
|
||||
);
|
||||
|
||||
$this->connector->connect($host.':'.$port)
|
||||
->always(function () use ($timer) {
|
||||
$this->loop->cancelTimer($timer);
|
||||
})
|
||||
->then(function (DuplexStreamInterface $stream) use ($deferred) {
|
||||
$stream->on('data', function ($data) {
|
||||
$this->handleReceive($data);
|
||||
});
|
||||
|
||||
$stream->on('close', function () {
|
||||
$this->handleClose();
|
||||
});
|
||||
|
||||
$stream->on('error', function (\Exception $e) {
|
||||
$this->handleError($e);
|
||||
});
|
||||
|
||||
$deferred->resolve($stream);
|
||||
})
|
||||
->otherwise(function (\Exception $e) use ($deferred) {
|
||||
$deferred->reject($e);
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new client with the broker.
|
||||
*
|
||||
* @param Connection $connection
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
private function registerClient(Connection $connection, $timeout)
|
||||
{
|
||||
$deferred = new Deferred();
|
||||
|
||||
$responseTimer = $this->loop->addTimer(
|
||||
$timeout,
|
||||
function () use ($deferred, $timeout) {
|
||||
$exception = new \RuntimeException(sprintf('No response after %d seconds.', $timeout));
|
||||
$deferred->reject($exception);
|
||||
}
|
||||
);
|
||||
|
||||
$this->startFlow(new OutgoingConnectFlow($connection), true)
|
||||
->always(function () use ($responseTimer) {
|
||||
$this->loop->cancelTimer($responseTimer);
|
||||
})->then(function (ConnectResponsePacket $responsePacket) use ($deferred) {
|
||||
$this->timer[] = $this->loop->addPeriodicTimer(
|
||||
OutgoingConnectFlow::KEEPALIVE - OutgoingConnectFlow::KEEPALIVE_TIMEOUT,
|
||||
function () {
|
||||
$this->startFlow(new OutgoingPingFlow());
|
||||
}
|
||||
);
|
||||
|
||||
$deferred->resolve($responsePacket);
|
||||
})->otherwise(function (\Exception $e) use ($deferred) {
|
||||
$deferred->reject($e);
|
||||
});
|
||||
|
||||
return $deferred->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles incoming data.
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
private function handleReceive($data)
|
||||
{
|
||||
if (!$this->isConnected && !$this->isConnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
$flowCount = count($this->receivingFlows);
|
||||
|
||||
$packets = $this->parser->push($data);
|
||||
foreach ($packets as $packet) {
|
||||
$this->handlePacket($packet);
|
||||
}
|
||||
|
||||
if ($flowCount > count($this->receivingFlows)) {
|
||||
$this->receivingFlows = array_values($this->receivingFlows);
|
||||
}
|
||||
|
||||
$this->handleSend();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an incoming packet.
|
||||
*
|
||||
* @param Packet $packet
|
||||
*/
|
||||
private function handlePacket(Packet $packet)
|
||||
{
|
||||
switch ($packet->getPacketType()) {
|
||||
case Packet::TYPE_PUBLISH:
|
||||
/* @var PublishRequestPacket $packet */
|
||||
$message = new DefaultMessage(
|
||||
$packet->getTopic(),
|
||||
$packet->getPayload(),
|
||||
$packet->getQosLevel(),
|
||||
$packet->isRetained(),
|
||||
$packet->isDuplicate()
|
||||
);
|
||||
|
||||
$this->startFlow(new IncomingPublishFlow($message, $packet->getIdentifier()));
|
||||
break;
|
||||
case Packet::TYPE_CONNACK:
|
||||
case Packet::TYPE_PINGRESP:
|
||||
case Packet::TYPE_SUBACK:
|
||||
case Packet::TYPE_UNSUBACK:
|
||||
case Packet::TYPE_PUBREL:
|
||||
case Packet::TYPE_PUBACK:
|
||||
case Packet::TYPE_PUBREC:
|
||||
case Packet::TYPE_PUBCOMP:
|
||||
$flowFound = false;
|
||||
foreach ($this->receivingFlows as $index => $flow) {
|
||||
if ($flow->accept($packet)) {
|
||||
$flowFound = true;
|
||||
|
||||
unset($this->receivingFlows[$index]);
|
||||
$this->continueFlow($flow, $packet);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$flowFound) {
|
||||
$this->emitWarning(
|
||||
new \LogicException(sprintf('Received unexpected packet of type %d.', $packet->getPacketType()))
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->emitWarning(
|
||||
new \LogicException(sprintf('Cannot handle packet of type %d.', $packet->getPacketType()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles outgoing packets.
|
||||
*/
|
||||
private function handleSend()
|
||||
{
|
||||
$flow = null;
|
||||
if ($this->writtenFlow !== null) {
|
||||
$flow = $this->writtenFlow;
|
||||
$this->writtenFlow = null;
|
||||
}
|
||||
|
||||
if (count($this->sendingFlows) > 0) {
|
||||
$this->writtenFlow = array_shift($this->sendingFlows);
|
||||
$this->stream->write($this->writtenFlow->getPacket());
|
||||
}
|
||||
|
||||
if ($flow !== null) {
|
||||
if ($flow->isFinished()) {
|
||||
$this->loop->nextTick(function () use ($flow) {
|
||||
$this->finishFlow($flow);
|
||||
});
|
||||
} else {
|
||||
$this->receivingFlows[] = $flow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles closing of the stream.
|
||||
*/
|
||||
private function handleClose()
|
||||
{
|
||||
foreach ($this->timer as $timer) {
|
||||
$this->loop->cancelTimer($timer);
|
||||
}
|
||||
$this->timer = [];
|
||||
|
||||
$this->cleanPreviousSession();
|
||||
|
||||
$connection = $this->connection;
|
||||
|
||||
$this->isConnecting = false;
|
||||
$this->isDisconnecting = false;
|
||||
$this->isConnected = false;
|
||||
$this->connection = null;
|
||||
$this->stream = null;
|
||||
|
||||
if ($connection !== null) {
|
||||
$this->emit('close', [$connection, $this]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles errors of the stream.
|
||||
*
|
||||
* @param \Exception $e
|
||||
*/
|
||||
private function handleError(\Exception $e)
|
||||
{
|
||||
$this->emitError($e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the given flow.
|
||||
*
|
||||
* @param Flow $flow
|
||||
* @param bool $isSilent
|
||||
*
|
||||
* @return ExtendedPromiseInterface
|
||||
*/
|
||||
private function startFlow(Flow $flow, $isSilent = false)
|
||||
{
|
||||
try {
|
||||
$packet = $flow->start();
|
||||
} catch (\Exception $e) {
|
||||
$this->emitError($e);
|
||||
|
||||
return new RejectedPromise($e);
|
||||
}
|
||||
|
||||
$deferred = new Deferred();
|
||||
$internalFlow = new ReactFlow($flow, $deferred, $packet, $isSilent);
|
||||
|
||||
if ($packet !== null) {
|
||||
if ($this->writtenFlow !== null) {
|
||||
$this->sendingFlows[] = $internalFlow;
|
||||
} else {
|
||||
$this->stream->write($packet);
|
||||
$this->writtenFlow = $internalFlow;
|
||||
$this->handleSend();
|
||||
}
|
||||
} else {
|
||||
$this->loop->nextTick(function () use ($internalFlow) {
|
||||
$this->finishFlow($internalFlow);
|
||||
});
|
||||
}
|
||||
|
||||
return $deferred->promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Continues the given flow.
|
||||
*
|
||||
* @param ReactFlow $flow
|
||||
* @param Packet $packet
|
||||
*/
|
||||
private function continueFlow(ReactFlow $flow, Packet $packet)
|
||||
{
|
||||
try {
|
||||
$response = $flow->next($packet);
|
||||
} catch (\Exception $e) {
|
||||
$this->emitError($e);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($response !== null) {
|
||||
if ($this->writtenFlow !== null) {
|
||||
$this->sendingFlows[] = $flow;
|
||||
} else {
|
||||
$this->stream->write($response);
|
||||
$this->writtenFlow = $flow;
|
||||
$this->handleSend();
|
||||
}
|
||||
} elseif ($flow->isFinished()) {
|
||||
$this->loop->nextTick(function () use ($flow) {
|
||||
$this->finishFlow($flow);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the given flow.
|
||||
*
|
||||
* @param ReactFlow $flow
|
||||
*/
|
||||
private function finishFlow(ReactFlow $flow)
|
||||
{
|
||||
if ($flow->isSuccess()) {
|
||||
if (!$flow->isSilent()) {
|
||||
$this->emit($flow->getCode(), [$flow->getResult(), $this]);
|
||||
}
|
||||
|
||||
$flow->getDeferred()->resolve($flow->getResult());
|
||||
} else {
|
||||
$result = new \RuntimeException($flow->getErrorMessage());
|
||||
$this->emitWarning($result);
|
||||
|
||||
$flow->getDeferred()->reject($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans previous session by rejecting all pending flows.
|
||||
*/
|
||||
private function cleanPreviousSession()
|
||||
{
|
||||
$error = new \RuntimeException('Connection has been closed.');
|
||||
foreach ($this->receivingFlows as $receivingFlow) {
|
||||
$receivingFlow->getDeferred()->reject($error);
|
||||
}
|
||||
$this->receivingFlows = [];
|
||||
foreach ($this->sendingFlows as $sendingFlow) {
|
||||
$sendingFlow->getDeferred()->reject($error);
|
||||
}
|
||||
$this->sendingFlows = [];
|
||||
}
|
||||
}
|
||||
102
vendor/valga/fbns-react/src/Lite/StreamParser.php
vendored
Executable file
102
vendor/valga/fbns-react/src/Lite/StreamParser.php
vendored
Executable file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of net-mqtt.
|
||||
*
|
||||
* Copyright (c) 2015 Sebastian Mößler code@binsoul.de
|
||||
*
|
||||
* This source file is subject to the MIT license.
|
||||
*/
|
||||
|
||||
namespace Fbns\Client\Lite;
|
||||
|
||||
use BinSoul\Net\Mqtt\Exception\EndOfStreamException;
|
||||
use BinSoul\Net\Mqtt\Exception\MalformedPacketException;
|
||||
use BinSoul\Net\Mqtt\Exception\UnknownPacketTypeException;
|
||||
use BinSoul\Net\Mqtt\Packet;
|
||||
use BinSoul\Net\Mqtt\PacketStream;
|
||||
use BinSoul\Net\Mqtt\StreamParser as BaseStreamParser;
|
||||
|
||||
/**
|
||||
* Provides methods to parse a stream of bytes into packets.
|
||||
*/
|
||||
class StreamParser extends BaseStreamParser
|
||||
{
|
||||
/** @var PacketStream */
|
||||
private $buffer;
|
||||
/** @var PacketFactory */
|
||||
private $factory;
|
||||
/** @var callable */
|
||||
private $errorCallback;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->buffer = new PacketStream();
|
||||
$this->factory = new PacketFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an error callback.
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function onError($callback)
|
||||
{
|
||||
$this->errorCallback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the given data to the internal buffer and parses it.
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return Packet[]
|
||||
*/
|
||||
public function push($data)
|
||||
{
|
||||
$this->buffer->write($data);
|
||||
|
||||
$result = [];
|
||||
while ($this->buffer->getRemainingBytes() > 0) {
|
||||
$type = $this->buffer->readByte() >> 4;
|
||||
try {
|
||||
$packet = $this->factory->build($type);
|
||||
} catch (UnknownPacketTypeException $e) {
|
||||
$this->handleError($e);
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->buffer->seek(-1);
|
||||
$position = $this->buffer->getPosition();
|
||||
try {
|
||||
$packet->read($this->buffer);
|
||||
$result[] = $packet;
|
||||
$this->buffer->cut();
|
||||
} catch (EndOfStreamException $e) {
|
||||
$this->buffer->setPosition($position);
|
||||
break;
|
||||
} catch (MalformedPacketException $e) {
|
||||
$this->handleError($e);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the registered error callback.
|
||||
*
|
||||
* @param \Throwable $exception
|
||||
*/
|
||||
private function handleError($exception)
|
||||
{
|
||||
if ($this->errorCallback !== null) {
|
||||
$callback = $this->errorCallback;
|
||||
$callback($exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
153
vendor/valga/fbns-react/src/Message/Push.php
vendored
Executable file
153
vendor/valga/fbns-react/src/Message/Push.php
vendored
Executable file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client\Message;
|
||||
|
||||
use Fbns\Client\Json;
|
||||
|
||||
class Push
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $json;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $token;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $connectionKey;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $packageName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $collapseKey;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $payload;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $notificationId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $isBuffered;
|
||||
|
||||
/**
|
||||
* @param string $json
|
||||
*/
|
||||
private function parseJson($json)
|
||||
{
|
||||
$data = Json::decode($json);
|
||||
$this->json = $json;
|
||||
|
||||
if (isset($data->token)) {
|
||||
$this->token = (string) $data->token;
|
||||
}
|
||||
if (isset($data->ck)) {
|
||||
$this->connectionKey = (string) $data->ck;
|
||||
}
|
||||
if (isset($data->pn)) {
|
||||
$this->packageName = (string) $data->pn;
|
||||
}
|
||||
if (isset($data->cp)) {
|
||||
$this->collapseKey = (string) $data->cp;
|
||||
}
|
||||
if (isset($data->fbpushnotif)) {
|
||||
$this->payload = (string) $data->fbpushnotif;
|
||||
}
|
||||
if (isset($data->nid)) {
|
||||
$this->notificationId = (string) $data->nid;
|
||||
}
|
||||
if (isset($data->bu)) {
|
||||
$this->isBuffered = (string) $data->bu;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Message constructor.
|
||||
*
|
||||
* @param string $json
|
||||
*/
|
||||
public function __construct($json)
|
||||
{
|
||||
$this->parseJson($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getConnectionKey()
|
||||
{
|
||||
return $this->connectionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPackageName()
|
||||
{
|
||||
return $this->packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCollapseKey()
|
||||
{
|
||||
return $this->collapseKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPayload()
|
||||
{
|
||||
return $this->payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getNotificationId()
|
||||
{
|
||||
return $this->notificationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIsBuffered()
|
||||
{
|
||||
return $this->isBuffered;
|
||||
}
|
||||
}
|
||||
89
vendor/valga/fbns-react/src/Message/Register.php
vendored
Executable file
89
vendor/valga/fbns-react/src/Message/Register.php
vendored
Executable file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client\Message;
|
||||
|
||||
use Fbns\Client\Json;
|
||||
|
||||
class Register
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $json;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $packageName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $token;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* @param string $json
|
||||
*/
|
||||
private function parseJson($json)
|
||||
{
|
||||
$data = Json::decode($json);
|
||||
$this->json = $json;
|
||||
|
||||
if (isset($data->pkg_name)) {
|
||||
$this->packageName = (string) $data->pkg_name;
|
||||
}
|
||||
if (isset($data->token)) {
|
||||
$this->token = (string) $data->token;
|
||||
}
|
||||
if (isset($data->error)) {
|
||||
$this->error = (string) $data->error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Message constructor.
|
||||
*
|
||||
* @param string $json
|
||||
*/
|
||||
public function __construct($json)
|
||||
{
|
||||
$this->parseJson($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->json;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPackageName()
|
||||
{
|
||||
return $this->packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
}
|
||||
24
vendor/valga/fbns-react/src/Thrift/Compact.php
vendored
Executable file
24
vendor/valga/fbns-react/src/Thrift/Compact.php
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client\Thrift;
|
||||
|
||||
/**
|
||||
* @see https://thrift.apache.org/
|
||||
*/
|
||||
class Compact
|
||||
{
|
||||
const TYPE_STOP = 0x00;
|
||||
const TYPE_TRUE = 0x01;
|
||||
const TYPE_FALSE = 0x02;
|
||||
const TYPE_BYTE = 0x03;
|
||||
const TYPE_I16 = 0x04;
|
||||
const TYPE_I32 = 0x05;
|
||||
const TYPE_I64 = 0x06;
|
||||
const TYPE_DOUBLE = 0x07;
|
||||
const TYPE_BINARY = 0x08;
|
||||
const TYPE_LIST = 0x09;
|
||||
const TYPE_SET = 0x0A;
|
||||
const TYPE_MAP = 0x0B;
|
||||
const TYPE_STRUCT = 0x0C;
|
||||
const TYPE_FLOAT = 0x0D;
|
||||
}
|
||||
52
vendor/valga/fbns-react/src/Thrift/Debug.php
vendored
Executable file
52
vendor/valga/fbns-react/src/Thrift/Debug.php
vendored
Executable file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client\Thrift;
|
||||
|
||||
class Debug extends Reader
|
||||
{
|
||||
/**
|
||||
* @param string $context
|
||||
* @param int $field
|
||||
* @param mixed $value
|
||||
* @param int $type
|
||||
*/
|
||||
private function handler($context, $field, $value, $type)
|
||||
{
|
||||
if (strlen($context)) {
|
||||
$field = $context.'/'.$field;
|
||||
}
|
||||
if (is_bool($value)) {
|
||||
$value = $value ? 'true' : 'false';
|
||||
} elseif (is_array($value)) {
|
||||
$value = array_map(function ($value) {
|
||||
if (is_bool($value)) {
|
||||
$value = $value ? 'true' : 'false';
|
||||
} elseif (is_string($value)) {
|
||||
$value = '"'.$value.'"';
|
||||
} else {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}, $value);
|
||||
$value = '['.implode(', ', $value).']';
|
||||
} elseif (is_string($value)) {
|
||||
$value = '"'.$value.'"';
|
||||
} else {
|
||||
$value = (string) $value;
|
||||
}
|
||||
printf('%s (%02x): %s%s', $field, $type, $value, PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug constructor.
|
||||
*
|
||||
* @param string $buffer
|
||||
*/
|
||||
public function __construct($buffer = '')
|
||||
{
|
||||
parent::__construct($buffer, function ($context, $field, $value, $type) {
|
||||
$this->handler($context, $field, $value, $type);
|
||||
});
|
||||
}
|
||||
}
|
||||
263
vendor/valga/fbns-react/src/Thrift/Reader.php
vendored
Executable file
263
vendor/valga/fbns-react/src/Thrift/Reader.php
vendored
Executable file
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client\Thrift;
|
||||
|
||||
/**
|
||||
* WARNING: This implementation is not complete.
|
||||
*
|
||||
* @see https://thrift.apache.org/
|
||||
*/
|
||||
class Reader
|
||||
{
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
private $stack;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $field;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $buffer;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $length;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $position;
|
||||
|
||||
/**
|
||||
* @var callable|null
|
||||
*/
|
||||
private $handler;
|
||||
|
||||
/**
|
||||
* Reader constructor.
|
||||
*
|
||||
* @param string $buffer
|
||||
* @param callable|null $handler
|
||||
*/
|
||||
public function __construct($buffer = '', callable $handler = null)
|
||||
{
|
||||
if (PHP_INT_SIZE === 4 && !extension_loaded('gmp')) {
|
||||
throw new \RuntimeException('You need to install GMP extension to run this code with x86 PHP build.');
|
||||
}
|
||||
$this->buffer = $buffer;
|
||||
$this->position = 0;
|
||||
$this->length = strlen($buffer);
|
||||
$this->field = 0;
|
||||
$this->stack = [];
|
||||
$this->handler = $handler;
|
||||
$this->parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parser.
|
||||
*/
|
||||
private function parse()
|
||||
{
|
||||
$context = '';
|
||||
while ($this->position < $this->length) {
|
||||
$type = $this->readField();
|
||||
switch ($type) {
|
||||
case Compact::TYPE_STRUCT:
|
||||
array_push($this->stack, $this->field);
|
||||
$this->field = 0;
|
||||
$context = implode('/', $this->stack);
|
||||
break;
|
||||
case Compact::TYPE_STOP:
|
||||
if (!count($this->stack)) {
|
||||
return;
|
||||
}
|
||||
$this->field = array_pop($this->stack);
|
||||
$context = implode('/', $this->stack);
|
||||
break;
|
||||
case Compact::TYPE_LIST:
|
||||
$sizeAndType = $this->readUnsignedByte();
|
||||
$size = $sizeAndType >> 4;
|
||||
$listType = $sizeAndType & 0x0f;
|
||||
if ($size === 0x0f) {
|
||||
$size = $this->readVarint();
|
||||
}
|
||||
$this->handleField($context, $this->field, $this->readList($size, $listType), $listType);
|
||||
break;
|
||||
case Compact::TYPE_TRUE:
|
||||
case Compact::TYPE_FALSE:
|
||||
$this->handleField($context, $this->field, $type === Compact::TYPE_TRUE, $type);
|
||||
break;
|
||||
case Compact::TYPE_BYTE:
|
||||
$this->handleField($context, $this->field, $this->readSignedByte(), $type);
|
||||
break;
|
||||
case Compact::TYPE_I16:
|
||||
case Compact::TYPE_I32:
|
||||
case Compact::TYPE_I64:
|
||||
$this->handleField($context, $this->field, $this->fromZigZag($this->readVarint()), $type);
|
||||
break;
|
||||
case Compact::TYPE_BINARY:
|
||||
$this->handleField($context, $this->field, $this->readString($this->readVarint()), $type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $size
|
||||
* @param int $type
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function readList($size, $type)
|
||||
{
|
||||
$result = [];
|
||||
switch ($type) {
|
||||
case Compact::TYPE_TRUE:
|
||||
case Compact::TYPE_FALSE:
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
$result[] = $this->readSignedByte() === Compact::TYPE_TRUE;
|
||||
}
|
||||
break;
|
||||
case Compact::TYPE_BYTE:
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
$result[] = $this->readSignedByte();
|
||||
}
|
||||
break;
|
||||
case Compact::TYPE_I16:
|
||||
case Compact::TYPE_I32:
|
||||
case Compact::TYPE_I64:
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
$result[] = $this->fromZigZag($this->readVarint());
|
||||
}
|
||||
break;
|
||||
case Compact::TYPE_BINARY:
|
||||
$result[] = $this->readString($this->readVarint());
|
||||
break;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function readField()
|
||||
{
|
||||
$typeAndDelta = ord($this->buffer[$this->position++]);
|
||||
if ($typeAndDelta === Compact::TYPE_STOP) {
|
||||
return Compact::TYPE_STOP;
|
||||
}
|
||||
$delta = $typeAndDelta >> 4;
|
||||
if ($delta === 0) {
|
||||
$this->field = $this->fromZigZag($this->readVarint());
|
||||
} else {
|
||||
$this->field += $delta;
|
||||
}
|
||||
$type = $typeAndDelta & 0x0f;
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function readSignedByte()
|
||||
{
|
||||
$result = $this->readUnsignedByte();
|
||||
if ($result > 0x7f) {
|
||||
$result = 0 - (($result - 1) ^ 0xff);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function readUnsignedByte()
|
||||
{
|
||||
return ord($this->buffer[$this->position++]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
private function readVarint()
|
||||
{
|
||||
$shift = 0;
|
||||
$result = 0;
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$result = gmp_init($result, 10);
|
||||
}
|
||||
while ($this->position < $this->length) {
|
||||
$byte = ord($this->buffer[$this->position++]);
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$byte = gmp_init($byte, 10);
|
||||
}
|
||||
$result |= ($byte & 0x7f) << $shift;
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$byte = (int) gmp_strval($byte, 10);
|
||||
}
|
||||
if ($byte >> 7 === 0) {
|
||||
break;
|
||||
}
|
||||
$shift += 7;
|
||||
}
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$result = gmp_strval($result, 10);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $n
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function fromZigZag($n)
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$n = gmp_init($n, 10);
|
||||
}
|
||||
$result = ($n >> 1) ^ -($n & 1);
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$result = gmp_strval($result, 10);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function readString($length)
|
||||
{
|
||||
$result = substr($this->buffer, $this->position, $length);
|
||||
$this->position += $length;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $context
|
||||
* @param int $field
|
||||
* @param mixed $value
|
||||
* @param int $type
|
||||
*/
|
||||
private function handleField($context, $field, $value, $type)
|
||||
{
|
||||
if (!is_callable($this->handler)) {
|
||||
return;
|
||||
}
|
||||
call_user_func($this->handler, $context, $field, $value, $type);
|
||||
}
|
||||
}
|
||||
279
vendor/valga/fbns-react/src/Thrift/Writer.php
vendored
Executable file
279
vendor/valga/fbns-react/src/Thrift/Writer.php
vendored
Executable file
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
namespace Fbns\Client\Thrift;
|
||||
|
||||
/**
|
||||
* WARNING: This implementation is not complete.
|
||||
*
|
||||
* @see https://thrift.apache.org/
|
||||
*/
|
||||
class Writer
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $buffer;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $field;
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
private $stack;
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
* @param int $bits
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
private function toZigZag($number, $bits)
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$number = gmp_init($number, 10);
|
||||
}
|
||||
$result = ($number << 1) ^ ($number >> ($bits - 1));
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$result = gmp_strval($result, 10);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*/
|
||||
private function writeByte($number)
|
||||
{
|
||||
$this->buffer .= chr($number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*/
|
||||
private function writeWord($number)
|
||||
{
|
||||
$this->writeVarint($this->toZigZag($number, 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*/
|
||||
private function writeInt($number)
|
||||
{
|
||||
$this->writeVarint($this->toZigZag($number, 32));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*/
|
||||
private function writeLongInt($number)
|
||||
{
|
||||
$this->writeVarint($this->toZigZag($number, 64));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
* @param int $type
|
||||
*/
|
||||
private function writeField($field, $type)
|
||||
{
|
||||
$delta = $field - $this->field;
|
||||
if ((0 < $delta) && ($delta <= 15)) {
|
||||
$this->writeByte(($delta << 4) | $type);
|
||||
} else {
|
||||
$this->writeByte($type);
|
||||
$this->writeWord($field);
|
||||
}
|
||||
$this->field = $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*/
|
||||
private function writeVarint($number)
|
||||
{
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$number = gmp_init($number, 10);
|
||||
}
|
||||
while (true) {
|
||||
$byte = $number & (~0x7f);
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$byte = (int) gmp_strval($byte, 10);
|
||||
}
|
||||
if ($byte === 0) {
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$number = (int) gmp_strval($number, 10);
|
||||
}
|
||||
$this->buffer .= chr($number);
|
||||
break;
|
||||
} else {
|
||||
$byte = ($number & 0xff) | 0x80;
|
||||
if (PHP_INT_SIZE === 4) {
|
||||
$byte = (int) gmp_strval($byte, 10);
|
||||
}
|
||||
$this->buffer .= chr($byte);
|
||||
$number = $number >> 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*/
|
||||
private function writeBinary($data)
|
||||
{
|
||||
$this->buffer .= $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
* @param bool $value
|
||||
*/
|
||||
public function writeBool($field, $value)
|
||||
{
|
||||
$this->writeField($field, $value ? Compact::TYPE_TRUE : Compact::TYPE_FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
* @param string $string
|
||||
*/
|
||||
public function writeString($field, $string)
|
||||
{
|
||||
$this->writeField($field, Compact::TYPE_BINARY);
|
||||
$this->writeVarint(strlen($string));
|
||||
$this->writeBinary($string);
|
||||
}
|
||||
|
||||
public function writeStop()
|
||||
{
|
||||
$this->buffer .= chr(Compact::TYPE_STOP);
|
||||
if (count($this->stack)) {
|
||||
$this->field = array_pop($this->stack);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
* @param int $number
|
||||
*/
|
||||
public function writeInt8($field, $number)
|
||||
{
|
||||
$this->writeField($field, Compact::TYPE_BYTE);
|
||||
$this->writeByte($number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
* @param int $number
|
||||
*/
|
||||
public function writeInt16($field, $number)
|
||||
{
|
||||
$this->writeField($field, Compact::TYPE_I16);
|
||||
$this->writeWord($number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
* @param int $number
|
||||
*/
|
||||
public function writeInt32($field, $number)
|
||||
{
|
||||
$this->writeField($field, Compact::TYPE_I32);
|
||||
$this->writeInt($number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
* @param int $number
|
||||
*/
|
||||
public function writeInt64($field, $number)
|
||||
{
|
||||
$this->writeField($field, Compact::TYPE_I64);
|
||||
$this->writeLongInt($number);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
* @param int $type
|
||||
* @param array $list
|
||||
*/
|
||||
public function writeList($field, $type, array $list)
|
||||
{
|
||||
$this->writeField($field, Compact::TYPE_LIST);
|
||||
$size = count($list);
|
||||
if ($size < 0x0f) {
|
||||
$this->writeByte(($size << 4) | $type);
|
||||
} else {
|
||||
$this->writeByte(0xf0 | $type);
|
||||
$this->writeVarint($size);
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case Compact::TYPE_TRUE:
|
||||
case Compact::TYPE_FALSE:
|
||||
foreach ($list as $value) {
|
||||
$this->writeByte($value ? Compact::TYPE_TRUE : Compact::TYPE_FALSE);
|
||||
}
|
||||
break;
|
||||
case Compact::TYPE_BYTE:
|
||||
foreach ($list as $number) {
|
||||
$this->writeByte($number);
|
||||
}
|
||||
break;
|
||||
case Compact::TYPE_I16:
|
||||
foreach ($list as $number) {
|
||||
$this->writeWord($number);
|
||||
}
|
||||
break;
|
||||
case Compact::TYPE_I32:
|
||||
foreach ($list as $number) {
|
||||
$this->writeInt($number);
|
||||
}
|
||||
break;
|
||||
case Compact::TYPE_I64:
|
||||
foreach ($list as $number) {
|
||||
$this->writeLongInt($number);
|
||||
}
|
||||
break;
|
||||
case Compact::TYPE_BINARY:
|
||||
foreach ($list as $string) {
|
||||
$this->writeVarint(strlen($string));
|
||||
$this->writeBinary($string);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $field
|
||||
*/
|
||||
public function writeStruct($field)
|
||||
{
|
||||
$this->writeField($field, Compact::TYPE_STRUCT);
|
||||
$this->stack[] = $this->field;
|
||||
$this->field = 0;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (PHP_INT_SIZE === 4 && !extension_loaded('gmp')) {
|
||||
throw new \RuntimeException('You need to install GMP extension to run this code with x86 PHP build.');
|
||||
}
|
||||
$this->buffer = '';
|
||||
$this->field = 0;
|
||||
$this->stack = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->buffer;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user