fashilong.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. const network = require('./network')
  2. var server = require("http").createServer()
  3. const TLSSigAPIv2 = require("tls-sig-api-v2")
  4. const appids = require("./../config/appid")
  5. const api = new TLSSigAPIv2.Api(appids.fashilong.appid, appids.fashilong.key)
  6. const PORT = 3031
  7. const LEADER = "leader"
  8. let userCount = 0
  9. function getSig(userId) {
  10. return api.genSig(userId, 86400)
  11. }
  12. const EVENT = {
  13. someOneInRoom: "someOneInRoom", // 有人进入房间
  14. someOneLeaveRoom: "someOneLeaveRoom", // 有人离开房间
  15. startCall: "startCall", // 开始通话
  16. stopCall: "stopCall", // 结束通话
  17. webSyncAction: "webSyncAction", // 通知h5的事件
  18. clientSyncAction: "clientSyncAction", // 通知非H5的事件
  19. action: "action", // 通知所有连接设备的事件
  20. roomClose: "roomClose", // 房间已结束/房主已离开
  21. roomIn: "roomIn", // 通知设备成功进入房间
  22. changeVoiceStatus: "changeVoiceStatus", // 通知某设备语音状态
  23. changeOnlineStatus: "changeOnlineStatus", // 通知某设备的在线状态
  24. roomPersonChange: "roomPersonChange", // 房间人数变化事件
  25. changeRoomEnableTalk: "changeRoomEnableTalk", // 改变房间是否可通话的配置
  26. }
  27. const CODEMAP = {
  28. 3001: "房间已被解散",
  29. 3002: "房主主动解散",
  30. }
  31. module.exports = class WebSocketServer {
  32. constructor() {
  33. this._pageMap = new Map()
  34. this._roomIDS = new Map()
  35. this._roomPerson = new Map()
  36. this._roomsConfig = {}
  37. }
  38. create() {
  39. this.io = require("socket.io")(server, {
  40. path: "/fsl-node",
  41. serveClient: false,
  42. // below are engine.IO options
  43. pingInterval: 10000,
  44. pingTimeout: 5000,
  45. cookie: false,
  46. })
  47. server.listen(PORT, { origins: "*" })
  48. this.io.on("connection", socket => {
  49. let user = socket.handshake.query
  50. const { roomId, userId, sceneNum, isClient, role, userLimitNum, roomType } = user
  51. const webRoomId = `${roomId}_${sceneNum}_web`
  52. const clientRoom = `${userId}${roomId}`
  53. // 加入客户端与H5单独的通讯房间
  54. socket.join(clientRoom, () => {
  55. console.log(user, user.nickname && decodeURIComponent(user.nickname))
  56. })
  57. socket.on(EVENT.clientSyncAction, data => {
  58. //console.log(data, 'clientSyncAction')
  59. socket.broadcast.to(clientRoom).emit(EVENT.clientSyncAction, data)
  60. })
  61. socket.on(EVENT.changeVoiceStatus, data => {
  62. let _roomPerson = this._roomPerson.get(roomId) || []
  63. user.voiceStatus = data.status
  64. _roomPerson.forEach(item => {
  65. if (item.userId === user.userId) {
  66. item.voiceStatus = user.voiceStatus
  67. }
  68. })
  69. this._roomPerson.set(roomId, _roomPerson)
  70. socket.broadcast
  71. .to(roomId)
  72. .emit(EVENT.changeVoiceStatus, { roomsPerson: sortRoomUser(_roomPerson) })
  73. })
  74. // 房主,保存房间配置
  75. if (isClient && role === LEADER && !this._roomsConfig[roomId]) {
  76. //console.log('in', user)
  77. this._roomsConfig[roomId] = {
  78. userLimitNum,
  79. enableTalk: user.enableTalk,
  80. }
  81. }
  82. // 1v1保存房主
  83. if (roomType === "1v1" && !this._roomsConfig[roomId]) {
  84. //console.log(roomType, roomId, user)
  85. this._roomsConfig[roomId] = {
  86. leaderId: userId,
  87. }
  88. }
  89. if (roomType === "1v1" && sortRoomUser(this._roomPerson.get(roomId)).length > 2) {
  90. setTimeout(() => {
  91. socket.emit("roomInFail", {
  92. type: "full",
  93. msg: "房间人数已满",
  94. })
  95. }, 1000)
  96. return this
  97. }
  98. socket.on(EVENT.changeRoomEnableTalk, data => {
  99. this._roomsConfig[roomId].enableTalk = data
  100. socket.broadcast
  101. .to(roomId)
  102. .emit(EVENT.changeRoomEnableTalk, this._roomsConfig[roomId])
  103. })
  104. // 若有房间人数限制
  105. if (
  106. userLimitNum &&
  107. this._roomPerson.get(roomId) &&
  108. sortRoomUser(this._roomPerson.get(roomId)).length >= userLimitNum
  109. ) {
  110. setTimeout(() => {
  111. socket.emit("roomInFail", { type: "full", msg: "房间人数已满" })
  112. }, 1000)
  113. return this
  114. }
  115. let is1v1 = false
  116. if (this._roomsConfig[roomId]) {
  117. is1v1 = this._roomsConfig[roomId].leaderId === userId
  118. }
  119. //console.log(this._roomsConfig[roomId], userId, !is1v1, user.role !== LEADER, (this._roomPerson.get(roomId) && !this._roomPerson.get(roomId).find(item => item.role === LEADER)))
  120. // 非房主进来房间,判断房间是否存在,以及房间内是否有房主,若无则通知房间已关闭
  121. if (
  122. !is1v1 &&
  123. user.role !== LEADER &&
  124. ((this._roomPerson.get(roomId) &&
  125. !this._roomPerson.get(roomId).find(item => item.role === LEADER)) ||
  126. !this._roomPerson.get(roomId))
  127. ) {
  128. setTimeout(() => {
  129. socket.emit(EVENT.roomClose, { code: 3001, msg: CODEMAP[3001] })
  130. }, 1000)
  131. return this
  132. }
  133. // 加入所有连接数的通讯房间
  134. socket.join(roomId, () => {
  135. // 只有h5才能加入H5端的房间
  136. if (!isClient) {
  137. let roomsPerson = this._roomPerson.get(roomId) || []
  138. if (userId) {
  139. user.sig = getSig(userId)
  140. }
  141. let clientPerson = this._roomPerson.get(clientRoom) || []
  142. clientPerson.forEach(item => {
  143. if (item.userId === user.userId && item.avatar) {
  144. user.avatar = item.avatar
  145. user.voiceStatus = item.voiceStatus
  146. user.onlineStatus = item.onlineStatus
  147. user.nickname = decodeURIComponent(item.nickname)
  148. }
  149. })
  150. roomsPerson.push(user)
  151. this._roomPerson.set(roomId, roomsPerson)
  152. } else {
  153. // 通知客户端的房间配置
  154. let roomsPerson = this._roomPerson.get(roomId) || []
  155. socket.emit(EVENT.roomIn, {
  156. user,
  157. roomsPerson: sortRoomUser(roomsPerson),
  158. roomsConfig: this._roomsConfig[roomId],
  159. })
  160. }
  161. userCount++
  162. console.log("在线人数1:" + userCount)
  163. network.autoUpdate(userCount)
  164. })
  165. let clientPerson = this._roomPerson.get(clientRoom) || []
  166. if (isClient) {
  167. clientPerson.push(user)
  168. this._roomPerson.set(clientRoom, clientPerson)
  169. }
  170. if (!isClient) {
  171. socket.join(webRoomId, () => {
  172. //let roomsPerson = this._roomPerson.get(roomId) || []
  173. //socket.broadcast.to(roomId).emit(EVENT.someOneInRoom, { user, roomsPerson: sortRoomUser(roomsPerson) })
  174. let roomPerson = this._roomPerson.get(roomId)
  175. let __roomPerson = updateRoomUser(roomPerson, user)
  176. let actionName = ""
  177. socket.broadcast
  178. .to(roomId)
  179. .emit(EVENT.roomPersonChange, {
  180. roomsPerson: sortRoomUser(__roomPerson),
  181. actionName,
  182. user,
  183. })
  184. })
  185. }
  186. // 开始通话
  187. socket.on(EVENT.startCall, () => {
  188. if (!isClient) {
  189. let roomsPerson = this._roomPerson.get(roomId) || []
  190. // 返回h5房间内的信息
  191. socket.emit(EVENT.roomIn, {
  192. user,
  193. roomsPerson: sortRoomUser(roomsPerson),
  194. roomsConfig: this._roomsConfig[roomId],
  195. })
  196. // 判断是否某些情况断线重连
  197. if (!user.isInRoom) {
  198. socket.broadcast
  199. .to(roomId)
  200. .emit(EVENT.someOneInRoom, {
  201. user,
  202. roomsPerson: sortRoomUser(roomsPerson),
  203. })
  204. }
  205. user.isInRoom = true
  206. updateRoomUser(roomsPerson, user)
  207. }
  208. })
  209. socket.on(EVENT.changeOnlineStatus, data => {
  210. user.onlineStatus = data.status
  211. let roomPerson = this._roomPerson.get(roomId)
  212. let __roomPerson = updateRoomUser(roomPerson, user)
  213. let actionName = user.onlineStatus ? "inRoom" : "leaveRoom"
  214. socket.broadcast
  215. .to(roomId)
  216. .emit(EVENT.roomPersonChange, {
  217. roomsPerson: sortRoomUser(__roomPerson),
  218. actionName,
  219. user,
  220. })
  221. })
  222. socket.on(EVENT.stopCall, () => {
  223. socket.leave(roomId)
  224. //console.log(role, user, 'stopCall')
  225. if (role === LEADER) {
  226. socket.broadcast
  227. .to(roomId)
  228. .emit(EVENT.roomClose, { code: 3002, msg: CODEMAP[3002] })
  229. delete this._roomsConfig[roomId]
  230. }
  231. let roomsPerson = this._roomPerson.get(roomId) || []
  232. roomsPerson = removeRoomUser(roomsPerson, user)
  233. this._roomPerson.set(roomId, roomsPerson)
  234. socket.broadcast
  235. .to(roomId)
  236. .emit(EVENT.someOneLeaveRoom, { user, roomsPerson: sortRoomUser(roomsPerson) })
  237. user.isInRoom = false
  238. updateRoomUser(roomsPerson, user)
  239. })
  240. socket.on(EVENT.webSyncAction, data => {
  241. socket.broadcast.to(webRoomId).emit(EVENT.webSyncAction, data)
  242. })
  243. socket.on(EVENT.action, data => {
  244. socket.broadcast.to(roomId).emit(EVENT.action, data)
  245. })
  246. socket.on("disconnect", reason => {
  247. socket.leave(roomId)
  248. if (!isClient) {
  249. let roomsPerson = this._roomPerson.get(roomId) || []
  250. roomsPerson = removeRoomUser(roomsPerson, user)
  251. this._roomPerson.set(roomId, roomsPerson)
  252. // socket.broadcast.to(roomId).emit(EVENT.someOneLeaveRoom, { user, roomsPerson })
  253. socket.leave(webRoomId)
  254. socket.leave(roomId)
  255. }
  256. userCount--
  257. console.log("在线人数2:" + userCount)
  258. network.autoUpdate(userCount)
  259. })
  260. socket.on("reconnect", () => {
  261. socket.join(roomId)
  262. if (!isClient) {
  263. let roomsPerson = this._roomPerson.get(roomId) || []
  264. roomsPerson.push(user)
  265. this._roomPerson.set(roomId, roomsPerson)
  266. socket.join(webRoomId)
  267. socket.join(roomId)
  268. }
  269. console.log("重连")
  270. })
  271. socket.on("error", function (reason) {
  272. console.log("异常关闭", reason)
  273. })
  274. return this
  275. })
  276. }
  277. close() {
  278. this.server.disconnect(true)
  279. }
  280. }
  281. function removeRoomUser(roomsPerson, user) {
  282. for (let i = 0; i < roomsPerson.length; i++) {
  283. if (roomsPerson[i].userId === user.userId) {
  284. roomsPerson.splice(i, 1)
  285. }
  286. }
  287. return roomsPerson
  288. }
  289. // 过滤房间内相同的人
  290. function sortRoomUser(roomsPerson) {
  291. if (!roomsPerson) return []
  292. const res = new Map()
  293. return roomsPerson.filter(a => !res.has(a.userId) && res.set(a.userId, 1))
  294. }
  295. function updateRoomUser(roomsPerson, user) {
  296. if (!roomsPerson) return []
  297. roomsPerson.forEach(item => {
  298. if (item.userId === user.userId) {
  299. item = Object.assign(item, user)
  300. }
  301. })
  302. return roomsPerson
  303. }