* @copyright walkor * @link http://www.workerman.net/ * @license http://www.opensource.org/licenses/mit-license.php MIT License */ /** * 用于检测业务代码死循环或者长时间阻塞等问题 * 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload * 然后观察一段时间workerman.log看是否有process_timeout异常 */ //declare(ticks=1); namespace addons\fastchat\library\GatewayWorker\Applications\FastChat; use addons\fastchat\library\Common; use GatewayWorker\Lib\Gateway; use Workerman\Lib\Timer; use think\Db; /** * 主逻辑 * 主要是处理 onConnect onMessage onClose 三个方法 * onConnect 和 onClose 如果不需要可以不用实现并删除 */ class Events { /** * WebSocket 链接成功 * * @param int $client_id data * @param $[data] [websocket握手时的http头数据,包含get、server等变量] */ public static function onWebSocketConnect($client_id, $data) { // 安全检查 array_walk_recursive($data, array('addons\fastchat\library\Common', 'check_variable')); $config_data = get_addon_config('fastchat'); $_SESSION['origin'] = 'http://' . $data['server']['SERVER_NAME'];//设置服务器域名 if (!$config_data['anonymous_to_admin'] && !$config_data['anonymous_to_user'] && !$data['get']['token']) { // 禁止匿名发起会话,确认用户收到登录提示后,直接关闭链接 Gateway::sendToClient($client_id, json_encode(['msgtype' => 'clear', 'code' => 401])); return; } // 获取连接人信息 $token_info = false; if ($data['get']['modulename'] == 'admin' && $data['get']['token']) { // 验证管理员身份 $token_info = Common::check_admin($data['get']['token']); // 设置定时器,定时检测管理员身份是否过期 // $_SESSION['auth_timer_id'] = Timer::add(30, function ($client_id, $token) { // $token_info = Common::check_admin($token); // if (!$token_info) { // Gateway::closeClient($client_id); // } // }, array($client_id, $data['get']['token'])); } else if ($data['get']['modulename'] == 'user' && $data['get']['token']) { // 验证用户身份 $token_info = Common::check_fa_user($data['get']['token'], 0); if ($token_info && $data['get']['fastchat_user']) { // 游客登录了 Common::tourists_to_login($data['get']['fastchat_user'], $token_info['user_id']); } } else if ($data['get']['modulename'] == 'index' && $data['get']['fastchat_user']) { // 验证游客身份 $token_info = Common::check_tourists($data['get']['fastchat_user']); if ($token_info && !$config_data['anonymous_to_admin'] && !$config_data['anonymous_to_user']) { // 禁止匿名发起会话,确认用户收到登录提示后,直接关闭链接 Gateway::sendToClient($client_id, json_encode(['msgtype' => 'clear', 'code' => 401])); } } else if ($data['get']['modulename'] == 'massager' && $data['get']['token']) { // 验证助教登录 $token_info = Common::check_massager($data['get']['token']); } if ($token_info) { Gateway::bindUid($client_id, $token_info['user_id']); $_SESSION['user_id'] = $token_info['user_id']; } else { Gateway::sendToClient($client_id, json_encode([ 'msgtype' => 'welcome_tourists', 'code' => 0, 'msg' => '未找到token!' ])); Gateway::closeClient($client_id); } // else if ($data['get']['modulename'] != 'admin') { // // 建立游客身份,cookie值发送到前台保存->已废弃,转由http处理 // $tourists_max_id = Db::name('fastchat_tourists')->max('id'); // // $token = Random::uuid(); // $tourists = [ // 'avatar' => '',// 随机头像->算了算了 // 'nickname' => '游客 ' . $tourists_max_id, // 'token' => $token, // 'createtime' => time() // ]; // // if (Db::name('fastchat_tourists')->insert($tourists)) { // // $tourists_id = Db::name('fastchat_tourists')->getLastInsID(); // // $_SESSION['user_id'] = $tourists_id . '||tourists'; // Gateway::bindUid($client_id, $_SESSION['user_id']); // // $keeptime = 864000; // $expiretime = time() + $keeptime; // $key = md5(md5($tourists_id) . md5($keeptime) . md5($expiretime) . $token); // $data = [$tourists_id, $keeptime, $expiretime, $key]; // // // 为游客登录 // $fastchat_tourists = implode('|', $data); // $token_info = Common::check_tourists($fastchat_tourists); // $_SESSION['user_id'] = $token_info['user_id']; // // Gateway::sendToClient($client_id, json_encode([ // 'msgtype' => 'welcome_tourists', // 'code' => 1, // 'data' => $fastchat_tourists // ])); // } else { // Gateway::sendToClient($client_id, json_encode([ // 'msgtype' => 'welcome_tourists', // 'code' => 0, // 'msg' => '会话服务异常!' // ])); // } // // } else { // $_SESSION['user_id'] = $client_id; // } $config_data['new_msg'] = Common::get_unread_messages($_SESSION['user_id'], true); $config_data['user_info'] = $token_info; $config_data['service_user'] = Db::name("fastchat_service_user")->order("id", "ASC")->find(); // 向当前client_id发送数据 Gateway::sendToClient($client_id, json_encode(['msgtype' => 'config', 'data' => $config_data])); // 向所有人发送 Gateway::sendToAll(json_encode([ 'msgtype' => 'online', 'user_id' => $_SESSION['user_id'] ])); } /** * 当客户端发来消息时触发 * @param int $client_id 连接id * @param mixed $message 具体消息 */ public static function onMessage($client_id, $message) { // 分发到控制器 $data = json_decode($message, true); // 安全检查 array_walk_recursive($data, array('addons\fastchat\library\Common', 'check_variable')); if (!is_array($data) || !isset($data['c']) || !isset($data['a'])) { $res_data = array('msgtype' => 'notice', 'msg' => '错误的请求!'); Gateway::sendToClient($client_id, json_encode($res_data)); return; } if ($data['c'] == 'clear') { Gateway::closeClient($client_id); return ''; } $filename = __DIR__ . '/controller/' . $data['c'] . '.php';//载入文件类似/controller/index.php if (file_exists($filename)) { require_once($filename); /* 检查要访问的类是否存在 */ if (!class_exists($data['c'], false)) { $res_data = array('msgtype' => 'notice', 'msg' => '您访问的控制器不存在!'); Gateway::sendToClient($client_id, json_encode($res_data)); return ''; } } else { $res_data = array('msgtype' => 'notice', 'msg' => '您访问的页面并存在!'); Gateway::sendToClient($client_id, json_encode($res_data)); return ''; } $o = new $data['c'](); // 新建对象 if (!method_exists($o, $data['a'])) { $res_data = array('msgtype' => 'notice', 'msg' => '您访问的方法并存在!'); Gateway::sendToClient($client_id, json_encode($res_data)); return ''; } $data['data'] = isset($data['data']) ? $data['data'] : ''; call_user_func_array(array($o, $data['a']), array($client_id, $data['data']));//调用对象$o($c)里的方法$a } /** * 当用户断开连接时触发 * @param int $client_id 连接id */ public static function onClose($client_id) { if (isset($_SESSION['auth_timer_id'])) { Timer::del($_SESSION['auth_timer_id']); } // 向所有人发送 if (isset($_SESSION['user_id'])) { $user_info = Common::user_info($_SESSION['user_id']); if (($user_info['session_type'] != 5) || ($user_info['session_type'] == 5 && $user_info['online_status'] == 1)) { Gateway::sendToAll(json_encode([ 'msgtype' => 'offline', 'user_id' => $_SESSION['user_id'] ])); } } } }