You've already forked qlg.tsgz.moe
Init Repo
This commit is contained in:
27
vendor/swoole/tests/include/api/swoole_websocket_server/send_large_request_data.php
vendored
Executable file
27
vendor/swoole/tests/include/api/swoole_websocket_server/send_large_request_data.php
vendored
Executable file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . "/../../../include/bootstrap.php";
|
||||
require "websocket_client.php";
|
||||
|
||||
function send_large_request_data($host, $port)
|
||||
{
|
||||
$client = new WebSocketClient($host, $port);
|
||||
if (!$client->connect())
|
||||
{
|
||||
echo "send failed, errCode={$client->errCode}\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
$data = str_repeat("data", 40000);
|
||||
for ($i = 0; $i < 100; $i++)
|
||||
{
|
||||
if (!$client->send($data))
|
||||
{
|
||||
echo "send failed, errCode={$client->errCode}\n";
|
||||
return false;
|
||||
}
|
||||
$response = $client->recv();
|
||||
assert($response == "SUCCESS", "response failed");
|
||||
}
|
||||
return true;
|
||||
}
|
18
vendor/swoole/tests/include/api/swoole_websocket_server/send_small_request_data.php
vendored
Executable file
18
vendor/swoole/tests/include/api/swoole_websocket_server/send_small_request_data.php
vendored
Executable file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . "/../../../include/bootstrap.php";
|
||||
require "websocket_client.php";
|
||||
|
||||
function send_small_request_data($host, $port)
|
||||
{
|
||||
$client = new WebSocketClient($host, $port);
|
||||
$client->connect();
|
||||
|
||||
$data = "";
|
||||
for ($i = 0; $i < 100; $i++)
|
||||
{
|
||||
$client->send($data);
|
||||
$response = $client->recv();
|
||||
assert($response == "SUCCESS", "response failed");
|
||||
}
|
||||
}
|
118
vendor/swoole/tests/include/api/swoole_websocket_server/swoole_websocket_server.php
vendored
Executable file
118
vendor/swoole/tests/include/api/swoole_websocket_server/swoole_websocket_server.php
vendored
Executable file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . "/../../../include/bootstrap.php";
|
||||
|
||||
class WebSocketServer
|
||||
{
|
||||
/**
|
||||
* @var \swoole_websocket_server
|
||||
*/
|
||||
public $webSocketServ;
|
||||
|
||||
public function __construct($host = WEBSOCKET_SERVER_HOST, $port = WEBSOCKET_SERVER_PORT)
|
||||
{
|
||||
$this->webSocketServ = new \swoole_websocket_server($host, $port);
|
||||
|
||||
$this->webSocketServ->set([
|
||||
// 输出限制
|
||||
"buffer_output_size" => 1024 * 1024 * 1024,
|
||||
|
||||
"max_connection" => 10240,
|
||||
"pipe_buffer_size" => 1024 * 1024 * 1024,
|
||||
|
||||
// 'enable_port_reuse' => true,
|
||||
'user' => 'www-data',
|
||||
'group' => 'www-data',
|
||||
|
||||
// 'log_file' => __DIR__.'/swoole.log',
|
||||
'open_tcp_nodelay' => 1,
|
||||
'open_cpu_affinity' => 1,
|
||||
'daemonize' => 0,
|
||||
'reactor_num' => 1,
|
||||
'worker_num' => 2,
|
||||
'max_request' => 100000,
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
$this->webSocketServ->on('start', [$this, 'onStart']);
|
||||
$this->webSocketServ->on('shutdown', [$this, 'onShutdown']);
|
||||
|
||||
$this->webSocketServ->on('workerStart', [$this, 'onWorkerStart']);
|
||||
$this->webSocketServ->on('workerStop', [$this, 'onWorkerStop']);
|
||||
$this->webSocketServ->on('workerError', [$this, 'onWorkerError']);
|
||||
|
||||
$this->webSocketServ->on('connect', [$this, 'onConnect']);
|
||||
$this->webSocketServ->on('request', [$this, 'onRequest']);
|
||||
|
||||
$this->webSocketServ->on('open', [$this, 'onOpen']);
|
||||
$this->webSocketServ->on('message', [$this, 'onMessage']);
|
||||
|
||||
$this->webSocketServ->on('close', [$this, 'onClose']);
|
||||
|
||||
$sock = $this->webSocketServ->getSocket();
|
||||
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) {
|
||||
echo 'Unable to set option on socket: '. socket_strerror(socket_last_error()) . PHP_EOL;
|
||||
}
|
||||
|
||||
$this->webSocketServ->start();
|
||||
}
|
||||
|
||||
public function onConnect()
|
||||
{
|
||||
debug_log("connecting ......");
|
||||
}
|
||||
|
||||
public function onClose()
|
||||
{
|
||||
debug_log("closing .....");
|
||||
}
|
||||
|
||||
public function onStart(\swoole_websocket_server $swooleServer)
|
||||
{
|
||||
debug_log("swoole_server starting .....");
|
||||
}
|
||||
|
||||
public function onShutdown(\swoole_websocket_server $swooleServer)
|
||||
{
|
||||
debug_log("swoole_server shutdown .....");
|
||||
}
|
||||
|
||||
public function onWorkerStart(\swoole_websocket_server $swooleServer, $workerId)
|
||||
{
|
||||
debug_log("worker #$workerId starting .....");
|
||||
}
|
||||
|
||||
public function onWorkerStop(\swoole_websocket_server $swooleServer, $workerId)
|
||||
{
|
||||
debug_log("worker #$workerId stopping ....");
|
||||
}
|
||||
|
||||
public function onWorkerError(\swoole_websocket_server $swooleServer, $workerId, $workerPid, $exitCode, $sigNo)
|
||||
{
|
||||
debug_log("worker error happening [workerId=$workerId, workerPid=$workerPid, exitCode=$exitCode, signalNo=$sigNo]...");
|
||||
}
|
||||
|
||||
public function onRequest(\swoole_http_request $request, \swoole_http_response $response)
|
||||
{
|
||||
$response->end("Hello World!");
|
||||
}
|
||||
|
||||
public function onOpen(swoole_websocket_server $server, $request)
|
||||
{
|
||||
debug_log("{$request->fd} opened");
|
||||
}
|
||||
|
||||
public function onMessage(swoole_websocket_server $server, $frame)
|
||||
{
|
||||
$server->push($frame->fd, "SUCCESS");
|
||||
}
|
||||
}
|
||||
|
||||
$host = isset($argv[1]) ? $argv[1] : WEBSOCKET_SERVER_HOST;
|
||||
$port = isset($argv[2]) ? $argv[2] : WEBSOCKET_SERVER_PORT;
|
||||
|
||||
$wsServer = new WebSocketServer($host, $port);
|
||||
$wsServer->start();
|
391
vendor/swoole/tests/include/api/swoole_websocket_server/websocket_client.php
vendored
Executable file
391
vendor/swoole/tests/include/api/swoole_websocket_server/websocket_client.php
vendored
Executable file
@@ -0,0 +1,391 @@
|
||||
<?php
|
||||
|
||||
class WebSocketClient
|
||||
{
|
||||
const VERSION = '0.1.4';
|
||||
const TOKEN_LENGHT = 16;
|
||||
const TYPE_ID_WELCOME = 0;
|
||||
const TYPE_ID_PREFIX = 1;
|
||||
const TYPE_ID_CALL = 2;
|
||||
const TYPE_ID_CALLRESULT = 3;
|
||||
const TYPE_ID_ERROR = 4;
|
||||
const TYPE_ID_SUBSCRIBE = 5;
|
||||
const TYPE_ID_UNSUBSCRIBE = 6;
|
||||
const TYPE_ID_PUBLISH = 7;
|
||||
const TYPE_ID_EVENT = 8;
|
||||
private $key;
|
||||
private $host;
|
||||
private $port;
|
||||
private $path;
|
||||
/**
|
||||
* @var swoole_client
|
||||
*/
|
||||
private $socket;
|
||||
private $buffer = '';
|
||||
private $origin = null;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $connected = false;
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @param int $port
|
||||
* @param string $path
|
||||
*/
|
||||
function __construct($host = '127.0.0.1', $port = 8080, $path = '/', $origin = null)
|
||||
{
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->path = $path;
|
||||
$this->origin = $origin;
|
||||
$this->key = $this->generateToken(self::TOKEN_LENGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect on destruct
|
||||
*/
|
||||
function __destruct()
|
||||
{
|
||||
$this->disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect client to swoole_server
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
$this->socket = new \swoole_client(SWOOLE_SOCK_TCP);
|
||||
if (!$this->socket->connect($this->host, $this->port))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$this->socket->send($this->createHeader());
|
||||
return $this->recv();
|
||||
}
|
||||
|
||||
public function getSocket()
|
||||
{
|
||||
return $this->socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from swoole_server
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$this->connected = false;
|
||||
$this->socket->close();
|
||||
}
|
||||
|
||||
public function recv()
|
||||
{
|
||||
$data = $this->socket->recv();
|
||||
if ($data === false)
|
||||
{
|
||||
echo "Error: {$this->socket->errMsg}";
|
||||
return false;
|
||||
}
|
||||
$this->buffer .= $data;
|
||||
$recv_data = $this->parseData($this->buffer);
|
||||
if ($recv_data)
|
||||
{
|
||||
$this->buffer = '';
|
||||
return $recv_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param string $type
|
||||
* @param bool $masked
|
||||
*/
|
||||
public function send($data, $type = 'text', $masked = true)
|
||||
{
|
||||
return $this->socket->send($this->hybi10Encode($data, $type, $masked));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse received data
|
||||
*
|
||||
* @param $response
|
||||
*/
|
||||
private function parseData($response)
|
||||
{
|
||||
if (!$this->connected && isset($response['Sec-Websocket-Accept']))
|
||||
{
|
||||
if (base64_encode(pack('H*', sha1($this->key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')))
|
||||
=== $response['Sec-Websocket-Accept']
|
||||
)
|
||||
{
|
||||
$this->connected = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \Exception("error response key.");
|
||||
}
|
||||
}
|
||||
return $this->hybi10Decode($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create header for websocket client
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function createHeader()
|
||||
{
|
||||
$host = $this->host;
|
||||
if ($host === '127.0.0.1' || $host === '0.0.0.0')
|
||||
{
|
||||
$host = 'localhost';
|
||||
}
|
||||
return "GET {$this->path} HTTP/1.1" . "\r\n" .
|
||||
"Origin: {$this->origin}" . "\r\n" .
|
||||
"Host: {$host}:{$this->port}" . "\r\n" .
|
||||
"Sec-WebSocket-Key: {$this->key}" . "\r\n" .
|
||||
"User-Agent: PHPWebSocketClient/" . self::VERSION . "\r\n" .
|
||||
"Upgrade: websocket" . "\r\n" .
|
||||
"Connection: Upgrade" . "\r\n" .
|
||||
"Sec-WebSocket-Protocol: wamp" . "\r\n" .
|
||||
"Sec-WebSocket-Version: 13" . "\r\n" . "\r\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse raw incoming data
|
||||
*
|
||||
* @param $header
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function parseIncomingRaw($header)
|
||||
{
|
||||
$retval = array();
|
||||
$content = "";
|
||||
$fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
|
||||
foreach ($fields as $field)
|
||||
{
|
||||
if (preg_match('/([^:]+): (.+)/m', $field, $match))
|
||||
{
|
||||
$match[1] = preg_replace_callback('/(?<=^|[\x09\x20\x2D])./',
|
||||
function ($matches)
|
||||
{
|
||||
return strtoupper($matches[0]);
|
||||
},
|
||||
strtolower(trim($match[1])));
|
||||
if (isset($retval[$match[1]]))
|
||||
{
|
||||
$retval[$match[1]] = array($retval[$match[1]], $match[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$retval[$match[1]] = trim($match[2]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (preg_match('!HTTP/1\.\d (\d)* .!', $field))
|
||||
{
|
||||
$retval["status"] = $field;
|
||||
}
|
||||
else
|
||||
{
|
||||
$content .= $field . "\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
$retval['content'] = $content;
|
||||
return $retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate token
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generateToken($length)
|
||||
{
|
||||
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"§$%&/()=[]{}';
|
||||
$useChars = array();
|
||||
// select some random chars:
|
||||
for ($i = 0; $i < $length; $i++)
|
||||
{
|
||||
$useChars[] = $characters[mt_rand(0, strlen($characters) - 1)];
|
||||
}
|
||||
// Add numbers
|
||||
array_push($useChars, rand(0, 9), rand(0, 9), rand(0, 9));
|
||||
shuffle($useChars);
|
||||
$randomString = trim(implode('', $useChars));
|
||||
$randomString = substr($randomString, 0, self::TOKEN_LENGHT);
|
||||
return base64_encode($randomString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate token
|
||||
*
|
||||
* @param int $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateAlphaNumToken($length)
|
||||
{
|
||||
$characters = str_split('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
|
||||
srand((float)microtime() * 1000000);
|
||||
$token = '';
|
||||
do
|
||||
{
|
||||
shuffle($characters);
|
||||
$token .= $characters[mt_rand(0, (count($characters) - 1))];
|
||||
} while (strlen($token) < $length);
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $payload
|
||||
* @param string $type
|
||||
* @param bool $masked
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function hybi10Encode($payload, $type = 'text', $masked = true)
|
||||
{
|
||||
$frameHead = array();
|
||||
$frame = '';
|
||||
$payloadLength = strlen($payload);
|
||||
switch ($type)
|
||||
{
|
||||
case 'text':
|
||||
// first byte indicates FIN, Text-Frame (10000001):
|
||||
$frameHead[0] = 129;
|
||||
break;
|
||||
case 'close':
|
||||
// first byte indicates FIN, Close Frame(10001000):
|
||||
$frameHead[0] = 136;
|
||||
break;
|
||||
case 'ping':
|
||||
// first byte indicates FIN, Ping frame (10001001):
|
||||
$frameHead[0] = 137;
|
||||
break;
|
||||
case 'pong':
|
||||
// first byte indicates FIN, Pong frame (10001010):
|
||||
$frameHead[0] = 138;
|
||||
break;
|
||||
}
|
||||
// set mask and payload length (using 1, 3 or 9 bytes)
|
||||
if ($payloadLength > 65535)
|
||||
{
|
||||
$payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8);
|
||||
$frameHead[1] = ($masked === true) ? 255 : 127;
|
||||
for ($i = 0; $i < 8; $i++)
|
||||
{
|
||||
$frameHead[$i + 2] = bindec($payloadLengthBin[$i]);
|
||||
}
|
||||
// most significant bit MUST be 0 (close connection if frame too big)
|
||||
if ($frameHead[2] > 127)
|
||||
{
|
||||
$this->close(1004);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elseif ($payloadLength > 125)
|
||||
{
|
||||
$payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8);
|
||||
$frameHead[1] = ($masked === true) ? 254 : 126;
|
||||
$frameHead[2] = bindec($payloadLengthBin[0]);
|
||||
$frameHead[3] = bindec($payloadLengthBin[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength;
|
||||
}
|
||||
// convert frame-head to string:
|
||||
foreach (array_keys($frameHead) as $i)
|
||||
{
|
||||
$frameHead[$i] = chr($frameHead[$i]);
|
||||
}
|
||||
if ($masked === true)
|
||||
{
|
||||
// generate a random mask:
|
||||
$mask = array();
|
||||
for ($i = 0; $i < 4; $i++)
|
||||
{
|
||||
$mask[$i] = chr(rand(0, 255));
|
||||
}
|
||||
$frameHead = array_merge($frameHead, $mask);
|
||||
}
|
||||
$frame = implode('', $frameHead);
|
||||
// append payload to frame:
|
||||
for ($i = 0; $i < $payloadLength; $i++)
|
||||
{
|
||||
$frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];
|
||||
}
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
private function hybi10Decode($data)
|
||||
{
|
||||
if (empty($data))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
$bytes = $data;
|
||||
$dataLength = '';
|
||||
$mask = '';
|
||||
$coded_data = '';
|
||||
$decodedData = '';
|
||||
$secondByte = sprintf('%08b', ord($bytes[1]));
|
||||
$masked = ($secondByte[0] == '1') ? true : false;
|
||||
$dataLength = ($masked === true) ? ord($bytes[1]) & 127 : ord($bytes[1]);
|
||||
if ($masked === true)
|
||||
{
|
||||
if ($dataLength === 126)
|
||||
{
|
||||
$mask = substr($bytes, 4, 4);
|
||||
$coded_data = substr($bytes, 8);
|
||||
}
|
||||
elseif ($dataLength === 127)
|
||||
{
|
||||
$mask = substr($bytes, 10, 4);
|
||||
$coded_data = substr($bytes, 14);
|
||||
}
|
||||
else
|
||||
{
|
||||
$mask = substr($bytes, 2, 4);
|
||||
$coded_data = substr($bytes, 6);
|
||||
}
|
||||
for ($i = 0; $i < strlen($coded_data); $i++)
|
||||
{
|
||||
$decodedData .= $coded_data[$i] ^ $mask[$i % 4];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($dataLength === 126)
|
||||
{
|
||||
$decodedData = substr($bytes, 4);
|
||||
}
|
||||
elseif ($dataLength === 127)
|
||||
{
|
||||
$decodedData = substr($bytes, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
$decodedData = substr($bytes, 2);
|
||||
}
|
||||
}
|
||||
return $decodedData;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user