Files
kiri-core/http-server/Events/WebSocket.php
T

178 lines
4.4 KiB
PHP
Raw Normal View History

2020-08-31 01:27:08 +08:00
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/11/8 0008
* Time: 18:15
*/
namespace HttpServer\Events;
use Exception;
use HttpServer\ServerManager;
2020-08-31 14:52:28 +08:00
use ReflectionException;
2020-09-01 03:11:34 +08:00
use Snowflake\Application;
2020-08-31 01:27:08 +08:00
use Snowflake\Error\Logger;
use Snowflake\Event;
use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
use Swoole\Http\Request as SRequest;
use Swoole\Http\Response as SResponse;
2020-08-31 14:52:28 +08:00
use Swoole\Process\Pool;
2020-08-31 01:27:08 +08:00
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
2020-09-01 03:11:34 +08:00
use HttpServer\Route\Annotation\Websocket as AWebsocket;
2020-08-31 01:27:08 +08:00
/**
* Class ServerWebSocket
2020-08-31 12:38:32 +08:00
* @package Snowflake\Snowflake\Server
2020-08-31 01:27:08 +08:00
*/
class WebSocket extends Server
{
public $namespace = 'App\\Sockets\\';
public $callback = [];
2020-09-01 03:11:34 +08:00
/** @var Application */
2020-08-31 01:27:08 +08:00
public $application;
/**
* WebSocket constructor.
* @param $application
* @param $host
* @param null $port
* @param null $mode
* @param null $sock_type
*/
public function __construct($application, $host, $port = null, $mode = null, $sock_type = null)
{
parent::__construct($host, $port, $mode, $sock_type);
2020-09-01 03:42:32 +08:00
$this->application = $application;
2020-08-31 01:27:08 +08:00
}
/**
* @param array $settings
2020-08-31 14:52:28 +08:00
* @param null $pool
2020-08-31 01:27:08 +08:00
* @param array $events
2020-08-31 14:52:28 +08:00
* @param array $config
2020-08-31 01:27:08 +08:00
* @return mixed|void
* @throws NotFindClassException
2020-08-31 14:52:28 +08:00
* @throws ReflectionException
* @throws Exception
2020-08-31 01:27:08 +08:00
*/
2020-08-31 14:52:28 +08:00
public function set(array $settings, $pool = null, $events = [], $config = [])
2020-08-31 01:27:08 +08:00
{
parent::set($settings);
2020-09-01 03:11:34 +08:00
2020-09-01 04:19:03 +08:00
$application = Snowflake::get();
$application->set(WebSocket::class, $this);
$application->set(Pool::class, $pool);
2020-09-01 03:11:34 +08:00
2020-09-01 04:19:03 +08:00
ServerManager::set($this, $settings, $application, $events, $config);
2020-08-31 01:27:08 +08:00
}
/**
* @param Server $server
* @param Frame $frame
* @throws
*/
public function onMessage(Server $server, Frame $frame)
{
try {
if ($frame->opcode == 0x08) {
return;
}
2020-09-01 03:55:37 +08:00
$event = Snowflake::get()->event;
if ($event->exists(Event::SERVER_MESSAGE)) {
2020-09-01 04:16:56 +08:00
$event->trigger(Event::SERVER_MESSAGE, [$server, $frame]);
2020-09-01 03:56:19 +08:00
} else {
$frame->data = json_decode($frame->data, true);
2020-09-01 03:55:37 +08:00
}
2020-08-31 01:27:08 +08:00
2020-09-01 03:11:34 +08:00
/** @var AWebsocket $manager */
$manager = Snowflake::get()->annotation->get('websocket');
2020-09-01 04:14:55 +08:00
$manager->runWith($manager->getName(AWebsocket::MESSAGE, [null, null, $frame->data['route']]), [$frame, $server]);
2020-08-31 01:27:08 +08:00
} catch (Exception $exception) {
2020-09-01 03:11:34 +08:00
$this->application->addError($exception->getMessage(), 'websocket');
2020-09-01 03:59:53 +08:00
$server->send($frame->fd, $exception->getMessage());
2020-08-31 01:27:08 +08:00
} finally {
$event = Snowflake::get()->event;
$event->trigger(Event::EVENT_AFTER_REQUEST);
Logger::insert();
}
}
/**
* @param SRequest $request
* @param SResponse $response
* @return bool
* @throws Exception
*/
protected function connect($request, $response)
{
2020-09-01 04:24:36 +08:00
/** @var AWebsocket $manager */
$manager = Snowflake::get()->annotation->get('websocket');
$manager->runWith($manager->getName(AWebsocket::HANDSHAKE), [$request, $response]);
2020-08-31 01:27:08 +08:00
return true;
}
/**
* @param SRequest $request
* @param SResponse $response
* @return bool|string
* @throws Exception
*/
public function onHandshake(SRequest $request, SResponse $response)
{
/** @var Server $server */
$secWebSocketKey = $request->header['sec-websocket-key'];
$patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
return false;
}
$key = base64_encode(sha1(
$request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
TRUE
));
$headers = [
'Upgrade' => 'websocket',
'Connection' => 'Upgrade',
'Sec-websocket-Accept' => $key,
'Sec-websocket-Version' => '13',
];
if (isset($request->header['sec-websocket-protocol'])) {
$headers['Sec-websocket-Protocol'] = $request->header['sec-websocket-protocol'];
}
foreach ($headers as $key => $val) {
$response->header($key, $val);
}
2020-09-01 04:24:36 +08:00
return $this->connect($request, $response);
2020-08-31 01:27:08 +08:00
}
/**
* @param Server $server
* @param int $fd
* @throws Exception
*/
public function onClose(Server $server, int $fd)
{
try {
2020-09-01 04:24:36 +08:00
/** @var AWebsocket $manager */
$manager = Snowflake::get()->annotation->get('websocket');
$manager->runWith($manager->getName(AWebsocket::CLOSE), [$fd]);
2020-08-31 01:27:08 +08:00
} catch (\Throwable $exception) {
2020-09-01 03:11:34 +08:00
$this->application->addError($exception->getMessage());
2020-08-31 01:27:08 +08:00
} finally {
2020-09-01 04:24:36 +08:00
$event = Snowflake::get()->event;
2020-08-31 01:27:08 +08:00
$event->trigger(Event::RELEASE_ALL);
Logger::insert();
}
}
}