|
@@ -0,0 +1,250 @@
|
|
|
+var server = require("http").createServer();
|
|
|
+const TLSSigAPIv2 = require('tls-sig-api-v2')
|
|
|
+const appids = require('./../config/appid')
|
|
|
+const api = new TLSSigAPIv2.Api(appids.zhuisu.appid, appids.zhuisu.key)
|
|
|
+const PORT = 3032 // 监听端口号
|
|
|
+const LEADER = 'leader'
|
|
|
+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',
|
|
|
+ changeRoomEnableTalk: 'changeRoomEnableTalk'
|
|
|
+}
|
|
|
+
|
|
|
+const CODEMAP = {
|
|
|
+ 3001: '房间已被解散',
|
|
|
+ 3002: '房主主动解散'
|
|
|
+}
|
|
|
+
|
|
|
+module.exports = class WebSocketServer {
|
|
|
+ constructor() {
|
|
|
+ this._pageMap = new Map();
|
|
|
+ this._roomIDS = new Map();
|
|
|
+ this._roomPerson = new Map()
|
|
|
+ this._roomsConfig = {}
|
|
|
+ }
|
|
|
+
|
|
|
+ create() {
|
|
|
+ this.io = require("socket.io")(server, {
|
|
|
+ path: "/zhuisu-node",
|
|
|
+ serveClient: false,
|
|
|
+ // below are engine.IO options
|
|
|
+ pingInterval: 10000,
|
|
|
+ pingTimeout: 5000,
|
|
|
+ cookie: false,
|
|
|
+ });
|
|
|
+ server.listen(PORT, { 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 (isClient && role === LEADER && !this._roomsConfig[roomId]) {
|
|
|
+ this._roomsConfig[roomId] = {
|
|
|
+ userLimitNum,
|
|
|
+ enableTalk: user.enableTalk
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ socket.on(EVENT.changeRoomEnableTalk, data => {
|
|
|
+ this._roomsConfig[roomId].enableTalk = data
|
|
|
+ socket.broadcast.to(roomId).emit(EVENT.changeRoomEnableTalk, this._roomsConfig[roomId])
|
|
|
+ })
|
|
|
+
|
|
|
+ // 若有房间人数限制
|
|
|
+ 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)
|
|
|
+ } else {
|
|
|
+ // 通知客户端的房间配置
|
|
|
+ let roomsPerson = this._roomPerson.get(roomId) || []
|
|
|
+ socket.emit(EVENT.roomIn, { user, roomsPerson: sortRoomUser(roomsPerson), roomsConfig: this._roomsConfig[roomId]})
|
|
|
+ }
|
|
|
+ })
|
|
|
+ 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) || []
|
|
|
+ socket.emit(EVENT.roomIn, { user, roomsPerson: sortRoomUser(roomsPerson), roomsConfig: this._roomsConfig[roomId]})
|
|
|
+ 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]})
|
|
|
+ delete this._roomsConfig[roomId]
|
|
|
+ }
|
|
|
+ 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
|
|
|
+}
|