From b64d923daa2aad9ca848dd8ff57c016a51ac5383 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Fri, 23 Apr 2021 11:44:58 -0300 Subject: identifier per socket connection --- socket.js | 61 ++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 17 deletions(-) (limited to 'socket.js') diff --git a/socket.js b/socket.js index 5f3ded0..42f4057 100644 --- a/socket.js +++ b/socket.js @@ -22,6 +22,8 @@ import EventEmitter from 'node:events' import * as net from 'node:net' +import shortid from 'shortid' + import { restoreBackend, restoreNewItem, @@ -102,6 +104,8 @@ function validateCommand(command) { switch (command.code) { case 'initialize-backend': return typeof command.backend === 'object' + case 'set-socket-id': + return typeof command.socketId === 'string' } // No break here; servers can send commands which typically come from // clients too. @@ -235,7 +239,7 @@ export function makeSocketServer() { // that's the responsibility of the caller (use server.listen()). const server = new net.Server() - const sockets = [] + const socketMap = Object.create(null) server.canonicalBackend = null @@ -244,13 +248,15 @@ export function makeSocketServer() { const donePlaying = {} server.on('connection', socket => { - sockets.push(socket) + const socketId = shortid.generate() + + socketMap[socketId] = socket let nickname = DEFAULT_NICKNAME socket.on('close', () => { - if (sockets.includes(socket)) { - sockets.splice(sockets.indexOf(socket), 1) + if (socketId in socketMap) { + delete socketMap[socketId] } }) @@ -265,6 +271,7 @@ export function makeSocketServer() { } command.sender = 'client' + command.senderSocketId = socketId command.senderNickname = nickname if (!validateCommand(command)) { @@ -278,25 +285,26 @@ export function makeSocketServer() { switch (command.status) { case 'done-playing': { const doneSockets = donePlaying[command.queuePlayer] - if (doneSockets && !doneSockets.includes(socket)) { - doneSockets.push(socket) - if (doneSockets.length === sockets.length) { + if (doneSockets && !doneSockets.includes(socketId)) { + doneSockets.push(socketId) + if (doneSockets.length === Object.keys(socketMap).length) { // determine next track - for (const socket of sockets) { + for (const socket of Object.values(socketMap)) { // play next track } delete donePlaying[command.queuePlayer] } } + break } case 'ready-to-resume': { const readySockets = readyToResume[command.queuePlayer] - if (readySockets && !readySockets.includes(socket)) { - readySockets.push(socket) - if (readySockets.length === sockets.length) { + if (readySockets && !readySockets.includes(socketId)) { + readySockets.push(socketId) + if (readySockets.length === Object.keys(socketMap).length) { const QP = server.canonicalBackend.queuePlayers.find(QP => QP.id === command.queuePlayer) silenceEvents(QP, ['set-pause'], () => QP.setPause(false)) - for (const socket of sockets) { + for (const socket of Object.values(socketMap)) { socket.write(serializeCommandToData({ sender: 'server', code: 'set-pause', @@ -351,7 +359,7 @@ export function makeSocketServer() { // Relay the command to client sockets besides the sender. - const otherSockets = sockets.filter(s => s !== socket) + const otherSockets = Object.values(socketMap).filter(s => s !== socket) for (const socket of otherSockets) { socket.write(serializeCommandToData(command) + '\n') @@ -366,6 +374,12 @@ export function makeSocketServer() { } } + socket.write(serializeCommandToData({ + sender: 'server', + code: 'set-socket-id', + socketId + }) + '\n') + socket.write(serializeCommandToData({ sender: 'server', code: 'initialize-backend', @@ -384,6 +398,7 @@ export function makeSocketClient() { const client = new EventEmitter() client.socket = new net.Socket() client.nickname = DEFAULT_NICKNAME + client.socketId = null // Will be received from server. client.sendCommand = function(command) { const data = serializeCommandToData(command) @@ -424,11 +439,16 @@ export function attachBackendToSocketClient(backend, client, { // All actual logic for instances of the mtui backend interacting with each // other through commands lives here. - const partyGrouplike = {name: 'My Party Sources', isPartySources: true, items: []} + const partyGrouplike = { + name: `Party Sources - ${client.nickname}`, + isPartySources: true, + items: [] + } + + const partyGrouplikeMap = Object.create(null) backend.setAlwaysStartPaused(true) backend.setWaitWhenDonePlaying(true) - backend.loadPartyGrouplike(partyGrouplike) function logCommand(command) { const nickToMessage = nickname => `\x1b[32;1m${nickname}\x1b[0m` @@ -489,6 +509,8 @@ export function attachBackendToSocketClient(backend, client, { actionmsg = `updated their nickname (from ${nickToMessage(command.oldNickname)})` senderNickname = command.nickname break + case 'set-socket-id': + return case 'set-pause': if (command.paused) { actionmsg = 'paused the player' @@ -540,6 +562,11 @@ export function attachBackendToSocketClient(backend, client, { switch (command.sender) { case 'server': switch (command.code) { + case 'set-socket-id': + client.socketId = command.socketId + partyGrouplikeMap[command.socketId] = partyGrouplike + backend.loadPartyGrouplike(client.socketId, partyGrouplike) + return case 'initialize-backend': await restoreBackend(backend, command.backend) // TODO: does this need to be called here? @@ -551,7 +578,7 @@ export function attachBackendToSocketClient(backend, client, { }) return } - // Again, no pause. Client commands can come from the server. + // Again, no break. Client commands can come from the server. case 'client': { let QP = ( command.queuePlayer && @@ -767,7 +794,7 @@ export function attachBackendToSocketClient(backend, client, { if (partyGrouplike.items.every(x => x[originalSymbol] !== origItem)) { partyGrouplike.items.push(newItem) - backend.partyGrouplikeUpdated(partyGrouplike) + backend.partyGrouplikeUpdated(client.socketId, partyGrouplike) } }) } -- cgit 1.3.0-6-gf8a5