123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- const network = require('./network')
- var server = require("http").createServer()
- const TLSSigAPIv2 = require("tls-sig-api-v2")
- const appids = require("./../config/appid")
- const api = new TLSSigAPIv2.Api(appids.fashilong.appid, appids.fashilong.key)
- const PORT = 3031
- const LEADER = "leader"
- let userCount = 0
- function getSig(userId) {
- return api.genSig(userId, 86400)
- }
- const EVENT = {
- someOneInRoom: "someOneInRoom", // 有人进入房间
- someOneLeaveRoom: "someOneLeaveRoom", // 有人离开房间
- startCall: "startCall", // 开始通话
- stopCall: "stopCall", // 结束通话
- webSyncAction: "webSyncAction", // 通知h5的事件
- clientSyncAction: "clientSyncAction", // 通知非H5的事件
- 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: "/fsl-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, roomType } = user
- const webRoomId = `${roomId}_${sceneNum}_web`
- const clientRoom = `${userId}${roomId}`
- // 加入客户端与H5单独的通讯房间
- socket.join(clientRoom, () => {
- console.log(user, user.nickname && decodeURIComponent(user.nickname))
- })
- 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]) {
- //console.log('in', user)
- this._roomsConfig[roomId] = {
- userLimitNum,
- enableTalk: user.enableTalk,
- }
- }
- // 1v1保存房主
- if (roomType === "1v1" && !this._roomsConfig[roomId]) {
- //console.log(roomType, roomId, user)
- this._roomsConfig[roomId] = {
- leaderId: userId,
- }
- }
- if (roomType === "1v1" && sortRoomUser(this._roomPerson.get(roomId)).length > 2) {
- setTimeout(() => {
- socket.emit("roomInFail", {
- type: "full",
- msg: "房间人数已满",
- })
- }, 1000)
- return this
- }
- 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
- ) {
- setTimeout(() => {
- socket.emit("roomInFail", { type: "full", msg: "房间人数已满" })
- }, 1000)
- return this
- }
- let is1v1 = false
- if (this._roomsConfig[roomId]) {
- is1v1 = this._roomsConfig[roomId].leaderId === userId
- }
- //console.log(this._roomsConfig[roomId], userId, !is1v1, user.role !== LEADER, (this._roomPerson.get(roomId) && !this._roomPerson.get(roomId).find(item => item.role === LEADER)))
- // 非房主进来房间,判断房间是否存在,以及房间内是否有房主,若无则通知房间已关闭
- if (
- !is1v1 &&
- user.role !== LEADER &&
- ((this._roomPerson.get(roomId) &&
- !this._roomPerson.get(roomId).find(item => item.role === LEADER)) ||
- !this._roomPerson.get(roomId))
- ) {
- 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],
- })
- }
- userCount++
- console.log("在线人数1:" + userCount)
- network.autoUpdate(userCount)
- })
- 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) })
- let roomPerson = this._roomPerson.get(roomId)
- let __roomPerson = updateRoomUser(roomPerson, user)
- let actionName = ""
- socket.broadcast
- .to(roomId)
- .emit(EVENT.roomPersonChange, {
- roomsPerson: sortRoomUser(__roomPerson),
- actionName,
- user,
- })
- })
- }
- // 开始通话
- socket.on(EVENT.startCall, () => {
- if (!isClient) {
- let roomsPerson = this._roomPerson.get(roomId) || []
- // 返回h5房间内的信息
- socket.emit(EVENT.roomIn, {
- user,
- roomsPerson: sortRoomUser(roomsPerson),
- roomsConfig: this._roomsConfig[roomId],
- })
- // 判断是否某些情况断线重连
- if (!user.isInRoom) {
- socket.broadcast
- .to(roomId)
- .emit(EVENT.someOneInRoom, {
- user,
- roomsPerson: sortRoomUser(roomsPerson),
- })
- }
- user.isInRoom = true
- updateRoomUser(roomsPerson, user)
- }
- })
- 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"
- socket.broadcast
- .to(roomId)
- .emit(EVENT.roomPersonChange, {
- roomsPerson: sortRoomUser(__roomPerson),
- actionName,
- user,
- })
- })
- socket.on(EVENT.stopCall, () => {
- socket.leave(roomId)
- //console.log(role, user, 'stopCall')
- 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) })
- user.isInRoom = false
- updateRoomUser(roomsPerson, user)
- })
- socket.on(EVENT.webSyncAction, data => {
- socket.broadcast.to(webRoomId).emit(EVENT.webSyncAction, data)
- })
- socket.on(EVENT.action, data => {
- socket.broadcast.to(roomId).emit(EVENT.action, data)
- })
- socket.on("disconnect", reason => {
- socket.leave(roomId)
- if (!isClient) {
- 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)
- }
- userCount--
- console.log("在线人数2:" + userCount)
- network.autoUpdate(userCount)
- })
- 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)
- }
- console.log("重连")
- })
- 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 => {
- if (item.userId === user.userId) {
- item = Object.assign(item, user)
- }
- })
- return roomsPerson
- }
|