From f867f4be9e8d89c6d04678eb846727e6b1805e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E6=9E=97?= Date: Thu, 6 Jan 2022 19:05:15 +0800 Subject: [PATCH] =?UTF-8?q?Revert=20"=E6=94=B9=E5=90=8D"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit fdf58326 --- kiri-engine/Abstracts/AbstractServer.php | 12 +++ kiri-engine/Abstracts/Config.php | 16 ++- kiri-engine/Di/Container.php | 4 +- kiri-websocket-server/Server.php | 130 ++++++++++++++++++----- 4 files changed, 131 insertions(+), 31 deletions(-) create mode 100644 kiri-engine/Abstracts/AbstractServer.php diff --git a/kiri-engine/Abstracts/AbstractServer.php b/kiri-engine/Abstracts/AbstractServer.php new file mode 100644 index 00000000..6b1abb98 --- /dev/null +++ b/kiri-engine/Abstracts/AbstractServer.php @@ -0,0 +1,12 @@ +router = $this->container->get(DataGrip::class)->get($this->serverName); + $this->router = $this->container->get(DataGrip::class)->get('ws'); $handler = $this->router->find('/', 'GET'); if (is_int($handler) || is_null($handler)) { return; } $this->callback = $handler->callback[0]; + + $this->server->on(Constant::HANDSHAKE, [$this, 'onHandshake']); + $this->server->on(Constant::MESSAGE, [$this, 'onMessage']); + $this->server->on(Constant::CLOSE, [$this, 'onClose']); } @@ -65,6 +75,37 @@ class Server extends Component implements OnHandshakeInterface, OnMessageInterfa } + /** + * @param Request $request + * @param Response $response + * @return void + * @throws Exception + */ + protected function protocol(Request $request, Response $response) + { + $secWebSocketKey = $request->header['sec-websocket-key']; + $patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#'; + if (preg_match($patten, $secWebSocketKey) === 0 || strlen(base64_decode($secWebSocketKey)) !== 16) { + throw new Exception('protocol error.', 500); + } + $key = base64_encode(sha1($request->header['sec-websocket-key'] . self::SHA1_KEY, 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); + } + $response->setStatusCode(101, 'connection success.'); + $response->end(); + } + + /** * @param Request $request * @param Response $response @@ -72,25 +113,64 @@ class Server extends Component implements OnHandshakeInterface, OnMessageInterfa public function onHandshake(Request $request, Response $response): void { try { - if (!$this->callback instanceof OnHandshakeInterface) { - throw new \Exception('Page not found.'); - } - $this->callback->onHandshake($request, $response); - - $this->afterHandshake($request); - if ($this->server instanceof \Swoole\Coroutine\Http\Server) { - while (true) { - $data = $response->recv(); - if ($data === '' || $data === false || $data instanceof CloseFrame) { - $this->onClose($this->server, $response->fd); - break; - } - $this->onMessage($this->server, $data); - } + if ($this->callback instanceof OnHandshakeInterface) { + $this->__handshake($request, $response); + } else { + $this->protocol($request, $response); } } catch (\Throwable $throwable) { $response->status(500, $throwable->getMessage()); $response->end(); + } finally { + if ($this->callback instanceof OnOpenInterface) { + $this->callback->onOpen($this->server, $request); + } + } + } + + + /** + * @param Request $request + * @param Response $response + * @return void + * @throws Exception + */ + private function __handshake(Request $request, Response $response) + { + $this->callback->onHandshake($request, $response); + $key = base64_encode(sha1($request->header['sec-websocket-key'] . self::SHA1_KEY, true)); + if ($key != $response->header['Sec-Websocket-Accept']) { + throw new Exception('Protocol fail.'); + } + $response->setStatusCode(101, 'connection success.'); + $response->end(); + } + + + /** + * @param Request $request + * @param Response $response + * @return void + */ + private function _coroutine_server(Request $request, Response $response) + { + if ($this->server instanceof \Swoole\Coroutine\Http\Server) { + $response->upgrade(); + $this->afterHandshake($request); + while (true) { + $data = $response->recv(); + if ($data === '' || $data === false || $data instanceof CloseFrame) { + if (!($this->callback instanceof OnCloseInterface)) { + break; + } + $this->callback->onClose($this->server, $response->fd); + break; + } + if (!($this->callback instanceof OnMessageInterface)) { + continue; + } + $this->callback->onMessage($this->server, $data); + } } }