Events.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. <?php
  2. /**
  3. * This file is part of workerman.
  4. *
  5. * Licensed under The MIT License
  6. * For full copyright and license information, please see the MIT-LICENSE.txt
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @author walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. /**
  15. * 用于检测业务代码死循环或者长时间阻塞等问题
  16. * 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
  17. * 然后观察一段时间workerman.log看是否有process_timeout异常
  18. */
  19. //declare(ticks=1);
  20. namespace addons\fastchat\library\GatewayWorker\Applications\FastChat;
  21. use addons\fastchat\library\Common;
  22. use GatewayWorker\Lib\Gateway;
  23. use Workerman\Lib\Timer;
  24. use think\Db;
  25. /**
  26. * 主逻辑
  27. * 主要是处理 onConnect onMessage onClose 三个方法
  28. * onConnect 和 onClose 如果不需要可以不用实现并删除
  29. */
  30. class Events
  31. {
  32. /**
  33. * WebSocket 链接成功
  34. *
  35. * @param int $client_id data
  36. * @param $[data] [websocket握手时的http头数据,包含get、server等变量]
  37. */
  38. public static function onWebSocketConnect($client_id, $data)
  39. {
  40. // 安全检查
  41. array_walk_recursive($data, array('addons\fastchat\library\Common', 'check_variable'));
  42. $config_data = get_addon_config('fastchat');
  43. $_SESSION['origin'] = 'http://' . $data['server']['SERVER_NAME'];//设置服务器域名
  44. if (!$config_data['anonymous_to_admin'] && !$config_data['anonymous_to_user'] && !$data['get']['token']) {
  45. // 禁止匿名发起会话,确认用户收到登录提示后,直接关闭链接
  46. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'clear', 'code' => 401]));
  47. return;
  48. }
  49. // 获取连接人信息
  50. $token_info = false;
  51. if ($data['get']['modulename'] == 'admin' && $data['get']['token']) {
  52. // 验证管理员身份
  53. $token_info = Common::check_admin($data['get']['token']);
  54. // 设置定时器,定时检测管理员身份是否过期
  55. // $_SESSION['auth_timer_id'] = Timer::add(30, function ($client_id, $token) {
  56. // $token_info = Common::check_admin($token);
  57. // if (!$token_info) {
  58. // Gateway::closeClient($client_id);
  59. // }
  60. // }, array($client_id, $data['get']['token']));
  61. } else if ($data['get']['modulename'] == 'user' && $data['get']['token']) {
  62. // 验证用户身份
  63. $token_info = Common::check_fa_user($data['get']['token'], 0);
  64. if ($token_info && $data['get']['fastchat_user']) {
  65. // 游客登录了
  66. Common::tourists_to_login($data['get']['fastchat_user'], $token_info['user_id']);
  67. }
  68. } else if ($data['get']['modulename'] == 'index' && $data['get']['fastchat_user']) {
  69. // 验证游客身份
  70. $token_info = Common::check_tourists($data['get']['fastchat_user']);
  71. if ($token_info && !$config_data['anonymous_to_admin'] && !$config_data['anonymous_to_user']) {
  72. // 禁止匿名发起会话,确认用户收到登录提示后,直接关闭链接
  73. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'clear', 'code' => 401]));
  74. }
  75. } else if ($data['get']['modulename'] == 'massager' && $data['get']['token']) {
  76. // 验证助教登录
  77. $token_info = Common::check_massager($data['get']['token']);
  78. }
  79. if ($token_info) {
  80. Gateway::bindUid($client_id, $token_info['user_id']);
  81. $_SESSION['user_id'] = $token_info['user_id'];
  82. } else {
  83. Gateway::sendToClient($client_id, json_encode([
  84. 'msgtype' => 'welcome_tourists',
  85. 'code' => 0,
  86. 'msg' => '未找到token!'
  87. ]));
  88. Gateway::closeClient($client_id);
  89. }
  90. // else if ($data['get']['modulename'] != 'admin') {
  91. // // 建立游客身份,cookie值发送到前台保存->已废弃,转由http处理
  92. // $tourists_max_id = Db::name('fastchat_tourists')->max('id');
  93. //
  94. // $token = Random::uuid();
  95. // $tourists = [
  96. // 'avatar' => '',// 随机头像->算了算了
  97. // 'nickname' => '游客 ' . $tourists_max_id,
  98. // 'token' => $token,
  99. // 'createtime' => time()
  100. // ];
  101. //
  102. // if (Db::name('fastchat_tourists')->insert($tourists)) {
  103. //
  104. // $tourists_id = Db::name('fastchat_tourists')->getLastInsID();
  105. //
  106. // $_SESSION['user_id'] = $tourists_id . '||tourists';
  107. // Gateway::bindUid($client_id, $_SESSION['user_id']);
  108. //
  109. // $keeptime = 864000;
  110. // $expiretime = time() + $keeptime;
  111. // $key = md5(md5($tourists_id) . md5($keeptime) . md5($expiretime) . $token);
  112. // $data = [$tourists_id, $keeptime, $expiretime, $key];
  113. //
  114. // // 为游客登录
  115. // $fastchat_tourists = implode('|', $data);
  116. // $token_info = Common::check_tourists($fastchat_tourists);
  117. // $_SESSION['user_id'] = $token_info['user_id'];
  118. //
  119. // Gateway::sendToClient($client_id, json_encode([
  120. // 'msgtype' => 'welcome_tourists',
  121. // 'code' => 1,
  122. // 'data' => $fastchat_tourists
  123. // ]));
  124. // } else {
  125. // Gateway::sendToClient($client_id, json_encode([
  126. // 'msgtype' => 'welcome_tourists',
  127. // 'code' => 0,
  128. // 'msg' => '会话服务异常!'
  129. // ]));
  130. // }
  131. //
  132. // } else {
  133. // $_SESSION['user_id'] = $client_id;
  134. // }
  135. $config_data['new_msg'] = Common::get_unread_messages($_SESSION['user_id'], true);
  136. $config_data['user_info'] = $token_info;
  137. $config_data['service_user'] = Db::name("fastchat_service_user")->order("id", "ASC")->find();
  138. // 向当前client_id发送数据
  139. Gateway::sendToClient($client_id, json_encode(['msgtype' => 'config', 'data' => $config_data]));
  140. // 向所有人发送
  141. Gateway::sendToAll(json_encode([
  142. 'msgtype' => 'online',
  143. 'user_id' => $_SESSION['user_id']
  144. ]));
  145. }
  146. /**
  147. * 当客户端发来消息时触发
  148. * @param int $client_id 连接id
  149. * @param mixed $message 具体消息
  150. */
  151. public static function onMessage($client_id, $message)
  152. {
  153. // 分发到控制器
  154. $data = json_decode($message, true);
  155. // 安全检查
  156. array_walk_recursive($data, array('addons\fastchat\library\Common', 'check_variable'));
  157. if (!is_array($data) || !isset($data['c']) || !isset($data['a'])) {
  158. $res_data = array('msgtype' => 'notice', 'msg' => '错误的请求!');
  159. Gateway::sendToClient($client_id, json_encode($res_data));
  160. return;
  161. }
  162. if ($data['c'] == 'clear') {
  163. Gateway::closeClient($client_id);
  164. return '';
  165. }
  166. $filename = __DIR__ . '/controller/' . $data['c'] . '.php';//载入文件类似/controller/index.php
  167. if (file_exists($filename)) {
  168. require_once($filename);
  169. /*
  170. 检查要访问的类是否存在
  171. */
  172. if (!class_exists($data['c'], false)) {
  173. $res_data = array('msgtype' => 'notice', 'msg' => '您访问的控制器不存在!');
  174. Gateway::sendToClient($client_id, json_encode($res_data));
  175. return '';
  176. }
  177. } else {
  178. $res_data = array('msgtype' => 'notice', 'msg' => '您访问的页面并存在!');
  179. Gateway::sendToClient($client_id, json_encode($res_data));
  180. return '';
  181. }
  182. $o = new $data['c'](); // 新建对象
  183. if (!method_exists($o, $data['a'])) {
  184. $res_data = array('msgtype' => 'notice', 'msg' => '您访问的方法并存在!');
  185. Gateway::sendToClient($client_id, json_encode($res_data));
  186. return '';
  187. }
  188. $data['data'] = isset($data['data']) ? $data['data'] : '';
  189. call_user_func_array(array($o, $data['a']), array($client_id, $data['data']));//调用对象$o($c)里的方法$a
  190. }
  191. /**
  192. * 当用户断开连接时触发
  193. * @param int $client_id 连接id
  194. */
  195. public static function onClose($client_id)
  196. {
  197. if (isset($_SESSION['auth_timer_id'])) {
  198. Timer::del($_SESSION['auth_timer_id']);
  199. }
  200. // 向所有人发送
  201. if (isset($_SESSION['user_id'])) {
  202. $user_info = Common::user_info($_SESSION['user_id']);
  203. if (($user_info['session_type'] != 5) || ($user_info['session_type'] == 5 && $user_info['online_status'] == 1)) {
  204. Gateway::sendToAll(json_encode([
  205. 'msgtype' => 'offline',
  206. 'user_id' => $_SESSION['user_id']
  207. ]));
  208. }
  209. }
  210. }
  211. }