diff --git a/docs/zh-cn/README.md b/docs/zh-cn/README.md index 2304abb..1074459 100644 --- a/docs/zh-cn/README.md +++ b/docs/zh-cn/README.md @@ -20,21 +20,13 @@ composer require simps/mqtt 参考 [examples](https://github.com/simps/mqtt/tree/master/examples) 目录 -## 捐献及赞助 :id=donate +## 关注 -### 一次性赞助 +![](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/202012/wechat_white.png) -如果您是个人开发者并且 PHPMQTT 给您解决燃眉之急或带来些许明朗,您可以打赏一杯咖啡或一杯香茗 :) +## 赞赏 :id=donate -我们通过以下方式接受赞助: +如果给您解决燃眉之急或带来些许明朗,您可以打赏一杯咖啡或一杯香茗 :) -![alipay](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/alipay.jpg ':size=362x562') -![wechat](https://cdn.jsdelivr.net/gh/sy-records/staticfile/images/wechatpay.png ':size=autox562') +[donate](https://donate.qq52o.me/ ':include :type=iframe') -### 周期性赞助 - -如果您是企业经营者并且将 PHPMQTT 用在商业产品中,那么赞助 PHPMQTT 有商业上的益处:可以让您的产品所依赖的类库保持健康并得到积极的升级维护,也能获得一些技术支持。 - -周期性赞助可以获得额外的回报,比如您的名字或组织/公司 Logo 及链接会出现在 PHPMQTT 的 GitHub 仓库中。 - -> 如您希望为 PHPMQTT 提供周期性的赞助,可邮件至 lufei@simps.io diff --git a/examples/getLevel.php b/examples/getLevel.php new file mode 100644 index 0000000..1f7ee20 --- /dev/null +++ b/examples/getLevel.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, + * please view the LICENSE file that was distributed with this source code + */ + +include __DIR__ . '/bootstrap.php'; + +use Simps\MQTT\Protocol\Types; +use Simps\MQTT\Protocol\V3; +use Simps\MQTT\Protocol\V5; +use Simps\MQTT\Tools\UnPackTool; +use Simps\MQTT\Protocol\ProtocolInterface; + +$server = new Swoole\Server('127.0.0.1', 1883, SWOOLE_BASE); + +$server->set( + [ + 'open_mqtt_protocol' => true, + 'worker_num' => 1, + 'package_max_length' => 2 * 1024 * 1024, + ] +); + +$server->on('connect', function ($server, $fd) { + echo "Client #{$fd}: Connect.\n"; +}); + +$server->on('receive', function (Swoole\Server $server, $fd, $from_id, $data) { + $type = UnPackTool::getType($data); + if ($type === Types::CONNECT) { + $level = UnPackTool::getLevel($data); + $class = $level === ProtocolInterface::MQTT_PROTOCOL_LEVEL_5_0 ? V5::class : V3::class; + $server->fds[$fd] = ['level' => $level, 'class' => $class]; + } + /** @var ProtocolInterface $unpack */ + $unpack = $server->fds[$fd]['class']; + var_dump($unpack::unpack($data)); +}); + +$server->on('close', function ($server, $fd) { + unset($server->fds[$fd]); + echo "Client #{$fd}: Close.\n"; +}); + +$server->start(); diff --git a/src/Tools/UnPackTool.php b/src/Tools/UnPackTool.php index 678dfa7..2da2b88 100644 --- a/src/Tools/UnPackTool.php +++ b/src/Tools/UnPackTool.php @@ -13,7 +13,9 @@ namespace Simps\MQTT\Tools; +use Simps\MQTT\Exception\InvalidArgumentException; use Simps\MQTT\Exception\LengthException; +use Simps\MQTT\Protocol\Types; class UnPackTool extends Common { @@ -97,4 +99,21 @@ public static function getRemaining(string $data): string return substr($data, $headBytes, $remainingLength); } + + /** + * Get the MQTT protocol level. + */ + public static function getLevel(string $data): int + { + $type = static::getType($data); + + if ($type !== Types::CONNECT) { + throw new InvalidArgumentException(sprintf('packet must be of type connect, %s given', Types::getType($type))); + } + + $remaining = static::getRemaining($data); + $length = unpack('n', $remaining)[1]; + + return ord($remaining[$length + 2]); + } } diff --git a/tests/Unit/ToolsTest.php b/tests/Unit/ToolsTest.php new file mode 100644 index 0000000..0634df1 --- /dev/null +++ b/tests/Unit/ToolsTest.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, + * please view the LICENSE file that was distributed with this source code + */ + +declare(strict_types=1); + +namespace SimpsTest\MQTT\Unit; + +use PHPUnit\Framework\TestCase; +use Simps\MQTT\Exception\InvalidArgumentException; +use Simps\MQTT\Protocol\ProtocolInterface; +use Simps\MQTT\Tools\UnPackTool; + +/** + * @internal + * @coversNothing + */ +class ToolsTest extends TestCase +{ + public function testGetLevel() + { + $connect_31 = '104400064d51497364700306000a001353696d70735f36313362316164323236626334001973696d70732d6d7174742f757365723030312f64656c6574650006627965627965'; + $connect_311 = '104200044d5154540406000a001353696d70735f36313362313830323035636633001973696d70732d6d7174742f757365723030312f64656c6574650006627965627965'; + $connect_50 = '106200044d515454050e000a0b110000003c21ffff22ffff001353696d70735f3631336231613330313962663213180000003c020000003c030004746573740101001973696d70732d6d7174742f757365723030312f64656c6574650006627965627965'; + $this->assertSame(UnPackTool::getLevel(hex2bin($connect_31)), ProtocolInterface::MQTT_PROTOCOL_LEVEL_3_1); + $this->assertSame(UnPackTool::getLevel(hex2bin($connect_311)), ProtocolInterface::MQTT_PROTOCOL_LEVEL_3_1_1); + $this->assertSame(UnPackTool::getLevel(hex2bin($connect_50)), ProtocolInterface::MQTT_PROTOCOL_LEVEL_5_0); + } + + public function testInvalidGetLevel() + { + try { + $connAck = '200200'; + UnPackTool::getLevel(hex2bin($connAck)); + } catch (\Throwable $ex) { + $this->assertInstanceOf(InvalidArgumentException::class, $ex); + $this->assertSame($ex->getMessage(), 'packet must be of type connect, connack given'); + } + } +}