walkor / workerman

An asynchronous event driven PHP socket framework. Supports HTTP, Websocket, SSL and other custom protocols.
http://www.workerman.net
MIT License
11.17k stars 2.27k forks source link

permessage-deflate support problem #1052

Closed boooch closed 2 months ago

boooch commented 3 months ago

Hi All! I have problem with deflate support on websockets. if short messages from client to server - all working good. But if client send long message to server this long message decoded OK but next messages fail with error. I set this debug line in code:

 public static function decode($buffer, ConnectionInterface $connection)
    {
        $first_byte = \ord($buffer[0]);
        $second_byte = \ord($buffer[1]);
        $len = $second_byte & 127;
        $is_fin_frame = $first_byte >> 7;
        $rsv1 = 64 === ($first_byte & 64);
        echo 'len:'.$len.' '.$first_byte.' '.$second_byte.' '.bin2hex($buffer)."\n";

then start to send messages:

1

window.online_ws.send('137,18,184,199,74,187,141,2,196');

debug:                     len:31 193 159 c19ff99c3a38fd5dfb29f9bc36fb4919c6090dd480c79bd4e458481f815c495dabbb02a23a
decoded message:  137,18,184,199,74,187,141,2,196

2

window.online_ws.send('b1000_0');

debug:                       len:9 193 137 c189f4b977b5be8b4385c43140b5f4
decoded message:    b1000_0

then I send long message from browser:

3

window.online_ws.send('638,935,936,535,969,970,568,639,937,641,640,971,972,973,499,536,537,974,538,539,975,540,976,977,978,541,979,980,981,497,982,983,984,938,498,939,940,941,642,942,943,944,945,946,985,542,986,987,543,988,947,544,948,989,990,991,992,569,993,500,496,994,949,995,996,950,643,951,952,953,954,997,955,956,957,958,959,960,1003,834,998,1002,802,803,861,1374,813,870,876,823,878,493,1369,1371,489,860,1068,1067,871,872,862,863,815,1272,1018,1019,864,1070,612,731,1001,873,804,805,825,816,883,1005,824,1365,961,817,818,1201,906,1020,892,877,907,1066,610,631,567,826,827,908,566,617,857,909,910,911,912,913,914,915,916,917,918,919,865,819,880,920,921,609,821,822,600,607,962,866,922,894,1069,963,923,924,830,925,926,881,898,1006,851,828,927,867,1203,1007,1008,1372,632,633,624,622,553,554,888,728,634,1058,618,623,889,1271,895,896,545,814,884,490,891,1307,1308,1314,1279,1313,807,808,899,858,999,1202,869,635,552,625,608,897,879,893,547,928,929,930,882,1320,1321,829,636,868,492,1009,885,1010,1000,491,1011,801,831,1368,890,820,1012,532,1394,832,886,1013,1064,1014,1015,1016,1367,477,590,964,965,588,587,572,718,645,644,575,585,586,584,592,966,580,593,719,577,591,589,720,967,578,579,721,574,968,722,581,582,723,576,646,724,573,725,637,726,627,887,732,729,730,806,1357,1329,859,1017,874,875,852,853,1366,900,141');

debug:           len:126 193 254 c1fe023776f461265260a833b2d46d656d0e664a86569f3ded53ada7b2f00e94320e4f9cf39a3258c1247d8ce14a23519ee3951d1ef62c84cfc8e8dc14f2ac8598a697b9d4cabe609547c4b8957097867b6a674bd4490939cc3ff2dd66868d715925d6080cfbdc64d9255b9915996ec385a9954aad9bb02c9fd464742432c56deb373205af3bbe2c0fabe650e8fe35afbc0222c8c5fef45b1adb4b87483058b1cb823b49e409b7434d7c5aa9fb3faf47d12dd54bee63d90b0df00ee3083dbb6f0c2c6850e499ceed30e5586f6a8718e4777b59559ebc87a0ddcf89949145c6fe5ac2fbfb9db71e5ed89e17a5fb95fc0a3954b2e2bf374b7f8581a7bb42e9e698374dca1274eb4fd3ebf98aa76a55590e74b1c39e5eeaeb64a7dc67e3d45b0c115322436ed954eefe7ac2f218f1cae2189279537f6f5eb8cdfd268a97a135e4faa2f29a01d62d138033cd0da9778a992b9e5846b88201db5248cef28c3d210251ef40857bc762ef833b2eab22ceb8d04c9cede60568bb7fba9f82f0dd637d065965989be9c69338afc38e854a60beea9833a1b37f821305d8b3aecb49a673a4718644fae2bb17e6774c4eb890d4d86f29043f63dfd29dfc7d6ee5cde31761bd50ff375bedff50cf55bce72c505b7091e64889a4d18ec6d745f1c322df2001227ba2da843d4e3d197cd91c960e89f51d6dc15d1cb264418c659fc640ccbde1b5acc7ecbb5fe0ee8ea56c2351033f599cb4bfbf2cf5d96d15bbbd8c1551ee98bb9299c4b69814c857ed8d62a86f45d482d7e2eb5ae3204694fbbeb286de990c62

decoded message:       message 638,935,936,535,969,970,568,639,937,641,640,971,972,973,499,536,537,974,538,539,975,540,976,977,978,541,979,980,981,497,982,983,984,938,498,939,940,941,642,942,943,944,945,946,985,542,986,987,543,988,947,544,948,989,990,991,992,569,993,500,496,994,949,995,996,950,643,951,952,953,954,997,955,956,957,958,959,960,1003,834,998,1002,802,803,861,1374,813,870,876,823,878,493,1369,1371,489,860,1068,1067,871,872,862,863,815,1272,1018,1019,864,1070,612,731,1001,873,804,805,825,816,883,1005,824,1365,961,817,818,1201,906,1020,892,877,907,1066,610,631,567,826,827,908,566,617,857,909,910,911,912,913,914,915,916,917,918,919,865,819,880,920,921,609,821,822,600,607,962,866,922,894,1069,963,923,924,830,925,926,881,898,1006,851,828,927,867,1203,1007,1008,1372,632,633,624,622,553,554,888,728,634,1058,618,623,889,1271,895,896,545,814,884,490,891,1307,1308,1314,1279,1313,807,808,899,858,999,1202,869,635,552,625,608,897,879,893,547,928,929,930,882,1320,1321,829,636,868,492,1009,885,1010,1000,491,1011,801,831,1368,890,820,1012,532,1394,832,886,1013,1064,1014,1015,1016,1367,477,590,964,965,588,587,572,718,645,644,575,585,586,584,592,966,580,593,719,577,591,589,720,967,578,579,721,574,968,722,581,582,723,576,646,724,573,725,637,726,627,887,732,729,730,806,1357,1329,859,1017,874,875,852,853,1366,900,141

4

window.online_ws.send('b1000_0');

debug:      len:5 193 133 c18573fd27daf16b61da73

ERROR: Aug 21 23:44:36 dev ws_server[1382787]: PHP Warning: inflate_add(): data error in /var/www/html/Pilot7_boooch/cron/vendor/workerman/workerman/Protocols/Websocket.php on line 377

All other messages after this error have thу same error even if they have only 1 symbol.

after reconnection all working well again

fuzqing commented 2 months ago

有两个方法来修复这个错误

第一种方式,修改 workerman 的源码,inflate_init 函数的 window 参数改为 15,如下:

    /**
     * Inflate.
     *
     * @param $connection
     * @param $buffer
     * @param $is_fin_frame
     * @return false|string
     */
    protected static function inflate($connection, $buffer, $is_fin_frame)
    {
        if (!isset($connection->context->inflator)) {
            $connection->context->inflator = \inflate_init(
                \ZLIB_ENCODING_RAW,
                [
                    'level'    => -1,
                    'memory'   => 8,
                    'window'   => 15,
                    'strategy' => \ZLIB_DEFAULT_STRATEGY
                ]
            );
        }
        if ($is_fin_frame) {
            $buffer .= "\x00\x00\xff\xff";
        }
        return \inflate_add($connection->context->inflator, $buffer);
    }

    /**
     * Deflate.
     *
     * @param $connection
     * @param $buffer
     * @return false|string
     */
    protected static function deflate($connection, $buffer)
    {
        if (!isset($connection->context->deflator)) {
            $connection->context->deflator = \deflate_init(
                \ZLIB_ENCODING_RAW,
                [
                    'level'    => -1,
                    'memory'   => 8,
                    'window'   => 15,
                    'strategy' => \ZLIB_DEFAULT_STRATEGY
                ]
            );
        }
        return \substr(\deflate_add($connection->context->deflator, $buffer), 0, -4);
    }

第二种方式,设置响应头:

<?php
require_once __DIR__ . '/vendor/autoload.php';

use Workerman\Connection\TcpConnection;
use Workerman\Protocols\Websocket;
use Workerman\Worker;

$worker = new Worker('websocket://127.0.0.1:8080');

$worker->onWebSocketConnect = function ($connection) {
    // 告诉浏览器服务端支持 permessage-deflate
    $connection->headers = [
        'sec-websocket-extensions: permessage-deflate; server_no_context_takeover; client_max_window_bits=9' //这个值必须为 9
    ];
    // 服务端设置websocket类型为 permessage-deflate,发送数据会自动压缩
    $connection->websocketType = Websocket::BINARY_TYPE_BLOB_DEFLATE;
};

$worker->onMessage = function (TcpConnection $connection, $data)
{
    $connection->send('hello');
};

Worker::runAll();
boooch commented 2 months ago

will check both, thank you!

boooch commented 2 months ago

Working well ! Thank you!!