zhuisu.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. var server = require("http").createServer();
  2. const TLSSigAPIv2 = require('tls-sig-api-v2')
  3. const appids = require('./../config/appid')
  4. const api = new TLSSigAPIv2.Api(appids.zhuisu.appid, appids.zhuisu.key)
  5. const PORT = 3032 // 监听端口号
  6. const LEADER = 'leader'
  7. function getSig (userId) {
  8. return api.genSig(userId, 86400)
  9. }
  10. const EVENT = {
  11. someOneInRoom: 'someOneInRoom',
  12. someOneLeaveRoom: 'someOneLeaveRoom',
  13. startCall: 'startCall',
  14. stopCall: 'stopCall',
  15. webSyncAction: 'webSyncAction',
  16. clientSyncAction: 'clientSyncAction',
  17. action: 'action',
  18. roomClose: 'roomClose',
  19. roomIn: 'roomIn',
  20. changeVoiceStatus: 'changeVoiceStatus',
  21. changeOnlineStatus: 'changeOnlineStatus',
  22. roomPersonChange: 'roomPersonChange',
  23. changeRoomEnableTalk: 'changeRoomEnableTalk'
  24. }
  25. const CODEMAP = {
  26. 3001: '房间已被解散',
  27. 3002: '房主主动解散'
  28. }
  29. module.exports = class WebSocketServer {
  30. constructor() {
  31. this._pageMap = new Map();
  32. this._roomIDS = new Map();
  33. this._roomPerson = new Map()
  34. this._roomsConfig = {}
  35. }
  36. create() {
  37. this.io = require("socket.io")(server, {
  38. path: "/zhuisu-node",
  39. serveClient: false,
  40. // below are engine.IO options
  41. pingInterval: 10000,
  42. pingTimeout: 5000,
  43. cookie: false,
  44. });
  45. server.listen(PORT, { origins: "*" });
  46. this.io.on("connection", (socket) => {
  47. let user = socket.handshake.query
  48. const { roomId, userId, sceneNum, isClient, role, userLimitNum } = user
  49. const webRoomId = `${roomId}_${sceneNum}_web`
  50. const clientRoom = `${userId}${roomId}`
  51. console.log(user, 'connection')
  52. // 加入客户端与H5单独的通讯房间
  53. socket.join(clientRoom, () => {
  54. })
  55. socket.on(EVENT.clientSyncAction, (data) => {
  56. console.log(data,'clientSyncAction')
  57. socket.broadcast.to(clientRoom).emit(EVENT.clientSyncAction, data)
  58. })
  59. socket.on(EVENT.changeVoiceStatus, data => {
  60. let _roomPerson = this._roomPerson.get(roomId) || []
  61. user.voiceStatus = data.status
  62. _roomPerson.forEach(item => {
  63. if (item.userId === user.userId) {
  64. item.voiceStatus = user.voiceStatus
  65. }
  66. })
  67. this._roomPerson.set(roomId, _roomPerson)
  68. socket.broadcast.to(roomId).emit(EVENT.changeVoiceStatus, {roomsPerson: sortRoomUser(_roomPerson)})
  69. })
  70. // 房主,保存房间配置
  71. if (isClient && role === LEADER && !this._roomsConfig[roomId]) {
  72. this._roomsConfig[roomId] = {
  73. userLimitNum,
  74. enableTalk: user.enableTalk
  75. }
  76. }
  77. socket.on(EVENT.changeRoomEnableTalk, data => {
  78. this._roomsConfig[roomId].enableTalk = data
  79. socket.broadcast.to(roomId).emit(EVENT.changeRoomEnableTalk, this._roomsConfig[roomId])
  80. })
  81. // 若有房间人数限制
  82. if (userLimitNum && this._roomPerson.get(roomId) && sortRoomUser(this._roomPerson.get(roomId)).length >= userLimitNum) {
  83. // console.log(this._roomPerson.get(roomId), 'full')
  84. // console.log(this._roomPerson.get(roomId).length, userLimitNum, 'full')
  85. setTimeout(() => {
  86. socket.emit('roomInFail', { type: 'full', msg: '房间人数已满' })
  87. }, 1000)
  88. return this
  89. }
  90. // 若已结束、房间已关闭
  91. if ( user.role !== LEADER&& ((this._roomPerson.get(roomId) && !this._roomPerson.get(roomId).find(item => item.role === LEADER)) || (!this._roomPerson.get(roomId)))) {
  92. console.log('roomClose')
  93. setTimeout(() => {
  94. socket.emit(EVENT.roomClose, { code: 3001, msg: CODEMAP[3001]})
  95. }, 1000)
  96. return this
  97. }
  98. // 加入所有连接数的通讯房间
  99. socket.join(roomId, () => {
  100. // 只有h5才能加入H5端的房间
  101. if (!isClient) {
  102. let roomsPerson = this._roomPerson.get(roomId) || []
  103. if (userId) {
  104. user.sig = getSig(userId)
  105. }
  106. let clientPerson = this._roomPerson.get(clientRoom) || []
  107. clientPerson.forEach(item => {
  108. if (item.userId === user.userId && item.avatar) {
  109. user.avatar = item.avatar
  110. user.voiceStatus = item.voiceStatus
  111. user.onlineStatus = item.onlineStatus
  112. user.nickname = decodeURIComponent(item.nickname)
  113. }
  114. })
  115. roomsPerson.push(user)
  116. this._roomPerson.set(roomId, roomsPerson)
  117. } else {
  118. // 通知客户端的房间配置
  119. let roomsPerson = this._roomPerson.get(roomId) || []
  120. socket.emit(EVENT.roomIn, { user, roomsPerson: sortRoomUser(roomsPerson), roomsConfig: this._roomsConfig[roomId]})
  121. }
  122. })
  123. let clientPerson = this._roomPerson.get(clientRoom) || []
  124. if (isClient) {
  125. clientPerson.push(user)
  126. this._roomPerson.set(clientRoom, clientPerson)
  127. }
  128. if (!isClient) {
  129. socket.join(webRoomId, () => {
  130. // let roomsPerson = this._roomPerson.get(roomId) || []
  131. // socket.broadcast.to(roomId).emit(EVENT.someOneInRoom, { user, roomsPerson: sortRoomUser(roomsPerson) })
  132. })
  133. }
  134. socket.on(EVENT.startCall, () => {
  135. if (!isClient) {
  136. let roomsPerson = this._roomPerson.get(roomId) || []
  137. socket.emit(EVENT.roomIn, { user, roomsPerson: sortRoomUser(roomsPerson), roomsConfig: this._roomsConfig[roomId]})
  138. socket.broadcast.to(roomId).emit(EVENT.someOneInRoom, { user, roomsPerson: sortRoomUser(roomsPerson) })
  139. }
  140. })
  141. socket.on(EVENT.changeOnlineStatus, data => {
  142. user.onlineStatus = data.status
  143. let roomPerson = this._roomPerson.get(roomId)
  144. let __roomPerson = updateRoomUser(roomPerson, user)
  145. let actionName = user.onlineStatus ? 'inRoom' : 'leaveRoom'
  146. console.log({roomsPerson: sortRoomUser(__roomPerson), actionName})
  147. socket.broadcast.to(roomId).emit(EVENT.roomPersonChange, {roomsPerson: sortRoomUser(__roomPerson), actionName, user})
  148. })
  149. socket.on(EVENT.stopCall, () => {
  150. socket.leave(roomId)
  151. if (role === LEADER) {
  152. socket.broadcast.to(roomId).emit(EVENT.roomClose, { code: 3002, msg: CODEMAP[3002]})
  153. delete this._roomsConfig[roomId]
  154. }
  155. let roomsPerson = this._roomPerson.get(roomId) || []
  156. roomsPerson = removeRoomUser(roomsPerson, user)
  157. this._roomPerson.set(roomId, roomsPerson)
  158. socket.broadcast.to(roomId).emit(EVENT.someOneLeaveRoom, { user, roomsPerson: sortRoomUser(roomsPerson) })
  159. })
  160. socket.on(EVENT.webSyncAction, (data) => {
  161. socket.broadcast.to(webRoomId).emit(EVENT.webSyncAction, data)
  162. })
  163. socket.on(EVENT.action, (data) => {
  164. console.log(data,'action')
  165. socket.broadcast.to(roomId).emit(EVENT.action, data)
  166. })
  167. socket.on("disconnect", (reason) => {
  168. socket.leave(roomId)
  169. if (!isClient) {
  170. // if (role === LEADER && reason !== 'ping timeout') {
  171. // socket.broadcast.to(roomId).emit(EVENT.roomClose)
  172. // }
  173. let roomsPerson = this._roomPerson.get(roomId) || []
  174. roomsPerson = removeRoomUser(roomsPerson, user)
  175. this._roomPerson.set(roomId, roomsPerson)
  176. // socket.broadcast.to(roomId).emit(EVENT.someOneLeaveRoom, { user, roomsPerson })
  177. socket.leave(webRoomId)
  178. socket.leave(roomId)
  179. }
  180. })
  181. socket.on('reconnect', () => {
  182. socket.join(roomId)
  183. if (!isClient) {
  184. let roomsPerson = this._roomPerson.get(roomId) || []
  185. roomsPerson.push(user)
  186. this._roomPerson.set(roomId, roomsPerson)
  187. socket.join(webRoomId)
  188. socket.join(roomId)
  189. }
  190. })
  191. socket.on("error", function (reason) {
  192. console.log("异常关闭", reason)
  193. })
  194. return this;
  195. })
  196. }
  197. close() {
  198. this.server.disconnect(true);
  199. }
  200. };
  201. function removeRoomUser (roomsPerson, user) {
  202. for (let i = 0; i < roomsPerson.length; i++) {
  203. if (roomsPerson[i].userId === user.userId) {
  204. roomsPerson.splice(i, 1)
  205. }
  206. }
  207. return roomsPerson
  208. }
  209. function sortRoomUser (roomsPerson) {
  210. if (!roomsPerson) return []
  211. const res = new Map()
  212. return roomsPerson.filter((a) => !res.has(a.userId) && res.set(a.userId, 1))
  213. }
  214. function updateRoomUser (roomsPerson, user) {
  215. if (!roomsPerson) return []
  216. roomsPerson.forEach(item => {
  217. console.log(item.userId === user.userId)
  218. if (item.userId === user.userId) {
  219. item = Object.assign(item, user)
  220. }
  221. })
  222. return roomsPerson
  223. }