initial commit

This commit is contained in:
whale
2020-03-02 16:14:20 +08:00
parent 517082d159
commit 769b87af6a
132 changed files with 5424 additions and 2866 deletions

View File

@@ -0,0 +1,94 @@
<?php
namespace ZM\Event\Swoole;
use Closure;
use Framework\Console;
use Framework\ZMBuf;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Connection\ConnectionManager;
use Exception;
use ZM\Event\EventHandler;
use ZM\ModBase;
use ZM\ModHandleType;
use ZM\Utils\ZMUtil;
class MessageEvent implements SwooleEvent
{
/**
* @var Server
*/
public $server;
/**
* @var Frame
*/
public $frame;
public function __construct(Server $server, Frame $frame) {
$this->server = $server;
$this->frame = $frame;
}
/**
* @inheritDoc
*/
public function onActivate() {
ZMUtil::checkWait();
try {
if (ConnectionManager::get($this->frame->fd)->getType() == "qq") {
$data = json_decode($this->frame->data, true);
if (isset($data["post_type"]))
EventHandler::callCQEvent($data, $this, 0);
else
EventHandler::callCQResponse($data);
}
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
if (strtolower($v->type) == "message" && $this->parseSwooleRule($v)) {
$conn = ConnectionManager::get($this->frame->fd);
$c = $v->class;
/** @var ModBase $class */
$class = new $c(["server" => $this->server, "frame" => $this->frame, "connection" => $conn], ModHandleType::SWOOLE_MESSAGE);
call_user_func_array([$class, $v->method], [$conn]);
if ($class->block_continue) break;
}
}
} catch (Exception $e) {
Console::error("出现错误: " . $e->getMessage());
}
return $this;
}
/**
* @inheritDoc
*/
public function onAfter() {
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
if (strtolower($v->type) == "message" && $this->parseSwooleRule($v) === true) {
$conn = ConnectionManager::get($this->frame->fd);
$c = $v->class;
/** @var ModBase $class */
$class = new $c(["server" => $this->server, "frame" => $this->frame, "connection" => $conn], ModHandleType::SWOOLE_MESSAGE);
call_user_func_array([$class, $v->method], []);
if ($class->block_continue) break;
}
}
return $this;
}
private function parseSwooleRule($v) {
switch (explode(":", $v->rule)[0]) {
case "connectType": //websocket连接类型
if ($v->callback instanceof Closure) return call_user_func($v->callback, ConnectionManager::get($this->frame->fd));
break;
case "dataEqual": //handle websocket message事件时才能用
if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->frame->data);
break;
}
return true;
}
}

View File

@@ -0,0 +1,132 @@
<?php
namespace ZM\Event\Swoole;
use Closure;
use Framework\ZMBuf;
use Swoole\Http\Request;
use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Http\Response;
use ZM\ModBase;
use ZM\ModHandleType;
use ZM\Utils\ZMUtil;
class RequestEvent implements SwooleEvent
{
/**
* @var Request
*/
private $request;
/**
* @var Response
*/
private $response;
public function __construct(Request $request, Response $response) {
$this->request = $request;
$this->response = $response;
}
/**
* @inheritDoc
*/
public function onActivate() {
ZMUtil::checkWait();
foreach (ZMBuf::globals("http_header") as $k => $v) {
$this->response->setHeader($k, $v);
}
$uri = $this->request->server["request_uri"];
if ($uri != "/") {
$uri = explode("/", $uri);
$uri = array_diff($uri, ["..", "", "."]);
$node = ZMBuf::$req_mapping_node;
$params = [];
while (true) {
$r = array_shift($uri);
if ($r === null) break;
if (($node2 = $node->getRealRoute($r, $params)) !== null) {
$node = $node2;
continue;
} else {
$this->responseStatus(404);
return $this;
}
}
if ($node->getRule() === null || call_user_func($node->getRule(), $this->request) === true) { //判断规则是否存在,如果有规则则走一遍规则
if (in_array(strtoupper($this->request->server["request_method"]), $node->getRequestMethod())) { //判断目标方法在不在里面
$c_name = $node->getClass();
/** @var ModBase $class */
$class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST);
$r = call_user_func_array([$class, $node->getMethod()], [$params]);
if (is_string($r) && !$this->response->isEnd()) $this->response->end($r);
if ($class->block_continue) return $this;
if ($this->response->isEnd()) return $this;
}
}
} else {
if (($node = ZMBuf::$req_mapping_node)->getMethod() !== null) {
if (in_array(strtoupper($this->request->server["request_method"]), $node->getRequestMethod())) { //判断目标方法在不在里面
$c_name = $node->getClass();
/** @var ModBase $class */
$class = new $c_name(["request" => $this->request, "response" => $this->response], ModHandleType::SWOOLE_REQUEST);
$r = call_user_func_array([$class, $node->getMethod()], []);
if (is_string($r) && !$this->response->isEnd()) $this->response->end($r);
if ($class->block_continue) return $this;
if ($this->response->isEnd()) return $this;
}
}
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) {
$c = $v->class;
$class = new $c(["request" => $this->request, "response" => $this->response]);
$r = call_user_func_array([$class, $v->method], []);
if ($class->block_continue) break;
}
}
}
if (!$this->response->isEnd()) {
$this->response->status(404);
$this->response->end(ZMUtil::getHttpCodePage(404));
}
return $this;
}
/**
* @inheritDoc
*/
public function onAfter() {
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) {
$c = $v->class;
$class = new $c(["request" => $this->request, "response" => $this->response]);
call_user_func_array([$class, $v->method], []);
if ($class->block_continue) break;
}
}
return $this;
}
private function responseStatus(int $int) {
$this->response->status($int);
$this->response->end();
}
private function parseSwooleRule($v) {
switch ($v->rule) {
case "containsGet":
case "containsPost":
if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->request);
break;
case "containsJson":
$content = $this->request->rawContent();
$content = json_decode($content, true);
if ($content === null) return false;
if ($v->callback instanceof Closure) return call_user_func($v->callback, $content);
break;
}
return true;
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace ZM\Event\Swoole;
use ZM\Event\Event;
interface SwooleEvent extends Event
{
/**
* @return SwooleEvent
*/
public function onActivate();
/**
* @return SwooleEvent
*/
public function onAfter();
}

View File

@@ -0,0 +1,61 @@
<?php
namespace ZM\Event\Swoole;
use Framework\ZMBuf;
use Swoole\Server;
use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\ModBase;
use ZM\ModHandleType;
use ZM\Utils\ZMUtil;
class WSCloseEvent implements SwooleEvent
{
public $server;
public $fd;
public function __construct(Server $server, int $fd) {
$this->server = $server;
$this->fd = $fd;
}
/**
* @inheritDoc
*/
public function onActivate() {
ZMUtil::checkWait();
foreach(ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
if(strtolower($v->type) == "close" && $this->parseSwooleRule($v)) {
$c = $v->class;
$class = new $c(["server" => $this->server, "fd" => $this->fd], ModHandleType::SWOOLE_CLOSE);
call_user_func_array([$class, $v->method], []);
if($class->block_continue) break;
}
}
return $this;
}
/**
* @inheritDoc
*/
public function onAfter() {
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
if (strtolower($v->type) == "close" && $this->parseSwooleRule($v) === true) {
$c = $v->class;
/** @var ModBase $class */
$class = new $c(["server" => $this->server, "fd" => $this->fd], ModHandleType::SWOOLE_CLOSE);
call_user_func_array([$class, $v->method], []);
if($class->block_continue) break;
}
}
return $this;
}
private function parseSwooleRule($v) {
return true;
}
}

View File

@@ -0,0 +1,93 @@
<?php
namespace ZM\Event\Swoole;
use Closure;
use Framework\ZMBuf;
use Swoole\Http\Request;
use Swoole\WebSocket\Server;
use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Annotation\Swoole\SwooleEventAt;
use ZM\Connection\ConnectionManager;
use ZM\Connection\CQConnection;
use ZM\Connection\UnknownConnection;
use ZM\Connection\WSConnection;
use ZM\ModBase;
use ZM\ModHandleType;
use ZM\Utils\ZMUtil;
class WSOpenEvent implements SwooleEvent
{
/**
* @var Server
*/
private $server;
/**
* @var Request
*/
private $request;
/**
* @var WSConnection
*/
private $conn;
public function __construct(Server $server, Request $request) {
$this->server = $server;
$this->request = $request;
}
/**
* @inheritDoc
*/
public function onActivate() {
ZMUtil::checkWait();
$type = strtolower($this->request->get["type"] ?? $this->request->header["x-client-role"] ?? "");
$type_conn = ConnectionManager::getTypeClassName($type);
if ($type_conn == CQConnection::class) {
$qq = $this->request->get["qq"] ?? $this->request->header["x-self-id"] ?? "";
$self_token = ZMBuf::globals("access_token") ?? "";
$remote_token = $this->request->get["token"] ?? (isset($header["authorization"]) ? explode(" ", $this->request->header["authorization"])[1] : "");
if ($qq != "" && ($self_token == $remote_token)) $this->conn = new CQConnection($this->server, $this->request->fd, $qq);
else $this->conn = new UnknownConnection($this->server, $this->request->fd);
} else {
$this->conn = new $type_conn($this->server, $this->request->fd);
}
ZMBuf::$connect[$this->request->fd] = $this->conn;
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
if (strtolower($v->type) == "open" && $this->parseSwooleRule($v) === true) {
$c = $v->class;
$class = new $c(["server" => $this->server, "request" => $this->request, "connection" => $this->conn], ModHandleType::SWOOLE_OPEN);
call_user_func_array([$class, $v->method], [$this->conn]);
if ($class->block_continue) break;
}
}
return $this;
}
/**
* @inheritDoc
*/
public function onAfter() {
if (!$this->conn->exists()) return $this;
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
if (strtolower($v->type) == "open" && $this->parseSwooleRule($v) === true) {
/** @var ModBase $class */
$class = new $v["class"](["server" => $this->server, "request" => $this->request, "connection" => $this->conn], ModHandleType::SWOOLE_OPEN);
call_user_func_array([$class, $v["method"]], [$this->conn]);
if ($class->block_continue) break;
}
}
return $this;
}
private function parseSwooleRule($v) {
switch (explode(":", $v->rule)[0]) {
case "connectType": //websocket连接类型
if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->conn);
break;
}
return true;
}
}

View File

@@ -0,0 +1,137 @@
<?php
namespace ZM\Event\Swoole;
use Doctrine\Common\Annotations\AnnotationException;
use ReflectionException;
use Swoole\Coroutine;
use Swoole\Timer;
use ZM\Annotation\AnnotationBase;
use ZM\Annotation\AnnotationParser;
use ZM\Annotation\MappingNode;
use ZM\Annotation\Swoole\SwooleEventAfter;
use ZM\Connection\ConnectionManager;
use ZM\DB\DB;
use ZM\DBCache\DBCacheManager;
use Framework\Console;
use Framework\GlobalConfig;
use Framework\ZMBuf;
use Swoole\Server;
use ZM\ModBase;
use ZM\ModHandleType;
use ZM\Utils\DataProvider;
use ZM\Utils\SQLPool;
class WorkerStartEvent implements SwooleEvent
{
private $worker_id;
/**
* @var Server
*/
private $server;
public function __construct(Server $server, $worker_id) {
$this->server = $server;
$this->worker_id = $worker_id;
}
/**
* @return WorkerStartEvent
* @throws AnnotationException
* @throws ReflectionException
*/
public function onActivate(): WorkerStartEvent {
Console::info("Worker启动中");
ZMBuf::resetCache(); //清空变量缓存
ZMBuf::set("wait_start", []); //添加队列在workerStart运行完成前先让其他协程等待执行
DBCacheManager::freeAllCache(); // 清空数据库缓存
$this->resetConnections();//释放所有与framework的连接
//设置炸毛buf中储存的对象
ZMBuf::$globals = new GlobalConfig();
if (ZMBuf::globals("sql_config")["sql_host"] != "") {
Console::info("新建SQL连接池中");
ZMBuf::$sql_pool = new SQLPool();
DB::initTableList();
}
ZMBuf::$server = $this->server;
ZMBuf::$atomics['reload_time']->add(1);
ZMBuf::$req_mapping_node = new MappingNode("/");
Console::info("监听console输入");
Console::listenConsole(); //这个方法只能在这里调用且如果worker_num不为1的话此功能不可用
$this->loadAllClass(); //加载composer资源、phar外置包、注解解析注册等
$this->setAutosaveTimer(ZMBuf::globals("auto_save_interval"));
return $this;
}
public function onAfter(): WorkerStartEvent {
foreach (ZMBuf::get("wait_start") as $v) {
Coroutine::resume($v);
}
ZMBuf::unsetCache("wait_start");
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
/** @var AnnotationBase $v */
if (strtolower($v->type) == "workerstart") {
$class_name = $v->class;
/** @var ModBase $class */
$class = new $class_name(["server" => $this->server, "worker_id" => $this->worker_id], ModHandleType::SWOOLE_WORKER_START);
call_user_func_array([$class, $v->method], []);
if ($class->block_continue) break;
}
}
return $this;
}
private function resetConnections() {
foreach ($this->server->connections as $v) {
$this->server->close($v);
}
if (ZMBuf::$sql_pool instanceof SqlPool) {
ZMBuf::$sql_pool->destruct();
ZMBuf::$sql_pool = null;
}
}
/**
* @throws AnnotationException
* @throws ReflectionException
*/
private function loadAllClass() {
//加载phar包
Console::info("加载外部phar包中");
$dir = WORKING_DIR . "/resources/package/";
if (is_dir($dir)) {
$list = scandir($dir);
unset($list[0], $list[1]);
foreach ($list as $v) {
if (is_dir($dir . $v)) continue;
if (pathinfo($dir . $v, 4) == "phar") require_once($dir . $v);
}
}
//加载composer类
Console::info("加载composer资源中");
/** @noinspection PhpIncludeInspection */
require_once WORKING_DIR . "/vendor/autoload.php";
//加载各个模块的注解类,以及反射
Console::info("检索Module中");
AnnotationParser::registerMods();
//加载Custom目录下的自定义的内部类
ConnectionManager::registerCustomClass();
}
private function setAutosaveTimer($globals) {
DataProvider::$buffer_list = [];
Timer::tick($globals * 1000, function() {
DataProvider::saveBuffer();
});
}
}