diff --git a/Database/Base/BaseActiveRecord.php b/Database/Base/BaseActiveRecord.php index 14ae4b69..d217e4c7 100644 --- a/Database/Base/BaseActiveRecord.php +++ b/Database/Base/BaseActiveRecord.php @@ -20,6 +20,7 @@ use Database\Mysql\Columns; use Database\Relation; use Snowflake\Error\Logger; use Exception; +use Snowflake\Exception\ComponentException; use validator\Validator; use Database\IOrm; use Snowflake\Snowflake; @@ -118,10 +119,11 @@ abstract class BaseActiveRecord extends Component implements IOrm, \ArrayAccess * @return mixed * * get last exception or other error + * @throws ComponentException */ public function getLastError() { - return Logger::getLastError('mysql'); + return Snowflake::get()->getLogger()->getLastError('mysql'); } /** diff --git a/http-server/Events/Callback.php b/http-server/Abstracts/Callback.php similarity index 83% rename from http-server/Events/Callback.php rename to http-server/Abstracts/Callback.php index 01e92413..848a35f1 100644 --- a/http-server/Events/Callback.php +++ b/http-server/Abstracts/Callback.php @@ -1,7 +1,7 @@ container = $container; - } - - - /** * @param $server @@ -46,8 +31,10 @@ abstract class Callback extends Application $this->eventNotify($message, $event); Snowflake::clearProcessId($server->worker_pid); - Logger::write($this->_MESSAGE[$message] . $worker_id); - Logger::clear(); + + $logger = Snowflake::get()->getLogger(); + $logger->write($this->_MESSAGE[$message] . $worker_id); + $logger->clear(); } diff --git a/http-server/Events/Trigger/OnAfterReload.php b/http-server/Events/OnAfterReload.php similarity index 64% rename from http-server/Events/Trigger/OnAfterReload.php rename to http-server/Events/OnAfterReload.php index 5e275ba4..38ce2e0c 100644 --- a/http-server/Events/Trigger/OnAfterReload.php +++ b/http-server/Events/OnAfterReload.php @@ -1,10 +1,10 @@ isEstablished($fd)) { + return; + } + $manager = Snowflake::get()->annotation->get('websocket'); + $name = $manager->getName(AWebsocket::CLOSE); + } else if ($server instanceof HServer) { + $manager = Snowflake::get()->annotation->get('http'); + $name = $manager->getName(Annotation::CLOSE); + } else { + $manager = Snowflake::get()->annotation->get('tcp'); + $name = $manager->getName(Tcp::CLOSE); + } + if (!$manager->has($name)) { + return; + } + $manager->runWith($name, [$fd]); + } catch (\Throwable $exception) { + $this->addError($exception->getMessage()); + } finally { + $event = Snowflake::get()->event; + $event->trigger(Event::RELEASE_ALL); + + $logger = Snowflake::get()->getLogger(); + $logger->insert(); + } + } + + +} diff --git a/http-server/Events/Trigger/OnConnect.php b/http-server/Events/OnConnect.php similarity index 82% rename from http-server/Events/Trigger/OnConnect.php rename to http-server/Events/OnConnect.php index bf9625b2..607cd5ad 100644 --- a/http-server/Events/Trigger/OnConnect.php +++ b/http-server/Events/OnConnect.php @@ -1,18 +1,18 @@ 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::get()->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; + } + + +} diff --git a/http-server/Events/Trigger/OnManagerStart.php b/http-server/Events/OnManagerStart.php similarity index 88% rename from http-server/Events/Trigger/OnManagerStart.php rename to http-server/Events/OnManagerStart.php index b87246fd..817ff9e0 100644 --- a/http-server/Events/Trigger/OnManagerStart.php +++ b/http-server/Events/OnManagerStart.php @@ -1,10 +1,10 @@ opcode == 0x08) { + return; + } + + $event = Snowflake::get()->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::get()->annotation->get('websocket'); + $manager->runWith($manager->getName(AWebsocket::MESSAGE, [null, null, $frame->data['route']]), [$frame, $server]); + } catch (\Exception $exception) { + $this->addError($exception->getMessage(), 'websocket'); + $server->send($frame->fd, $exception->getMessage()); + } finally { + $event = Snowflake::get()->event; + $event->trigger(Event::EVENT_AFTER_REQUEST); + Snowflake::get()->logger->insert(); + } + } + + + + +} diff --git a/http-server/Events/Packet.php b/http-server/Events/OnPacket.php similarity index 54% rename from http-server/Events/Packet.php rename to http-server/Events/OnPacket.php index 6f901591..c2a7a0e5 100644 --- a/http-server/Events/Packet.php +++ b/http-server/Events/OnPacket.php @@ -4,18 +4,60 @@ namespace HttpServer\Events; -use Exception; +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\Trigger + * @package HttpServer\Events */ -class Packet extends Service +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 @@ -41,4 +83,5 @@ class Packet extends Service } } + } diff --git a/http-server/Events/Trigger/OnPipeMessage.php b/http-server/Events/OnPipeMessage.php similarity index 64% rename from http-server/Events/Trigger/OnPipeMessage.php rename to http-server/Events/OnPipeMessage.php index 9230c145..31f8525d 100644 --- a/http-server/Events/Trigger/OnPipeMessage.php +++ b/http-server/Events/OnPipeMessage.php @@ -1,10 +1,10 @@ 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 @@ -25,7 +65,7 @@ class Receive extends Service * @return mixed * @throws Exception */ - public function onReceive(\Swoole\Server $server, int $fd, int $reactorId, string $data) + public function onHandler(\Swoole\Server $server, int $fd, int $reactorId, string $data) { try { $client = [$fd]; diff --git a/http-server/Events/Http.php b/http-server/Events/OnRequest.php similarity index 59% rename from http-server/Events/Http.php rename to http-server/Events/OnRequest.php index ed18553b..33bfd0b1 100644 --- a/http-server/Events/Http.php +++ b/http-server/Events/OnRequest.php @@ -4,66 +4,31 @@ 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\ServerManager; -use ReflectionException; -use Snowflake\Application; +use HttpServer\Service\Http; use Snowflake\Core\JSON; -use Snowflake\Exception\NotFindClassException; use Snowflake\Snowflake; use Swoole\Error; use Swoole\Http\Request; use Swoole\Http\Response; -use Exception; -use Swoole\Http\Server; -use Swoole\Process\Pool; -class Http extends Server +/** + * Class OnRequest + * @package HttpServer\Events + */ +class OnRequest extends Callback { - /** @var Application */ - protected $application; - - - /** - * Receive 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) - { - $application->set(Http::class, $this); - $this->application = $application; - parent::__construct($host, $port, $mode, $sock_type); - } - - - /** - * @param array $settings - * @param null $pool - * @param array $events - * @param array $config - * @return mixed|void - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - public function set(array $settings, $pool = null, $events = [], $config = []) - { - parent::set($settings); - ServerManager::set($this, $settings, $this->application, $events, $config); - } /** * @param Request $request * @param Response $response - * @throws \Exception + * @throws Exception */ public function onHandler(Request $request, Response $response) { @@ -79,7 +44,7 @@ class Http extends Server } } finally { $dividing_line = str_pad('', 100, '-'); - $this->application->debug($dividing_line, 'app'); + $this->debug($dividing_line, 'app'); } } @@ -96,7 +61,7 @@ class Http extends Server 'file' => $exception->getFile(), 'line' => $exception->getLine() ]; - $this->application->error(var_export($errorInfo, true)); + $this->error(var_export($errorInfo, true)); $code = $exception->getCode() ?? 500; $trance = array_slice($exception->getTrace(), 0, 10); @@ -119,4 +84,5 @@ class Http extends Server return [$request, $response]; } + } diff --git a/http-server/Events/OnShutdown.php b/http-server/Events/OnShutdown.php new file mode 100644 index 00000000..8ee61e84 --- /dev/null +++ b/http-server/Events/OnShutdown.php @@ -0,0 +1,80 @@ +system_mail($email, $nickname); + } + + + /** + * @param $email + * @param $nickname + */ + protected function system_mail($email, $nickname) + { + try { + $mail = new PHPMailer(true); + //Server settings + $mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output + $mail->isSMTP(); // Send using SMTP + $mail->Host = 'smtp1.example.com'; // Set the SMTP server to send through + $mail->SMTPAuth = true; // Enable SMTP authentication + $mail->Username = 'user@example.com'; // SMTP username + $mail->Password = 'secret'; // SMTP password + $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged + $mail->Port = 587; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above + + //Recipients + $mail->setFrom('system@example.com', '系统管理员'); + $mail->addAddress($email, $nickname); // Add a recipient + + // Attachments +// $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments +// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name + + // Content + $mail->isHTML(true); // Set email format to HTML + $mail->Subject = 'Here is the subject'; + $mail->Body = 'This is the HTML message body in bold!'; + $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; + + $mail->send(); + echo 'Message has been sent'; + } catch (Exception $e) { + echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; + } + } + + +} diff --git a/http-server/Events/Trigger/OnStart.php b/http-server/Events/OnStart.php similarity index 86% rename from http-server/Events/Trigger/OnStart.php rename to http-server/Events/OnStart.php index eeabb94d..c25bab9b 100644 --- a/http-server/Events/Trigger/OnStart.php +++ b/http-server/Events/OnStart.php @@ -1,10 +1,10 @@ event; $event->trigger(Event::RELEASE_ALL); - - $this->endCoroutine(); Timer::clearAll(); } return $finish; diff --git a/http-server/Events/Trigger/OnWorkerError.php b/http-server/Events/OnWorkerError.php similarity index 77% rename from http-server/Events/Trigger/OnWorkerError.php rename to http-server/Events/OnWorkerError.php index 93cb8e5e..e9ef9f1c 100644 --- a/http-server/Events/Trigger/OnWorkerError.php +++ b/http-server/Events/OnWorkerError.php @@ -1,10 +1,10 @@ worker_pid); $get_name = $this->get_process_name($server, $worker_id); @@ -69,7 +67,7 @@ class OnWorkerStart extends Callback } $event->trigger(Event::SERVER_WORKER_START); } catch (\Throwable $exception) { - Logger::write($exception->getMessage(), 'worker'); + Snowflake::get()->getLogger()->write($exception->getMessage(), 'worker'); } } diff --git a/http-server/Events/Trigger/OnWorkerStop.php b/http-server/Events/OnWorkerStop.php similarity index 76% rename from http-server/Events/Trigger/OnWorkerStop.php rename to http-server/Events/OnWorkerStop.php index 96c94901..7eb531c2 100644 --- a/http-server/Events/Trigger/OnWorkerStop.php +++ b/http-server/Events/OnWorkerStop.php @@ -1,10 +1,10 @@ set($host . ':' . $port, $this); - $this->application = $application; - parent::__construct($host, $port, $mode, $sock_type); - } - - - /** - * @param array $settings - * @param null $pool - * @param array $events - * @param array $config - * @return mixed|void - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - public function set(array $settings, $pool = null, $events = [], $config = []) - { - parent::set($settings); - ServerManager::set($this, $settings, $this->application, $events, $config); - } - - - /** - * @param $callbacks - */ - protected function bindCallback($callbacks) - { - if (empty($callbacks) || !is_array($callbacks)) { - return; - } - foreach ($callbacks as $callback) { - $this->on($callback[0], [$this, $callback[1][1]]); - } - } - - - /** - * @param $eventName - * @return array - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - protected function createHandler($eventName) - { - $classPrefix = 'HttpServer\Events\Trigger\On' . ucfirst($eventName); - if (!class_exists($classPrefix)) { - throw new Exception('class not found.'); - } - $class = Snowflake::createObject($classPrefix, [Snowflake::get()]); - return [$class, 'onHandler']; - } - - - /** - * @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); - } - -} diff --git a/http-server/Events/Trigger/OnClose.php b/http-server/Events/Trigger/OnClose.php deleted file mode 100644 index 49378a49..00000000 --- a/http-server/Events/Trigger/OnClose.php +++ /dev/null @@ -1,17 +0,0 @@ -set(WebSocket::class, $this); - $this->application = $application; - parent::__construct($host, $port, $mode, $sock_type); - } - - - /** - * @param array $settings - * @param null $pool - * @param array $events - * @param array $config - * @return mixed|void - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - public function set(array $settings, $pool = null, $events = [], $config = []) - { - parent::set($settings); - - ServerManager::set($this, $settings, $this->application, $events, $config); - } - - - /** - * @param Server $server - * @param Frame $frame - * @throws - */ - public function onMessage(Server $server, Frame $frame) - { - try { - if ($frame->opcode == 0x08) { - return; - } - - $event = Snowflake::get()->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::get()->annotation->get('websocket'); - $manager->runWith($manager->getName(AWebsocket::MESSAGE, [null, null, $frame->data['route']]), [$frame, $server]); - } catch (Exception $exception) { - $this->application->addError($exception->getMessage(), 'websocket'); - $server->send($frame->fd, $exception->getMessage()); - } 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) - { - /** @var AWebsocket $manager */ - $manager = Snowflake::get()->annotation->get('websocket'); - $manager->runWith($manager->getName(AWebsocket::HANDSHAKE), [$request, $response]); - 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); - } - return $this->connect($request, $response); - } - - /** - * @param Server $server - * @param int $fd - * @throws Exception - */ - public function onClose(Server $server, int $fd) - { - try { - /** @var AWebsocket $manager */ - $manager = Snowflake::get()->annotation->get('websocket'); - $manager->runWith($manager->getName(AWebsocket::CLOSE), [$fd]); - } catch (\Throwable $exception) { - $this->application->addError($exception->getMessage()); - } finally { - $event = Snowflake::get()->event; - $event->trigger(Event::RELEASE_ALL); - Logger::insert(); - } - } - -} diff --git a/http-server/IInterface/Service.php b/http-server/IInterface/Service.php new file mode 100644 index 00000000..b883bd7f --- /dev/null +++ b/http-server/IInterface/Service.php @@ -0,0 +1,13 @@ + [SWOOLE_SOCK_TCP, WebSocket::class], ]; + /** @var Http|WebSocket|Packet|Receive */ + private $baseServer; + + /** * @param array $configs - * @return array + * @return Http|Packet|Receive|WebSocket * @throws Exception */ public function initCore(array $configs) { - $response = []; + $configs = $this->sortServers($configs); foreach ($configs as $server) { - $response[] = $this->create($server); + $this->create($server); } - return $response; + $this->onProcessListener(); + return $this->getServer(); + } + + + /** + * @throws ReflectionException + * @throws ConfigException + * @throws NotFindClassException + * @throws Exception + */ + public function onProcessListener() + { + $processes = Config::get('processes'); + if (empty($processes) || !is_array($processes)) { + return; + } + + $application = Snowflake::get(); + foreach ($processes as $name => $process) { + $class = Snowflake::createObject($process); + + if (!method_exists($class, 'onHandler')) { + continue; + } + + $system = new Process([$class, 'onHandler'], false, null, true); + if (Snowflake::isLinux()) { + $system->name($name); + } + $this->baseServer->addProcess($system); + $application->set($name, $process); + } + } + + + /** + * @return Http|WebSocket|Packet|Receive + */ + public function getServer() + { + return $this->baseServer; } @@ -74,6 +129,7 @@ class Server extends Application /** * @param $config + * @throws Exception */ protected function createEventListen($config) { @@ -94,33 +150,83 @@ class Server extends Application */ private function dispatchCreate($config, $settings) { - switch ($config['type']) { - case self::HTTP: - $handler = [ - ['request', [Http::class, 'onHandler']] - ]; - break; - case self::TCP: - $handler = [ - ['receive', [Receive::class, 'onReceive']] - ]; - break; - case self::PACKAGE: - $handler = [ - ['packet', [Packet::class, 'onHandler']] - ]; - break; - case self::WEBSOCKET: - $handler = [ - ['handshake', [WebSocket::class, 'onHandshake']], - ['message', [WebSocket::class, 'onMessage']], - ['close', [WebSocket::class, 'onClose']], - ]; - break; - default: - throw new Exception('Unknown server type(' . $config['type'] . ').'); + if (!($this->baseServer instanceof \Swoole\Server)) { + $this->baseServer = new ($this->dispatch($config['type']))(); + $this->baseServer->set($settings); + } else { + $newListener = $this->baseServer->addlistener($config['host'], $config['port'], SWOOLE_TCP); + if (!empty($settings)) { + $newListener->set($settings); + } + $this->onListenerBind($config, $newListener); } - return [$this->server[$config['type']], $config, $handler, $settings]; + return $this->baseServer; + } + + + /** + * @param $config + * @param $newListener + * @throws Exception + */ + private function onListenerBind($config, $newListener) + { + if ($config['type'] == self::HTTP) { + $newListener->on('request', [OnRequest::class, 'onHandler']); + } else if ($config['type'] == self::TCP || $config['type'] == self::PACKAGE) { + $newListener->on('connect', [OnConnect::class, 'onHandler']); + $newListener->on('close', [OnClose::class, 'onHandler']); + if ($config['type'] == self::PACKAGE) { + $newListener->on('packet', [OnPacket::class, 'onHandler']); + } else { + $newListener->on('receive', [OnReceive::class, 'onHandler']); + } + $newListener->on('connect', [OnConnect::class, 'onHandler']); + $newListener->on('close', [OnClose::class, 'onHandler']); + } else if ($config['type'] == self::WEBSOCKET) { + throw new Exception('Base server must instanceof \Swoole\WebSocket\Server::class.'); + } else { + throw new Exception('Unknown server type(' . $config['type'] . ').'); + } + } + + + /** + * @param $type + * @return string + */ + private function dispatch($type) + { + $default = [ + self::HTTP => \Swoole\Http\Server::class, + self::WEBSOCKET => \Swoole\WebSocket\Server::class, + self::TCP => \Swoole\Server::class, + self::PACKAGE => \Swoole\Server::class + ]; + return $default[$type] ?? \Swoole\Server::class; + } + + /** + * @param $servers + * @return array + */ + private function sortServers($servers) + { + $array = []; + foreach ($servers as $server) { + switch ($server['type']) { + case self::WEBSOCKET: + array_unshift($array, $server); + break; + case self::HTTP: + case self::PACKAGE | self::TCP: + $array[] = $server; + break; + default: + $array[] = $server; + } + } + return $array; } diff --git a/http-server/ServerManager.php b/http-server/ServerManager.php deleted file mode 100644 index 4c666da6..00000000 --- a/http-server/ServerManager.php +++ /dev/null @@ -1,191 +0,0 @@ -set($settings ?? [], $pool, $handlers, $config); - static::notice($application, $workerId, $config); - if (property_exists($server, 'pack')) { - $server->pack = $config['message']['pack'] ?? function ($data) { - return $data; - }; - } - if (property_exists($server, 'unpack')) { - $server->unpack = $config['message']['unpack'] ?? function ($data) { - return $data; - }; - } - return $server->start(); - } catch (Exception $exception) { - echo $exception->getMessage() . PHP_EOL; - return $pool->shutdown(); - } - } - - - /** - * @param $application - * @param $config - * @param $category - * @return array - */ - protected static function parameter($application, $config, $category) - { - return [$application, $config['host'], $config['port'], SWOOLE_PROCESS, $category[0]]; - } - - - /** - * @param $process - * @param $application - * @param $pool - * @param $workerId - * @return mixed - */ - protected static function createProcess($process, $application, $pool, $workerId) - { - $process = new $process($application); - $application->debug(sprintf('Worker #%d is running.', $workerId)); - return $process->start(); - } - - - /** - * @param $application - * @param $workerId - * @param $config - */ - protected static function notice($application, $workerId, $config) - { - $application->debug(sprintf('Worker #%d Listener %s::%d is running.', $workerId, $config['host'], $config['port'])); - } - - /** - * @param $server - * @param $settings - * @param \Snowflake\Application $application - * @param array $events - * @param array $config - * @return mixed|void - * @throws NotFindClassException - * @throws ReflectionException - */ - public static function set($server, $settings, $application, $events = [], $config = []) - { - $server->on('start', static::createHandler('start')); - $server->on('shutdown', static::createHandler('shutdown')); - $server->on('workerStop', static::createHandler('workerStop')); - $server->on('workerExit', static::createHandler('workerExit')); - $server->on('workerStart', static::createHandler('workerStart')); - $server->on('workerError', static::createHandler('workerError')); - $server->on('managerStop', static::createHandler('managerStop')); - $server->on('managerStart', static::createHandler('managerStart')); - static::addListener($server, $application, $config); - static::bindCallback($server, $events); - static::addTask($server, $settings); - } - - - /** - * @param $server - * @param $settings - * @throws NotFindClassException - * @throws ReflectionException - */ - protected static function addTask($server, $settings) - { - if (($taskNumber = $settings['task_worker_num'] ?? 0) > 0) { - $server->on('finish', static::createHandler('finish')); - $callback = static::createHandler('task'); - if ($settings['task_enable_coroutine'] ?? false) { - $server->on('task', [$callback, 'onContinueTask']); - } else { - $server->on('task', [$callback, 'onTask']); - } - } - } - - - /** - * @param $server - * @param $application - * @param $config - * @return void - */ - protected static function addListener($server, $application, $config) - { - $grpc = $config['grpc'] ?? []; - if (empty($grpc) || !is_array($grpc)) { - return; - } - $listener = $server->addListener($grpc['host'], $grpc['port'], $grpc['mode']); - $listener->set($grpc['settings'] ?? []); - if (!isset($grpc['receive'])) { - $application->error(sprintf('must add listener %s::%s callback', $grpc['host'], $grpc['port'])); - return; - } - if ($grpc['receive'] instanceof \Closure) { - $grpc['receive'] = \Closure::bind($grpc['receive'], $server); - } - $listener->on('receive', $grpc['receive']); - } - - - /** - * @param $server - * @param $callbacks - */ - protected static function bindCallback($server, $callbacks) - { - if (empty($callbacks) || !is_array($callbacks)) { - return; - } - foreach ($callbacks as $callback) { - $server->on($callback[0], [$server, $callback[1][1]]); - } - } - - - /** - * @param $eventName - * @return array - * @throws NotFindClassException - * @throws ReflectionException - * @throws Exception - */ - protected static function createHandler($eventName) - { - $classPrefix = 'HttpServer\Events\Trigger\On' . ucfirst($eventName); - if (!class_exists($classPrefix)) { - throw new Exception('class not found.'); - } - $class = Snowflake::createObject($classPrefix, [Snowflake::get()]); - return [$class, 'onHandler']; - } - -} diff --git a/http-server/Service/Abstracts/Http.php b/http-server/Service/Abstracts/Http.php new file mode 100644 index 00000000..993d5b97 --- /dev/null +++ b/http-server/Service/Abstracts/Http.php @@ -0,0 +1,17 @@ +application = Snowflake::get(); + parent::__construct($host, $port, $mode, $sock_type); + } + + + /** + * @param array $settings + * @return mixed|void + */ + public function set(array $settings) + { + parent::set($settings); // TODO: Change the autogenerated stub + $this->onInit(); + } + + + /** + * @return mixed|void + * @throws NotFindClassException + * @throws ReflectionException + */ + public function onHandlerListener() + { + $this->on('start', $this->createHandler('start')); + $this->on('shutdown', $this->createHandler('shutdown')); + $this->on('workerStop', $this->createHandler('workerStop')); + $this->on('workerExit', $this->createHandler('workerExit')); + $this->on('workerStart', $this->createHandler('workerStart')); + $this->on('workerError', $this->createHandler('workerError')); + $this->on('managerStop', $this->createHandler('managerStop')); + $this->on('managerStart', $this->createHandler('managerStart')); + $this->addTask(); + } + + + /** + * @throws NotFindClassException + * @throws ReflectionException + */ + protected function addTask() + { + $settings = $this->setting; + if (($taskNumber = $settings['task_worker_num'] ?? 0) > 0) { + $this->on('finish', $this->createHandler('finish')); + $callback = $this->createHandler('task'); + if ($settings['task_enable_coroutine'] ?? false) { + $this->on('task', [$callback, 'onContinueTask']); + } else { + $this->on('task', [$callback, 'onTask']); + } + } + } + + + /** + * @param $eventName + * @return array + * @throws NotFindClassException + * @throws ReflectionException + * @throws Exception + */ + protected function createHandler($eventName) + { + $classPrefix = 'HttpServer\Events\On' . ucfirst($eventName); + if (!class_exists($classPrefix)) { + throw new Exception('class not found.'); + } + $class = Snowflake::createObject($classPrefix, [Snowflake::get()]); + return [$class, 'onHandler']; + } + + +} diff --git a/http-server/Service/Abstracts/Tcp.php b/http-server/Service/Abstracts/Tcp.php new file mode 100644 index 00000000..0b2de150 --- /dev/null +++ b/http-server/Service/Abstracts/Tcp.php @@ -0,0 +1,24 @@ +onHandlerListener(); + $this->onBaseListener(); + } + + + /** + * @throws NotFindClassException + * @throws ReflectionException + */ + public function onBaseListener() + { + $this->on('request', $this->createHandler('request')); + } + + +} diff --git a/http-server/Service/Packet.php b/http-server/Service/Packet.php new file mode 100644 index 00000000..616064db --- /dev/null +++ b/http-server/Service/Packet.php @@ -0,0 +1,46 @@ +onHandlerListener(); + $this->onBaseListener(); + } + + + /** + * @throws NotFindClassException + * @throws ReflectionException + */ + public function onBaseListener() + { + $this->on('connect', $this->createHandler('connect')); + $this->on('packet', $this->createHandler('packet')); + $this->on('close', $this->createHandler('close')); + } + + +} diff --git a/http-server/Service/Receive.php b/http-server/Service/Receive.php new file mode 100644 index 00000000..4185627a --- /dev/null +++ b/http-server/Service/Receive.php @@ -0,0 +1,46 @@ +onHandlerListener(); + $this->onBaseListener(); + } + + + /** + * @throws NotFindClassException + * @throws ReflectionException + */ + public function onBaseListener() + { + $this->on('connect', $this->createHandler('connect')); + $this->on('receive', $this->createHandler('receive')); + $this->on('close', $this->createHandler('close')); + } + + +} diff --git a/http-server/Service/Websocket.php b/http-server/Service/Websocket.php new file mode 100644 index 00000000..fc6018b2 --- /dev/null +++ b/http-server/Service/Websocket.php @@ -0,0 +1,45 @@ +onHandlerListener(); + $this->onBaseListener(); + } + + + /** + * @throws NotFindClassException + * @throws ReflectionException + */ + public function onBaseListener() + { + $this->on('handshake', $this->createHandler('handshake')); + $this->on('message', $this->createHandler('message')); + $this->on('close', $this->createHandler('close')); + } + +} diff --git a/http-server/config.php b/http-server/config.php index 04a003a0..e0f0c5ab 100644 --- a/http-server/config.php +++ b/http-server/config.php @@ -78,19 +78,6 @@ return [ 'worker_num' => 10, 'enable_coroutine' => 1 ], - 'grpc' => [ - 'host' => '127.0.0.1', - 'port' => 5555, - 'mode' => SWOOLE_SOCK_TCP, - 'receive' => function ($server, int $fd, int $reactorId, string $data) { - $server->push(1, 'success.'); - $server->send($fd, 'success.'); - - $socket = Snowflake::get()->get(\HttpServer\Events\WebSocket::class); - $socket->push(1, 'hello word~~~~~~~~~~~~~'); - }, - 'settings' => [] - ], 'events' => [ Event::SERVER_WORKER_START => function () { $path = APP_PATH . 'app/Websocket'; diff --git a/system/Abstracts/BaseApplication.php b/system/Abstracts/BaseApplication.php index 51b6f711..4fca5e95 100644 --- a/system/Abstracts/BaseApplication.php +++ b/system/Abstracts/BaseApplication.php @@ -307,7 +307,6 @@ abstract class BaseApplication extends Service } - /** * @return Router * @throws ComponentException @@ -348,6 +347,7 @@ abstract class BaseApplication extends Service 'router' => ['class' => Router::class], 'redis' => ['class' => Redis::class], 'jwt' => ['class' => Jwt::class], + 'server' => ['class' => Server::class], ]); } } diff --git a/system/Abstracts/BaseObject.php b/system/Abstracts/BaseObject.php index 6c02c312..7135588c 100644 --- a/system/Abstracts/BaseObject.php +++ b/system/Abstracts/BaseObject.php @@ -134,7 +134,6 @@ class BaseObject implements Configure } echo "\033[35m[DEBUG][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m"; echo PHP_EOL; - Logger::trance($message, 'debug'); } @@ -151,7 +150,6 @@ class BaseObject implements Configure } echo "\033[34m[INFO][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m"; echo PHP_EOL; - Logger::trance($message, 'info'); } /** @@ -167,7 +165,6 @@ class BaseObject implements Configure } echo "\033[36m[SUCCESS][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m"; echo PHP_EOL; - Logger::trance($message, 'success'); } @@ -184,7 +181,6 @@ class BaseObject implements Configure } echo "\033[33m[SUCCESS][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m"; echo PHP_EOL; - Logger::trance($message, 'warning'); } @@ -194,7 +190,7 @@ class BaseObject implements Configure * @param string|null $file * @throws Exception */ - public function error($message, string $method = null, string $file = null) + public function error($message, $method = null, $file = null) { if (!empty($file)) { echo "\033[41;37m[ERROR][" . date('Y-m-d H:i:s') . ']: ' . $file . "\033[0m"; @@ -205,7 +201,6 @@ class BaseObject implements Configure } echo "\033[41;37m[ERROR][" . date('Y-m-d H:i:s') . ']: ' . (empty($method) ? '' : $method . ': ') . $message . "\033[0m"; echo PHP_EOL; - Logger::error($message, 'error'); } } diff --git a/system/Application.php b/system/Application.php index 0f53e5b8..99662926 100644 --- a/system/Application.php +++ b/system/Application.php @@ -34,16 +34,12 @@ class Application extends BaseApplication */ public function init() { + /** @var Server $https */ + $https = $this->make(Server::class, Server::class); + $https->initCore(Config::get('servers', true)); + $process = Snowflake::get()->processes; - if (Config::has('servers', true)) { - /** @var Server $https */ - $https = $this->make(Server::class, Server::class); - $servers = $https->initCore(Config::get('servers')); - $process->push($servers); - } - if (Config::has('processes', true)) { - $process->push(Config::get('processes')); - } + $process->initCore(); } diff --git a/system/Error/ErrorHandler.php b/system/Error/ErrorHandler.php index d29a2ca3..b1a77d4b 100644 --- a/system/Error/ErrorHandler.php +++ b/system/Error/ErrorHandler.php @@ -101,7 +101,7 @@ class ErrorHandler extends Component implements ErrorInterface $data = JSON::to(500, 'Error : ' . $error[1], $path); - Logger::error($data, 'error'); + Snowflake::get()->getLogger()->error($data, 'error'); $event = Snowflake::get()->event; $event->trigger(Event::RELEASE_ALL); @@ -123,7 +123,7 @@ class ErrorHandler extends Component implements ErrorInterface $data = JSON::to($code, $this->category . ': ' . $message, $path); - Logger::trance($data, $this->category); + Snowflake::get()->getLogger()->trance($data, $this->category); return response()->send($data); } @@ -154,6 +154,6 @@ class ErrorHandler extends Component implements ErrorInterface */ public function writer($message, $category = 'app') { - Logger::debug($message, $category); + Snowflake::get()->getLogger()->debug($message, $category); } } diff --git a/system/Error/Logger.php b/system/Error/Logger.php index 3da4d1ea..fdc09e4f 100644 --- a/system/Error/Logger.php +++ b/system/Error/Logger.php @@ -9,6 +9,7 @@ namespace Snowflake\Error; use Exception; +use Snowflake\Abstracts\Component; use Snowflake\Core\JSON; use Snowflake\Snowflake; use Swoole\Process; @@ -17,21 +18,23 @@ use Swoole\Process; * Class Logger * @package Snowflake\Snowflake\Error */ -class Logger +class Logger extends Component { - private static $logs = []; + private $logs = []; - public static $worker_id; + public $worker_id; /** * @param $message * @param string $category + * @param null $_ * @throws Exception */ - public static function debug($message, $category = 'app') + public function debug($message, $category = 'app', $_ = null) { - static::writer($message, $category); + parent::debug($message); + $this->writer($message, $category); } @@ -40,30 +43,34 @@ class Logger * @param string $category * @throws Exception */ - public static function trance($message, $category = 'app') + public function trance($message, $category = 'app') { - static::writer($message, $category); + $this->writer($message, $category); } /** * @param $message * @param string $category + * @param null $_ * @throws Exception */ - public static function error($message, $category = 'app') + public function error($message, $category = 'error', $_ = null) { - static::writer($message, $category); + parent::error($message); + $this->writer($message, $category); } /** * @param $message * @param string $category + * @param null $_ * @throws Exception */ - public static function success($message, $category = 'app') + public function success($message, $category = 'app', $_ = null) { - static::writer($message, $category); + parent::success($message); + $this->writer($message, $category); } /** @@ -72,23 +79,23 @@ class Logger * @return string * @throws Exception */ - private static function writer($message, $category = 'app') + private function writer($message, $category = 'app') { if ($message instanceof \Throwable) { $message = $message->getMessage(); } else { if (is_array($message) || is_object($message)) { - $message = static::arrayFormat($message); + $message = $this->arrayFormat($message); } } if (is_array($message)) { - $message = static::arrayFormat($message); + $message = $this->arrayFormat($message); } if (!empty($message)) { - if (!is_array(static::$logs)) { - static::$logs = []; + if (!is_array($this->$logs)) { + $this->$logs = []; } - static::$logs[] = [$category, $message]; + $this->$logs[] = [$category, $message]; } return $message; } @@ -99,7 +106,7 @@ class Logger * @param $category * @throws Exception */ - public static function print_r($message, $category = '') + public function print_r($message, $category = '') { /** @var Process $logger */ $logger = Snowflake::get()->logger; @@ -111,10 +118,10 @@ class Logger * @param string $application * @return mixed */ - public static function getLastError($application = 'app') + public function getLastError($application = 'app') { $_tmp = []; - foreach (static::$logs as $key => $val) { + foreach ($this->logs as $key => $val) { if ($val[0] != $application) { continue; } @@ -131,7 +138,7 @@ class Logger * @param string $category * @throws Exception */ - public static function write(string $messages, $category = 'app') + public function write(string $messages, $category = 'app') { if (empty($messages)) { return; @@ -146,7 +153,7 @@ class Logger * @param $logFile * @return false|string */ - private static function getSource($logFile) + private function getSource($logFile) { if (!file_exists($logFile)) { shell_exec('echo 3 > /proc/sys/vm/drop_caches'); @@ -162,37 +169,37 @@ class Logger * @throws Exception * 写入日志 */ - public static function insert() + public function insert() { - if (empty(static::$logs)) { + if (empty($this->logs)) { return; } - foreach (static::$logs as $log) { + foreach ($this->logs as $log) { [$category, $message] = $log; - static::write($message, $category); + $this->write($message, $category); } - static::$logs = []; + $this->logs = []; } /** * @return array */ - public static function clear() + public function clear() { - return static::$logs = []; + return $this->logs = []; } /** * @param $data * @return string */ - private static function arrayFormat($data) + private function arrayFormat($data) { if (is_string($data)) { return $data; } if ($data instanceof Exception) { - $data = static::getException($data); + $data = $this->getException($data); } else if (is_object($data)) { $data = get_object_vars($data); } @@ -200,7 +207,7 @@ class Logger $_tmp = []; foreach ($data as $key => $val) { if (is_array($val)) { - $_tmp[] = static::arrayFormat($val); + $_tmp[] = $this->arrayFormat($val); } else { $_tmp[] = (is_string($key) ? $key . ' : ' : '') . $val; } @@ -212,7 +219,7 @@ class Logger * @param Exception $exception * @return array */ - private static function getException($exception) + private function getException($exception) { $_tmp = [$exception->getMessage()]; $_tmp[] = $exception->getFile() . ' on line ' . $exception->getLine(); diff --git a/system/Processes.php b/system/Processes.php index f5bc52d5..9be41f62 100644 --- a/system/Processes.php +++ b/system/Processes.php @@ -5,7 +5,6 @@ namespace Snowflake; use Exception; -use HttpServer\ServerManager; use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; use Snowflake\Abstracts\Component; @@ -27,75 +26,11 @@ class Processes extends Component */ public function initCore() { - $application = Snowflake::get(); - $server = $application->set(Pool::class, new Pool($this->size(), SWOOLE_IPC_UNIXSOCK)); - $server->on('workerStart', function (Pool $pool, int $workerId) use ($application) { - ServerManager::create($pool, $this->processes[$workerId], $workerId); - }); - $server->on('workerStop', function (Pool $pool, int $workerId) { - $event = Snowflake::get()->event; - if ($event->exists(Event::PROCESS_WORKER_STOP)) { - $event->trigger(Event::PROCESS_WORKER_STOP); - } + $manager = Snowflake::get()->servers; - $email = Config::get('admin.email'); - if (!empty($email)) { - $nickname = Config::get('admin.name', false, '亲爱的开发者'); - $this->system_mail($email, $nickname); - } - }); - $server->on('message', function (Pool $pool, $message) { - file_put_contents(storage('a.log'), $message); - }); - return $server; - } + $serverConfig = Config::get('servers', true); - - /** - * @param $email - * @param $nickname - */ - protected function system_mail($email, $nickname) - { - try { - $mail = new PHPMailer(true); - //Server settings - $mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output - $mail->isSMTP(); // Send using SMTP - $mail->Host = 'smtp1.example.com'; // Set the SMTP server to send through - $mail->SMTPAuth = true; // Enable SMTP authentication - $mail->Username = 'user@example.com'; // SMTP username - $mail->Password = 'secret'; // SMTP password - $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged - $mail->Port = 587; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above - - //Recipients - $mail->setFrom('system@example.com', '系统管理员'); - $mail->addAddress($email, $nickname); // Add a recipient - - // Attachments -// $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments -// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name - - // Content - $mail->isHTML(true); // Set email format to HTML - $mail->Subject = 'Here is the subject'; - $mail->Body = 'This is the HTML message body in bold!'; - $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; - - $mail->send(); - echo 'Message has been sent'; - } catch (Exception $e) { - echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; - } - } - - /** - * @return int - */ - protected function size() - { - return count($this->processes); + return $manager->initCore($serverConfig); } @@ -107,17 +42,4 @@ class Processes extends Component $server = $this->initCore(); $server->start(); } - - - /** - * @param array $servers - * @return $this - */ - public function push(array $servers) - { - foreach ($servers as $server) { - $this->processes[] = $server; - } - return $this; - } }