改名
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Abstracts;
|
||||
|
||||
use Annotation\Inject;
|
||||
use Kiri\Events\EventDispatch;
|
||||
|
||||
trait EventDispatchHelper
|
||||
{
|
||||
|
||||
/** @var EventDispatch */
|
||||
#[Inject(EventDispatch::class)]
|
||||
public EventDispatch $eventDispatch;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Abstracts;
|
||||
|
||||
use Annotation\Inject;
|
||||
use HttpServer\Route\Router;
|
||||
use Kiri\Abstracts\Config;
|
||||
use Kiri\Events\EventDispatch;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Exception\NotFindClassException;
|
||||
use Kiri\Kiri;
|
||||
use ReflectionException;
|
||||
use Server\Constrict\Response as CResponse;
|
||||
use Server\Constrict\ResponseEmitter;
|
||||
use Server\ExceptionHandlerDispatcher;
|
||||
use Server\ExceptionHandlerInterface;
|
||||
use Server\ListenerHelper;
|
||||
use Server\SInterface\OnRequest;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
abstract class Http implements OnRequest
|
||||
{
|
||||
|
||||
|
||||
use EventDispatchHelper;
|
||||
use ResponseHelper;
|
||||
|
||||
/** @var Router|mixed */
|
||||
#[Inject('router')]
|
||||
public Router $router;
|
||||
|
||||
|
||||
/**
|
||||
* @var ExceptionHandlerInterface
|
||||
*/
|
||||
public ExceptionHandlerInterface $exceptionHandler;
|
||||
|
||||
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
* @throws ConfigException
|
||||
* @throws NotFindClassException
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$exceptionHandler = Config::get('exception.http', ExceptionHandlerDispatcher::class);
|
||||
if (!in_array(ExceptionHandlerInterface::class, class_implements($exceptionHandler))) {
|
||||
$exceptionHandler = ExceptionHandlerDispatcher::class;
|
||||
}
|
||||
$this->exceptionHandler = Kiri::getDi()->get($exceptionHandler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Abstracts;
|
||||
|
||||
use Annotation\Inject;
|
||||
use Server\Constrict\Response as CResponse;
|
||||
use Server\Constrict\ResponseEmitter;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
trait ResponseHelper
|
||||
{
|
||||
|
||||
/** @var CResponse|mixed */
|
||||
#[Inject(CResponse::class)]
|
||||
public CResponse $response;
|
||||
|
||||
|
||||
/** @var ResponseEmitter */
|
||||
#[Inject(ResponseEmitter::class)]
|
||||
public ResponseEmitter $responseEmitter;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Abstracts;
|
||||
|
||||
use Kiri\Abstracts\Config;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Exception\NotFindClassException;
|
||||
use Kiri\Kiri;
|
||||
use ReflectionException;
|
||||
use Server\ExceptionHandlerDispatcher;
|
||||
use Server\ExceptionHandlerInterface;
|
||||
use Server\SInterface\OnReceive;
|
||||
|
||||
abstract class Tcp implements OnReceive
|
||||
{
|
||||
|
||||
use EventDispatchHelper;
|
||||
use ResponseHelper;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @var ExceptionHandlerInterface
|
||||
*/
|
||||
public ExceptionHandlerInterface $exceptionHandler;
|
||||
|
||||
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
* @throws ConfigException
|
||||
* @throws NotFindClassException
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$exceptionHandler = Config::get('exception.tcp', ExceptionHandlerDispatcher::class);
|
||||
if (!in_array(ExceptionHandlerInterface::class, class_implements($exceptionHandler))) {
|
||||
$exceptionHandler = ExceptionHandlerDispatcher::class;
|
||||
}
|
||||
$this->exceptionHandler = Kiri::getDi()->get($exceptionHandler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Abstracts;
|
||||
|
||||
use Kiri\Abstracts\Config;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Exception\NotFindClassException;
|
||||
use Kiri\Kiri;
|
||||
use ReflectionException;
|
||||
use Server\ExceptionHandlerDispatcher;
|
||||
use Server\ExceptionHandlerInterface;
|
||||
use Server\SInterface\OnPacket;
|
||||
use Server\SInterface\OnReceive;
|
||||
|
||||
abstract class Udp implements OnPacket
|
||||
{
|
||||
|
||||
use EventDispatchHelper;
|
||||
use ResponseHelper;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @var ExceptionHandlerInterface
|
||||
*/
|
||||
public ExceptionHandlerInterface $exceptionHandler;
|
||||
|
||||
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
* @throws ConfigException
|
||||
* @throws NotFindClassException
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$exceptionHandler = Config::get('exception.udp', ExceptionHandlerDispatcher::class);
|
||||
if (!in_array(ExceptionHandlerInterface::class, class_implements($exceptionHandler))) {
|
||||
$exceptionHandler = ExceptionHandlerDispatcher::class;
|
||||
}
|
||||
$this->exceptionHandler = Kiri::getDi()->get($exceptionHandler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Abstracts;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Abstracts\Config;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Exception\NotFindClassException;
|
||||
use Kiri\Kiri;
|
||||
use ReflectionException;
|
||||
use Server\ExceptionHandlerDispatcher;
|
||||
use Server\ExceptionHandlerInterface;
|
||||
use Server\SInterface\OnClose;
|
||||
use Server\SInterface\OnHandshake;
|
||||
use Server\SInterface\OnMessage;
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\Http\Response;
|
||||
use Swoole\Server;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
abstract class Websocket implements OnHandshake, OnMessage, OnClose
|
||||
{
|
||||
|
||||
use EventDispatchHelper;
|
||||
use ResponseHelper;
|
||||
|
||||
|
||||
/**
|
||||
* @var ExceptionHandlerInterface
|
||||
*/
|
||||
public ExceptionHandlerInterface $exceptionHandler;
|
||||
|
||||
|
||||
/**
|
||||
* @throws ReflectionException
|
||||
* @throws ConfigException
|
||||
* @throws NotFindClassException
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$exceptionHandler = Config::get('exception.websocket', ExceptionHandlerDispatcher::class);
|
||||
if (!in_array(ExceptionHandlerInterface::class, class_implements($exceptionHandler))) {
|
||||
$exceptionHandler = ExceptionHandlerDispatcher::class;
|
||||
}
|
||||
$this->exceptionHandler = Kiri::getDi()->get($exceptionHandler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandshake(Request $request, Response $response): void
|
||||
{
|
||||
// TODO: Implement OnHandshake() method.
|
||||
/** @var \Swoole\WebSocket\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))) {
|
||||
throw new Exception('protocol error.', 500);
|
||||
}
|
||||
$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->setHeader($key, $val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -22,7 +22,6 @@ trait ListenerHelper
|
||||
* @param array $events
|
||||
* @param array|Closure $default
|
||||
* @return mixed
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
protected static function callback(string $name, array $events, array|Closure $default): mixed
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Server\SInterface;
|
||||
|
||||
use Swoole\Server;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
interface OnClose
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
*/
|
||||
public function onClose(Server $server, int $fd): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
*/
|
||||
public function onDisconnect(Server $server, int $fd): void;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Server\SInterface;
|
||||
|
||||
use Swoole\Server;
|
||||
|
||||
interface OnConnect
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
* @return void
|
||||
*/
|
||||
public function onConnect(Server $server, int $fd): void;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Server\SInterface;
|
||||
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\Http\Response;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
interface OnHandshake
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function OnHandshake(Request $request, Response $response): void;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Server\SInterface;
|
||||
|
||||
use Swoole\Server;
|
||||
use Swoole\WebSocket\Frame;
|
||||
|
||||
interface OnMessage
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param Frame $frame
|
||||
* @return void
|
||||
*/
|
||||
public function OnMessage(Server $server, Frame $frame): void;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Server\SInterface;
|
||||
|
||||
use Server\Abstracts\Server;
|
||||
|
||||
interface OnPacket
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param string $data
|
||||
* @param array $clientInfo
|
||||
* @return mixed
|
||||
*/
|
||||
public function onPacket(Server $server, string $data, array $clientInfo): void;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Server\SInterface;
|
||||
|
||||
use Swoole\Server;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
interface OnReceive
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
* @param int $reactor_id
|
||||
* @param string $data
|
||||
* @return void
|
||||
*/
|
||||
public function onReceive(Server $server, int $fd, int $reactor_id, string $data): void;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Server\SInterface;
|
||||
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\Http\Response;
|
||||
|
||||
interface OnRequest
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function onRequest(Request $request, Response $response): void;
|
||||
|
||||
}
|
||||
+22
-28
@@ -4,15 +4,15 @@ namespace Server;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Kiri\Abstracts\Config;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Exception\NotFindClassException;
|
||||
use Kiri\Kiri;
|
||||
use ReflectionException;
|
||||
use Server\Manager\OnPipeMessage;
|
||||
use Server\SInterface\CustomProcess;
|
||||
use Server\SInterface\TaskExecute;
|
||||
use Server\Task\OnServerTask;
|
||||
use Kiri\Abstracts\Config;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Exception\NotFindClassException;
|
||||
use Kiri\Kiri;
|
||||
use Swoole\Http\Server as HServer;
|
||||
use Swoole\Process;
|
||||
use Swoole\Server;
|
||||
@@ -240,14 +240,7 @@ class ServerManager extends Abstracts\Server
|
||||
throw new Exception("The port is already in use[$host::$port]");
|
||||
}
|
||||
$this->ports[$port]->set($settings['settings'] ?? []);
|
||||
$reflect = match ($type) {
|
||||
Constant::SERVER_TYPE_TCP => Kiri::getDi()->newObject(TCPServerListener::class),
|
||||
Constant::SERVER_TYPE_UDP => Kiri::getDi()->newObject(UDPServerListener::class),
|
||||
Constant::SERVER_TYPE_HTTP => Kiri::getDi()->newObject(HTTPServerListener::class),
|
||||
Constant::SERVER_TYPE_WEBSOCKET => Kiri::getDi()->newObject(WebSocketServerListener::class),
|
||||
default => throw new Exception(''),
|
||||
};
|
||||
$reflect->bindCallback($this->ports[$port], $settings['events'] ?? []);
|
||||
$this->addServiceEvents($settings['events'] ?? [], $this->ports[$port]);
|
||||
}
|
||||
|
||||
|
||||
@@ -335,22 +328,23 @@ class ServerManager extends Abstracts\Server
|
||||
if (($this->server->setting['task_worker_num'] ?? 0) > 0) {
|
||||
$this->addTaskListener($settings['events']);
|
||||
}
|
||||
if ($type === Constant::SERVER_TYPE_WEBSOCKET) {
|
||||
/** @var WebSocketServerListener $reflect */
|
||||
$reflect = $this->getNewInstance(WebSocketServerListener::class);
|
||||
$reflect->bindCallback($this->server, $settings);
|
||||
} else if ($type === Constant::SERVER_TYPE_UDP) {
|
||||
/** @var UDPServerListener $reflect */
|
||||
$reflect = $this->getNewInstance(UDPServerListener::class);
|
||||
$reflect->bindCallback($this->server, $settings);
|
||||
} else if ($type === Constant::SERVER_TYPE_HTTP) {
|
||||
/** @var HTTPServerListener $reflect */
|
||||
$reflect = $this->getNewInstance(HTTPServerListener::class);
|
||||
$reflect->bindCallback($this->server, $settings);
|
||||
} else {
|
||||
/** @var TCPServerListener $reflect */
|
||||
$reflect = $this->getNewInstance(TCPServerListener::class);
|
||||
$reflect->bindCallback($this->server, $settings);
|
||||
$this->addServiceEvents($settings['events'] ?? [], $this->server);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $events
|
||||
* @param Server $server
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function addServiceEvents(array $events, Server $server)
|
||||
{
|
||||
foreach ($events as $name => $event) {
|
||||
if (is_array($event) && is_string($event)) {
|
||||
$callback[0] = $this->getNewInstance($event[0]);
|
||||
}
|
||||
$server->on($name, $event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Service;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Exception\RequestException;
|
||||
use HttpServer\Route\Node;
|
||||
use Kiri\Exception\NotFindClassException;
|
||||
use ReflectionException;
|
||||
use Server\Events\OnAfterRequest;
|
||||
use Server\ResponseInterface;
|
||||
use Server\SInterface\OnClose;
|
||||
use Swoole\Error;
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\Http\Response;
|
||||
use Swoole\Server;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Http extends \Server\Abstracts\Http implements OnClose
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function onRequest(Request $request, Response $response): void
|
||||
{
|
||||
// TODO: Implement onRequest() method.
|
||||
try {
|
||||
$node = $this->router->Branch_search(\Server\Constrict\Request::create($request));
|
||||
if (!($node instanceof Node)) {
|
||||
throw new RequestException('<h2>HTTP 404 Not Found</h2><hr><i>Powered by Swoole</i>', 404);
|
||||
}
|
||||
if (!(($responseData = $node->dispatch()) instanceof ResponseInterface)) {
|
||||
$responseData = $this->response->setContent($responseData)->setStatusCode(200);
|
||||
}
|
||||
} catch (Error | \Throwable $exception) {
|
||||
$responseData = $this->exceptionHandler->emit($exception, $this->response);
|
||||
} finally {
|
||||
$this->responseEmitter->sender($response, $responseData);
|
||||
$this->eventDispatch->dispatch(new OnAfterRequest());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onDisconnect(Server $server, int $fd): void
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onClose(Server $server, int $fd): void
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Service;
|
||||
|
||||
use Server\SInterface\OnClose;
|
||||
use Server\SInterface\OnConnect;
|
||||
use Swoole\Server;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Tcp extends \Server\Abstracts\Tcp implements OnConnect, OnClose
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
*/
|
||||
public function onConnect(Server $server, int $fd): void
|
||||
{
|
||||
// TODO: Implement onConnect() method.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
* @param int $reactor_id
|
||||
* @param string $data
|
||||
*/
|
||||
public function onReceive(Server $server, int $fd, int $reactor_id, string $data): void
|
||||
{
|
||||
// TODO: Implement onReceive() method.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
*/
|
||||
public function onClose(Server $server, int $fd): void
|
||||
{
|
||||
// TODO: Implement onClose() method.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
*/
|
||||
public function onDisconnect(Server $server, int $fd): void
|
||||
{
|
||||
// TODO: Implement onDisconnect() method.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Service;
|
||||
|
||||
|
||||
|
||||
use Server\Abstracts\Server;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Udp extends \Server\Abstracts\Udp
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param string $data
|
||||
* @param array $clientInfo
|
||||
*/
|
||||
public function onPacket(Server $server, string $data, array $clientInfo): void
|
||||
{
|
||||
// TODO: Implement onPacket() method.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Server\Service;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Server\SInterface\OnRequest;
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\Http\Response;
|
||||
use Swoole\Server;
|
||||
use Swoole\WebSocket\Frame;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class WebSocket extends \Server\Abstracts\Websocket
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandshake(Request $request, Response $response): void
|
||||
{
|
||||
parent::onHandshake($request, $response); // TODO: Change the autogenerated stub
|
||||
|
||||
$response->status(101);
|
||||
$response->end();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param Frame $frame
|
||||
*/
|
||||
public function onMessage(Server $server, Frame $frame): void
|
||||
{
|
||||
// TODO: Implement OnMessage() method.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
*/
|
||||
public function onClose(Server $server, int $fd): void
|
||||
{
|
||||
// TODO: Implement OnClose() method.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
*/
|
||||
public function onDisconnect(Server $server, int $fd): void
|
||||
{
|
||||
// TODO: Implement OnDisconnect() method.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user