This commit is contained in:
2020-09-04 00:41:33 +08:00
parent 622071256e
commit 46f9de1f6a
141 changed files with 105 additions and 73 deletions
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnAfterReload
* @package HttpServer\Events
*/
class OnAfterReload extends Callback
{
/**
* @param Server $server
* @throws ComponentException
* @throws Exception
*/
public function onHandler(Server $server)
{
$event = Snowflake::app()->getEvent();
if (!$event->exists(Event::SERVER_AFTER_RELOAD)) {
return;
}
$event->trigger(Event::SERVER_AFTER_RELOAD, [$server]);
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnBeforeReload
* @package HttpServer\Events
*/
class OnBeforeReload extends Callback
{
/**
* @param Server $server
* @throws Exception
*/
public function onHandler(Server $server)
{
$event = Snowflake::app()->getEvent();
if (!$event->exists(Event::SERVER_BEFORE_RELOAD)) {
return;
}
$event->trigger(Event::SERVER_BEFORE_RELOAD, [$server]);
}
}
+75
View File
@@ -0,0 +1,75 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Route\Annotation\Annotation;
use HttpServer\Route\Annotation\Tcp;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
use Exception;
use Swoole\Http\Server as HServer;
use Swoole\WebSocket\Server as WServer;
/**
* Class OnClose
* @package HttpServer\Events
*/
class OnClose extends Callback
{
/**
* @param Server $server
* @param int $fd
* @throws Exception
*/
public function onHandler(Server $server, int $fd)
{
try {
[$manager, $name] = $this->resovle($server, $fd);
if ($manager !== null && !$manager->has($name)) {
$manager->runWith($name, [$fd]);
}
} catch (\Throwable $exception) {
$this->addError($exception->getMessage());
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::RELEASE_ALL);
$logger = Snowflake::app()->getLogger();
$logger->insert();
}
}
/**
* @param $server
* @param $fd
* @return array|null
* @throws Exception
*/
public function resovle($server, $fd)
{
if ($server instanceof WServer) {
if (!$server->isEstablished($fd)) {
return [null, null];
}
$manager = Snowflake::app()->annotation->get('websocket');
$name = $manager->getName(AWebsocket::CLOSE);
} else if ($server instanceof HServer) {
$manager = Snowflake::app()->annotation->get('http');
$name = $manager->getName(Annotation::CLOSE);
} else {
$manager = Snowflake::app()->annotation->get('tcp');
$name = $manager->getName(Tcp::CLOSE);
}
return [$manager, $name];
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnConnect
* @package HttpServer\Events
*/
class OnConnect extends Callback
{
/**
* @param Server $server
* @param int $fd
* @param int $reactorId
* @throws Exception
*/
public function onHandler(\Swoole\Server $server, int $fd, int $reactorId)
{
$event = Snowflake::app()->event;
if (!$event->exists(Event::RECEIVE_CONNECTION)) {
return;
}
$event->trigger(Event::RECEIVE_CONNECTION, [$server, $fd, $reactorId]);
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Swoole\Server;
class OnFinish extends Callback
{
/**
* @param Server $server
* @param $task_id
* @param $data
* @throws Exception
*/
public function onHandler(Server $server, $task_id, $data)
{
$data = json_decode($data, true);
$data['work_id'] = $task_id;
$this->write(var_export($data, true), 'Task');
}
}
+67
View File
@@ -0,0 +1,67 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use Snowflake\Snowflake;
use Swoole\Http\Request as SRequest;
use Swoole\Http\Response as SResponse;
use Swoole\WebSocket\Server;
/**
* Class OnHandshake
* @package HttpServer\Events
*/
class OnHandshake extends Callback
{
/**
* @param SRequest $request
* @param SResponse $response
* @return bool|string
* @throws Exception
*/
public function onHandler(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);
}
/** @var AWebsocket $manager */
$manager = Snowflake::app()->annotation->get('websocket');
if ($manager->has($manager->getName(AWebsocket::HANDSHAKE))) {
$manager->runWith($manager->getName(AWebsocket::HANDSHAKE), [$request, $response]);
} else {
$response->status(502);
$response->end();
}
return true;
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
class OnManagerStart extends Callback
{
/**
* @param Server $server
* @throws \Exception
*/
public function onHandler(Server $server)
{
$this->debug('manager start.');
Snowflake::setProcessId($server->manager_pid);
$events = Snowflake::app()->event;
if ($events->exists(Event::SERVER_MANAGER_START)) {
$events->trigger(Event::SERVER_MANAGER_START, null, $server);
}
if (Snowflake::isLinux()) {
name('Server Manager.');
}
}
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnManagerStop
* @package HttpServer\Events
*/
class OnManagerStop extends Callback
{
/**
* @param $server
* @throws \Exception
*/
public function onHandler(Server $server)
{
$this->warning('manager stop.');
$events = Snowflake::app()->event;
if ($events->exists(Event::SERVER_MANAGER_STOP)) {
$events->trigger(Event::SERVER_MANAGER_STOP, [$server]);
}
// $runPath = storage(null, 'workerIds');
// foreach (glob($runPath . '/*') as $item) {
// if (!file_exists($item)) {
// continue;
// }
// @unlink($item);
// }
}
}
+57
View File
@@ -0,0 +1,57 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
/**
* Class OnMessage
* @package HttpServer\Events
*/
class OnMessage extends Callback
{
/**
* @param Server $server
* @param Frame $frame
* @throws
*/
public function onHandler(Server $server, Frame $frame)
{
try {
if ($frame->opcode == 0x08) {
return;
}
$event = Snowflake::app()->event;
if ($event->exists(Event::SERVER_MESSAGE)) {
$event->trigger(Event::SERVER_MESSAGE, [$server, $frame]);
} else {
$frame->data = json_decode($frame->data, true);
}
/** @var AWebsocket $manager */
$manager = Snowflake::app()->annotation->get('websocket');
if (!isset($frame->data['route'])) {
throw new \Exception('Fromat errr.');
}
$events = $manager->getName(AWebsocket::MESSAGE, [null, null, $frame->data['route']]);
$manager->runWith($events, [$frame, $server]);
} catch (\Exception $exception) {
$this->addError($exception->getMessage(), 'websocket');
$server->send($frame->fd, $exception->getMessage());
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::EVENT_AFTER_REQUEST);
Snowflake::app()->logger->insert();
}
}
}
+87
View File
@@ -0,0 +1,87 @@
<?php
namespace HttpServer\Events;
use Closure;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Core\JSON;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
use Exception;
/**
* Class OnPacket
* @package HttpServer\Events
*/
class OnPacket extends Callback
{
/** @var Closure|array */
public $unpack;
/** @var Closure|array */
public $pack;
/**
* @param $data
* @return mixed
* @throws Exception
*/
public function pack($data)
{
$callback = $this->pack;
if (is_callable($callback, true)) {
return $callback($data);
}
return JSON::encode($data);
}
/**
* @param $data
* @return mixed
*/
public function unpack($data)
{
$callback = $this->unpack;
if (is_callable($callback, true)) {
return $callback($data);
}
return JSON::decode($data);
}
/**
* @param Server $server
* @param $data
* @param $clientInfo
* @return mixed
* @throws
*/
public function onHandler($server, $data, $clientInfo)
{
try {
$client = [$clientInfo['address'], $clientInfo['port']];
if (empty($data = $this->unpack($data))) {
throw new Exception('Format error.');
}
$client[] = $this->pack($data);
return $server->sendto(...$client);
} catch (\Throwable $exception) {
$client[] = $this->pack(['message' => $exception->getMessage()]);
return $server->sendto(...$client);
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::SERVER_WORKER_STOP);
}
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnPipeMessage
* @package HttpServer\Events
*/
class OnPipeMessage extends Callback
{
/**
* @param Server $server
* @param int $src_worker_id
* @param $message
* @throws ComponentException
* @throws Exception
*/
public function onHandler(Server $server, int $src_worker_id, $message)
{
// TODO: Implement onHandler() method.
$events = Snowflake::app()->getEvent();
if (!$events->exists(Event::PIPE_MESSAGE)) {
return;
}
$events->trigger(Event::PIPE_MESSAGE, [$server, $src_worker_id, $message]);
}
}
+86
View File
@@ -0,0 +1,86 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Core\JSON;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
use Exception;
use Closure;
/**
* Class OnReceive
* @package HttpServer\Events
*/
class OnReceive extends Callback
{
/** @var Closure|array */
public $unpack;
/** @var Closure|array */
public $pack;
/**
* @param $data
* @return mixed
* @throws Exception
*/
public function pack($data)
{
$callback = $this->pack;
if (is_callable($callback, true)) {
return $callback($data);
}
return JSON::encode($data);
}
/**
* @param $data
* @return mixed
*/
public function unpack($data)
{
$callback = $this->unpack;
if (is_callable($callback, true)) {
return $callback($data);
}
return JSON::decode($data);
}
/**
* @param Server $server
* @param int $fd
* @param int $reactorId
* @param string $data
* @return mixed
* @throws Exception
*/
public function onHandler(\Swoole\Server $server, int $fd, int $reactorId, string $data)
{
try {
$client = [$fd];
if (empty($data = $this->unpack($data))) {
throw new Exception('Format error.');
}
$client[] = $this->pack($data);
return $server->send(...$client);
} catch (\Throwable $exception) {
$client[] = $this->pack(['message' => $exception->getMessage()]);
return $server->send(...$client);
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::SERVER_WORKER_STOP);
}
}
}
+116
View File
@@ -0,0 +1,116 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Http\Context;
use HttpServer\Http\Request as HRequest;
use HttpServer\Http\Response as HResponse;
use HttpServer\Service\Http;
use Snowflake\Core\JSON;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Error;
use Swoole\Http\Request;
use Swoole\Http\Response;
/**
* Class OnRequest
* @package HttpServer\Events
*/
class OnRequest extends Callback
{
/**
* @param Request $request
* @param Response $response
* @return void
* @throws Exception
*/
public function onHandler(Request $request, Response $response)
{
try {
/** @var HRequest $sRequest */
[$sRequest, $sResponse] = static::setContext($request, $response);
if ($sRequest->is('favicon.ico')) {
return $sResponse->send($sRequest->isNotFound(), 200);
}
$sResponse->send(Snowflake::app()->router->dispatch(), 200);
} catch (Error | \Throwable $exception) {
$this->sendErrorMessage($sResponse ?? null, $exception, $response);
} finally {
$events = Snowflake::app()->getEvent();
if (!$events->exists(Event::EVENT_AFTER_REQUEST)) {
return;
}
$events->trigger(Event::EVENT_AFTER_REQUEST, [$request]);
}
}
/**
* @param $sResponse
* @param $exception
* @param $response
* @throws Exception
*/
protected function sendErrorMessage($sResponse, $exception, $response)
{
if (empty($sResponse)) {
$response->status(200);
$response->end($exception->getMessage());
} else {
$sResponse->send($this->format($exception), 200);
}
}
/**
* @param Exception $exception
* @return false|int|mixed|string
* @throws Exception
*/
public function format($exception)
{
$errorInfo = [
'message' => $exception->getMessage(),
'file' => $exception->getFile(),
'line' => $exception->getLine()
];
$this->error(var_export($errorInfo, true));
$code = $exception->getCode() ?? 500;
$logger = Snowflake::app()->logger;
$string = 'Exception: ' . PHP_EOL;
$string .= '#. message: ' . $errorInfo['message'] . PHP_EOL;
$string .= '#. file: ' . $errorInfo['file'] . PHP_EOL;
$string .= '#. line: ' . $errorInfo['line'] . PHP_EOL;
$logger->write($string . $exception->getTraceAsString(), 'trace');
$logger->write(jTraceEx($exception), 'exception');
return JSON::to($code, $errorInfo['message']);
}
/**
* @param $request
* @param $response
* @return array
* @throws Exception
*/
public static function setContext($request, $response): array
{
$request = Context::setContext('request', HRequest::create($request));
$response = Context::setContext('response', HResponse::create($response));
return [$request, $response];
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use Snowflake\Config;
use Snowflake\Core\JSON;
use Snowflake\Error\Logger;
use Snowflake\Event;
use Snowflake\Exception\ComponentException;
use Snowflake\Exception\ConfigException;
use Snowflake\Snowflake;
use Swoole\Server;
use Closure;
/**
* Class OnShutdown
* @package HttpServer\Events
*/
class OnShutdown extends Callback
{
/**
* @param Server $server
* @throws ComponentException
* @throws Exception
*/
public function onHandler(Server $server)
{
$this->system_mail('server shutdown~');
$event = Snowflake::app()->getEvent();
if (!$event->exists(Event::SERVER_SHUTDOWN)) {
return;
}
$event->trigger(Event::SERVER_SHUTDOWN);
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
class OnStart extends Callback
{
/**
* @param Server $server
* @throws \Exception
*/
public function onHandler($server)
{
$time = storage('socket.sock');
Snowflake::writeFile($time, $server->master_pid);
$event = Snowflake::app()->event;
if ($event->exists(Event::SERVER_EVENT_START)) {
$event->trigger(Event::SERVER_EVENT_START, null, $server);
}
}
}
+142
View File
@@ -0,0 +1,142 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\IInterface\Task as ITask;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
use Swoole\Timer;
use Exception;
/**
* Class OnTask
* @package HttpServer\Events
*/
class OnTask extends Callback
{
/**
* @throws Exception
*/
public function onHandler()
{
$parameter = func_get_args();
if (func_num_args() < 4) {
$this->onContinueTask(...$parameter);
} else {
$this->onTask(...$parameter);
}
}
/**
* @param Server $server
* @param int $task_id
* @param int $from_id
* @param string $data
*
* @return mixed|void
* @throws Exception
* 异步任务
*/
public function onTask(Server $server, $task_id, $from_id, $data)
{
$time = microtime(TRUE);
if (empty($data)) {
return $server->finish('null data');
}
$finish = $this->runTaskHandler($data);
if (!$finish) {
$finish = [];
}
$finish['runTime'] = [
'startTime' => $time,
'runTime' => microtime(TRUE) - $time,
'endTime' => microtime(TRUE),
];
$server->finish(json_encode($finish));
}
/**
* @param Server $server
* @param Server\Task $task
* @return mixed|void
* @throws Exception
* 异步任务
*/
public function onContinueTask(Server $server, Server\Task $task)
{
$time = microtime(TRUE);
if (empty($task->data)) {
return $task->finish('null data');
}
$finish = $this->runTaskHandler($task->data);
if (!$finish) {
$finish = [];
}
$finish['runTime'] = [
'startTime' => $time,
'runTime' => microtime(TRUE) - $time,
'endTime' => microtime(TRUE),
];
$task->finish(json_encode($finish));
}
/**
* @param $data
* @return array|null
* @throws Exception
*/
private function runTaskHandler($data)
{
$serialize = $this->before($data);
try {
$params = $serialize->getParams();
if (is_object($params)) {
$params = get_object_vars($params);
}
$finish['class'] = get_class($serialize);
$finish['params'] = $params;
$finish['status'] = 'success';
$finish['info'] = $serialize->handler();
} catch (\Throwable $exception) {
$finish['status'] = 'error';
$finish['info'] = $this->format($exception);
$this->error($exception, 'Task');
} finally {
$event = Snowflake::app()->event;
$event->trigger(Event::RELEASE_ALL);
Timer::clearAll();
}
return $finish;
}
/**
* @param $data
* @return ITask|null
*/
protected function before($data)
{
if (empty($serialize = unserialize($data))) {
return null;
}
if (!($serialize instanceof ITask)) {
return null;
}
return $serialize;
}
/**
* @param $exception
* @return string
*/
private function format($exception)
{
return $exception->getMessage() . " on line " . $exception->getLine() . " at file " . $exception->getFile();
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use Snowflake\Config;
use Snowflake\Exception\ConfigException;
use Swoole\Server;
class OnWorkerError extends Callback
{
/**
* @param Server $server
* @param int $worker_id
* @param int $worker_pid
* @param int $exit_code
* @param int $signal
* @throws Exception
*/
public function onHandler(Server $server, int $worker_id, int $worker_pid, int $exit_code, int $signal)
{
$this->clear($server, $worker_id, self::EVENT_ERROR);
if (!Config::has('email')) {
return;
}
$this->system_mail(print_r([
'$worker_pid' => $worker_pid,
'$worker_id' => $worker_id,
'$exit_code' => $exit_code,
'$signal' => $signal,
], true));
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
/**
* Class OnWorkerExit
* @package HttpServer\Events
*/
class OnWorkerExit extends Callback
{
/**
* @param $server
* @param $worker_id
* @throws Exception
*/
public function onHandler($server, $worker_id)
{
$this->clear($server, $worker_id, self::EVENT_EXIT);
}
}
+81
View File
@@ -0,0 +1,81 @@
<?php
namespace HttpServer\Events;
use Exception;
use HttpServer\Events\Abstracts\Callback;
use HttpServer\Route\Annotation\Websocket as AWebsocket;
use HttpServer\Service\Http;
use HttpServer\Service\Websocket;
use Snowflake\Error\Logger;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
/**
* Class OnWorkerStart
* @package HttpServer\Events
*/
class OnWorkerStart extends Callback
{
/**
* @param Server $server
* @param int $worker_id
*
* @return mixed|void
* @throws Exception
*/
public function onHandler(Server $server, $worker_id)
{
Snowflake::setProcessId($server->worker_pid);
$get_name = $this->get_process_name($server, $worker_id);
if (!empty($get_name) && !Snowflake::isMac()) {
swoole_set_process_name($get_name);
}
if ($worker_id >= $server->setting['worker_num']) {
return;
}
$this->setWorkerAction($server, $worker_id);
}
/**
* @param $worker_id
* @param $socket
* @throws Exception
*/
private function setWorkerAction($socket, $worker_id)
{
try {
$this->debug(sprintf('Worker #%d is start.....', $worker_id));
$event = Snowflake::app()->event;
if (!$event->exists(Event::SERVER_WORKER_START)) {
return;
}
$event->trigger(Event::SERVER_WORKER_START);
} catch (\Throwable $exception) {
Snowflake::app()->getLogger()->write($exception->getMessage(), 'worker');
}
}
/**
* @param $socket
* @param $worker_id
* @return string
*/
private function get_process_name($socket, $worker_id)
{
$prefix = 'system:';
if ($worker_id >= $socket->setting['worker_num']) {
return $prefix . ': Task: No.' . $worker_id;
} else {
return $prefix . ': worker: No.' . $worker_id;
}
}
}
+23
View File
@@ -0,0 +1,23 @@
<?php
namespace HttpServer\Events;
use HttpServer\Events\Abstracts\Callback;
class OnWorkerStop extends Callback
{
/**
* @param $server
* @param $worker_id
* @throws \Exception
*/
public function onHandler($server, $worker_id)
{
$this->clear($server, $worker_id, self::EVENT_STOP);
}
}