socketv2.js 7.4 KB

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