multiparty-meeting/server/lib/Lobby.js

221 lines
3.9 KiB
JavaScript

const EventEmitter = require('events').EventEmitter;
const Logger = require('./Logger');
const logger = new Logger('Lobby');
class Lobby extends EventEmitter
{
constructor()
{
logger.info('constructor()');
super();
// Closed flag.
this._closed = false;
this._peers = {};
}
close()
{
logger.info('close()');
this._closed = true;
// Close the peers.
for (const peer in this._peers)
{
if (!this._peers[peer].closed)
this._peers[peer].close();
}
this._peers = null;
}
checkEmpty()
{
logger.info('checkEmpty()');
return Object.keys(this._peers).length === 0;
}
peerList()
{
logger.info('peerList()');
return Object.values(this._peers).map((peer) =>
({
peerId : peer.id,
displayName : peer.displayName,
picture : peer.picture
}));
}
hasPeer(peerId)
{
return this._peers[peerId] != null;
}
promoteAllPeers()
{
logger.info('promoteAllPeers()');
for (const peer in this._peers)
{
if (peer.socket)
this.promotePeer(peer.id);
}
}
promotePeer(peerId)
{
logger.info('promotePeer() [peer:"%s"]', peerId);
const peer = this._peers[peerId];
if (peer)
{
peer.socket.removeListener('request', peer.socketRequestHandler);
peer.removeListener('gotRole', peer.gotRoleHandler);
peer.removeListener('displayNameChanged', peer.displayNameChangeHandler);
peer.removeListener('pictureChanged', peer.pictureChangeHandler);
peer.removeListener('close', peer.closeHandler);
peer.socketRequestHandler = null;
peer.gotRoleHandler = null;
peer.displayNameChangeHandler = null;
peer.pictureChangeHandler = null;
peer.closeHandler = null;
this.emit('promotePeer', peer);
delete this._peers[peerId];
}
}
parkPeer(peer)
{
logger.info('parkPeer() [peer:"%s"]', peer.id);
if (this._closed)
return;
peer.socketRequestHandler = (request, cb) =>
{
logger.debug(
'Peer "request" event [method:"%s", peer:"%s"]',
request.method, peer.id);
if (this._closed)
return;
this._handleSocketRequest(peer, request, cb)
.catch((error) =>
{
logger.error('request failed [error:"%o"]', error);
cb(error);
});
};
peer.gotRoleHandler = () =>
{
logger.info('parkPeer() | rolesChange [peer:"%s"]', peer.id);
this.emit('peerRolesChanged', peer);
};
peer.displayNameChangeHandler = () =>
{
logger.info('parkPeer() | displayNameChange [peer:"%s"]', peer.id);
this.emit('changeDisplayName', peer);
};
peer.pictureChangeHandler = () =>
{
logger.info('parkPeer() | pictureChange [peer:"%s"]', peer.id);
this.emit('changePicture', peer);
};
peer.closeHandler = () =>
{
logger.debug('Peer "close" event [peer:"%s"]', peer.id);
if (this._closed)
return;
this.emit('peerClosed', peer);
delete this._peers[peer.id];
if (this.checkEmpty())
this.emit('lobbyEmpty');
};
this._notification(peer.socket, 'enteredLobby');
this._peers[peer.id] = peer;
peer.on('gotRole', peer.gotRoleHandler);
peer.on('displayNameChanged', peer.displayNameChangeHandler);
peer.on('pictureChanged', peer.pictureChangeHandler);
peer.socket.on('request', peer.socketRequestHandler);
peer.on('close', peer.closeHandler);
}
async _handleSocketRequest(peer, request, cb)
{
logger.debug(
'_handleSocketRequest [peer:"%s"], [request:"%s"]',
peer.id,
request.method
);
if (this._closed)
return;
switch (request.method)
{
case 'changeDisplayName':
{
const { displayName } = request.data;
peer.displayName = displayName;
cb();
break;
}
case 'changePicture':
{
const { picture } = request.data;
peer.picture = picture;
cb();
break;
}
}
}
_notification(socket, method, data = {}, broadcast = false)
{
if (broadcast)
{
socket.broadcast.to(this._roomId).emit(
'notification', { method, data }
);
}
else
{
socket.emit('notification', { method, data });
}
}
}
module.exports = Lobby;