var server = require("http").createServer(); const TLSSigAPIv2 = require('tls-sig-api-v2') const appids = require('./../config/appid') const api = new TLSSigAPIv2.Api(appids.shop.appid, appids.shop.key) function getSig (userId) { return api.genSig(userId, 86400) } const EVENT = { someOneInRoom: 'someOneInRoom', someOneLeaveRoom: 'someOneLeaveRoom', startCall: 'startCall', stopCall: 'stopCall', webSyncAction: 'webSyncAction', clientSyncAction: 'clientSyncAction', action: 'action', roomClose: 'roomClose', roomIn: 'roomIn', changeVoiceStatus: 'changeVoiceStatus', changeOnlineStatus: 'changeOnlineStatus', roomPersonChange: 'roomPersonChange' } const CODEMAP = { 3001: '房间已被解散', 3002: '房主主动解散' } module.exports = class WebSocketServer { constructor() { this._pageMap = new Map(); this._roomIDS = new Map(); this._roomPerson = new Map() } create() { this.io = require("socket.io")(server, { path: "/vr-node", serveClient: false, // below are engine.IO options pingInterval: 10000, pingTimeout: 5000, cookie: false, }); server.listen(3030, { origins: "*" }); this.io.on("connection", (socket) => { let user = socket.handshake.query const { roomId, userId, sceneNum, isClient, role, userLimitNum } = user const webRoomId = `${roomId}_${sceneNum}_web` const clientRoom = `${userId}${roomId}` console.log(user, 'connection') // 加入客户端与H5单独的通讯房间 socket.join(clientRoom, () => { }) socket.on(EVENT.clientSyncAction, (data) => { console.log(data,'clientSyncAction') socket.broadcast.to(clientRoom).emit(EVENT.clientSyncAction, data) }) socket.on(EVENT.changeVoiceStatus, data => { let _roomPerson = this._roomPerson.get(roomId) || [] user.voiceStatus = data.status _roomPerson.forEach(item => { if (item.userId === user.userId) { item.voiceStatus = user.voiceStatus } }) this._roomPerson.set(roomId, _roomPerson) socket.broadcast.to(roomId).emit(EVENT.changeVoiceStatus, {roomsPerson: sortRoomUser(_roomPerson)}) }) // 若有房间人数限制 if (userLimitNum && this._roomPerson.get(roomId) && sortRoomUser(this._roomPerson.get(roomId)).length >= userLimitNum) { // console.log(this._roomPerson.get(roomId), 'full') // console.log(this._roomPerson.get(roomId).length, userLimitNum, 'full') setTimeout(() => { socket.emit('roomInFail', { type: 'full', msg: '房间人数已满' }) }, 1000) return this } // 若已结束、房间已关闭 if ( user.role !== 'leader'&& ((this._roomPerson.get(roomId) && !this._roomPerson.get(roomId).find(item => item.role === 'leader')) || (!this._roomPerson.get(roomId)))) { console.log('roomClose') setTimeout(() => { socket.emit(EVENT.roomClose, { code: 3001, msg: CODEMAP[3001]}) }, 1000) return this } // 加入所有连接数的通讯房间 socket.join(roomId, () => { // 只有h5才能加入H5端的房间 if (!isClient) { let roomsPerson = this._roomPerson.get(roomId) || [] if (userId) { user.sig = getSig(userId) } let clientPerson = this._roomPerson.get(clientRoom) || [] clientPerson.forEach(item => { if (item.userId === user.userId && item.avatar) { user.avatar = item.avatar user.voiceStatus = item.voiceStatus user.onlineStatus = item.onlineStatus user.nickname = decodeURIComponent(item.nickname) } }) roomsPerson.push(user) this._roomPerson.set(roomId, roomsPerson) } }) let clientPerson = this._roomPerson.get(clientRoom) || [] if (isClient) { clientPerson.push(user) this._roomPerson.set(clientRoom, clientPerson) } if (!isClient) { socket.join(webRoomId, () => { // let roomsPerson = this._roomPerson.get(roomId) || [] // socket.broadcast.to(roomId).emit(EVENT.someOneInRoom, { user, roomsPerson: sortRoomUser(roomsPerson) }) }) } socket.on(EVENT.startCall, () => { if (!isClient) { let roomsPerson = this._roomPerson.get(roomId) || [] console.log('startCall', sortRoomUser(roomsPerson) ) socket.emit(EVENT.roomIn, { roomsPerson: sortRoomUser(roomsPerson) }) socket.broadcast.to(roomId).emit(EVENT.someOneInRoom, { user, roomsPerson: sortRoomUser(roomsPerson) }) } }) socket.on(EVENT.changeOnlineStatus, data => { user.onlineStatus = data.status let roomPerson = this._roomPerson.get(roomId) let __roomPerson = updateRoomUser(roomPerson, user) let actionName = user.onlineStatus ? 'inRoom' : 'leaveRoom' console.log({roomsPerson: sortRoomUser(__roomPerson), actionName}) socket.broadcast.to(roomId).emit(EVENT.roomPersonChange, {roomsPerson: sortRoomUser(__roomPerson), actionName, user}) }) socket.on(EVENT.stopCall, () => { socket.leave(roomId) if (role === 'leader') { socket.broadcast.to(roomId).emit(EVENT.roomClose, { code: 3002, msg: CODEMAP[3002]}) } let roomsPerson = this._roomPerson.get(roomId) || [] roomsPerson = removeRoomUser(roomsPerson, user) this._roomPerson.set(roomId, roomsPerson) socket.broadcast.to(roomId).emit(EVENT.someOneLeaveRoom, { user, roomsPerson: sortRoomUser(roomsPerson) }) }) socket.on(EVENT.webSyncAction, (data) => { socket.broadcast.to(webRoomId).emit(EVENT.webSyncAction, data) }) socket.on(EVENT.action, (data) => { console.log(data,'action') socket.broadcast.to(roomId).emit(EVENT.action, data) }) socket.on("disconnect", (reason) => { socket.leave(roomId) if (!isClient) { // if (role === 'leader' && reason !== 'ping timeout') { // socket.broadcast.to(roomId).emit(EVENT.roomClose) // } let roomsPerson = this._roomPerson.get(roomId) || [] roomsPerson = removeRoomUser(roomsPerson, user) this._roomPerson.set(roomId, roomsPerson) // socket.broadcast.to(roomId).emit(EVENT.someOneLeaveRoom, { user, roomsPerson }) socket.leave(webRoomId) socket.leave(roomId) } }) socket.on('reconnect', () => { socket.join(roomId) if (!isClient) { let roomsPerson = this._roomPerson.get(roomId) || [] roomsPerson.push(user) this._roomPerson.set(roomId, roomsPerson) socket.join(webRoomId) socket.join(roomId) } }) socket.on("error", function (reason) { console.log("异常关闭", reason) }) return this; }) } close() { this.server.disconnect(true); } }; function removeRoomUser (roomsPerson, user) { for (let i = 0; i < roomsPerson.length; i++) { if (roomsPerson[i].userId === user.userId) { roomsPerson.splice(i, 1) } } return roomsPerson } function sortRoomUser (roomsPerson) { if (!roomsPerson) return [] const res = new Map() return roomsPerson.filter((a) => !res.has(a.userId) && res.set(a.userId, 1)) } function updateRoomUser (roomsPerson, user) { if (!roomsPerson) return [] roomsPerson.forEach(item => { console.log(item.userId === user.userId) if (item.userId === user.userId) { item = Object.assign(item, user) } }) return roomsPerson }