protected function call($fd, $fromId, \stdClass $data)
{
$rpc = $data->rpc ?: static::$defaultRPC;
try {
if (isset(RPC::$__instance[$rpc][$fd])) {
# 复用已经存在的对象
$class = RPC::$__instance[$rpc][$fd];
} else {
$class = new $rpc($fd, $fromId);
if (!$class instanceof RPC) {
throw new \Exception("class {$rpc} not allow call by rpc");
}
}
$name = trim((string) $data->name);
$args = $data->args;
if ($name[0] === '_') {
throw new \Exception("{$name} not allowed to call");
}
switch ($data->type) {
case 'fun':
if (in_array(strtolower($name), static::$forbiddenAction)) {
throw new \Exception("{$name} not allowed to call");
}
$rs = call_user_func_array([$class, $name], $args ?: []);
break;
case 'set':
$class->{$name} = $args;
$rs = true;
break;
case 'get':
$rs = $class->{$name};
break;
default:
throw new \Exception("undefined type {$data->type}");
}
if ($class->isClosedByServer()) {
# 已经在程序里被关闭连接了
return;
}
} catch (\Exception $e) {
$rs = new \stdClass();
$rs->type = 'error';
$rs->code = $e->getCode();
$rs->msg = $e->getMessage();
}
if (is_object($rs) && $rs instanceof Result) {
$string = $rs->data;
$call = true;
} else {
$string = $rs;
$call = false;
}
/**
* @var RPC $rpc
*/
$key = $rpc::_getRpcKey();
$string = $key ? self::encrypt($string, $key) : msgpack_pack($string);
$status = $this->server->send($fd, $string, $fromId);
if ($call) {
/**
* @var Result $rs
*/
if (false === $status) {
$rs->trigger('error');
} else {
$rs->trigger('success');
}
$rs->trigger('complete');
}
}