livekit
This commit is contained in:
158
apps/mediasoup-server/socket-events/sfu.ts
Normal file
158
apps/mediasoup-server/socket-events/sfu.ts
Normal file
@@ -0,0 +1,158 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { Worker } from 'mediasoup/node/lib/types';
|
||||
import { UserDocument } from 'models/user';
|
||||
import { MediasoupChannel } from 'modules/mediasoup/Channel';
|
||||
import { createWorker } from 'modules/mediasoup/worker';
|
||||
import { Socket } from 'socket.io';
|
||||
import { User } from '@common/types/user';
|
||||
import { EventEmitter } from 'stream';
|
||||
import { setMemberNickname } from 'modules/bot/bot';
|
||||
import PilotController from './pilot';
|
||||
|
||||
interface SfuClient {
|
||||
socket: Socket;
|
||||
channelId: string;
|
||||
user: UserDocument;
|
||||
}
|
||||
|
||||
interface ISfuController {
|
||||
worker: Worker[];
|
||||
observer: EventEmitter;
|
||||
clients: Map<string, SfuClient>;
|
||||
channel: Map<string, MediasoupChannel>;
|
||||
init: () => void;
|
||||
handle: (channelId: string, socket: Socket, user: UserDocument) => void;
|
||||
disconnectUser: (userId: string) => void;
|
||||
}
|
||||
|
||||
const SfuController: ISfuController = {
|
||||
clients: new Map(),
|
||||
channel: new Map(),
|
||||
observer: new EventEmitter(),
|
||||
worker: [],
|
||||
disconnectUser: async (userId: string) => {
|
||||
SfuController.clients.forEach((client) => {
|
||||
if (client.user._id.toString() === userId) {
|
||||
client.socket.emit('error-message', { error: 'DISCONNECTED_BY_ADMIN' });
|
||||
|
||||
client.socket.disconnect();
|
||||
SfuController.clients.delete(client.socket.id);
|
||||
}
|
||||
});
|
||||
},
|
||||
init: async () => {
|
||||
// Setup Worker and Channel
|
||||
// Scalable!
|
||||
SfuController.worker = [
|
||||
await createWorker(),
|
||||
await createWorker(),
|
||||
await createWorker(),
|
||||
await createWorker(),
|
||||
await createWorker()
|
||||
];
|
||||
SfuController.channel.set('1', new MediasoupChannel(SfuController.worker[0])); // LST_VAR_RD_01
|
||||
SfuController.channel.set('2', new MediasoupChannel(SfuController.worker[1])); // LST_VAR_RD_02
|
||||
SfuController.channel.set('3', new MediasoupChannel(SfuController.worker[2])); // LST_VAR_RD_03
|
||||
SfuController.channel.set('4', new MediasoupChannel(SfuController.worker[3])); // LST_VAR_RD_04
|
||||
SfuController.channel.set('x', new MediasoupChannel(SfuController.worker[4])); // LST_VAR_RESERVE
|
||||
|
||||
// setup listends for new connections, producer-close event is handled by Channel
|
||||
SfuController.channel.forEach((channel, channelId) => {
|
||||
channel.on('producer-pausing-forced', ({ user }: { user: User.PublicUser }) => {
|
||||
SfuController.clients.forEach((client) => {
|
||||
if (client.channelId === channelId && client.user._id.toString() !== user.id) {
|
||||
client.socket.emit('producer-pausing-forced', { user });
|
||||
}
|
||||
});
|
||||
});
|
||||
channel.on('new-producer', ({ producerId, user }) => {
|
||||
SfuController.clients.forEach((client) => {
|
||||
if (client.channelId === channelId) {
|
||||
client.socket.emit('new-producer', { producerId, user });
|
||||
}
|
||||
});
|
||||
});
|
||||
channel.on('producer-closed', ({ producerId }) => {
|
||||
SfuController.clients.forEach((client) => {
|
||||
if (client.channelId === channelId) {
|
||||
client.socket.emit('producer-closed', { producerId });
|
||||
}
|
||||
});
|
||||
});
|
||||
channel.on('producer-paused', ({ producerId }) => {
|
||||
SfuController.clients.forEach((client) => {
|
||||
if (client.channelId === channelId) {
|
||||
client.socket.emit('producer-paused', { producerId });
|
||||
}
|
||||
});
|
||||
});
|
||||
channel.on('producer-resumed', ({ producerId }) => {
|
||||
SfuController.clients.forEach((client) => {
|
||||
if (client.channelId === channelId) {
|
||||
client.socket.emit('producer-resumed', { producerId });
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
handle: (channelId, socket, user) => {
|
||||
const channel = SfuController.channel.get(channelId);
|
||||
if (!channel) {
|
||||
socket.emit('error-message', { error: 'invalid channel id' });
|
||||
return;
|
||||
}
|
||||
|
||||
// check for double connections
|
||||
if (
|
||||
Array.from(SfuController.clients.values()).find(
|
||||
(client) => client.user._id.toString() === user._id.toString()
|
||||
) &&
|
||||
process.env.ALLOW_DOUBLE_CONNECTION === 'false'
|
||||
) {
|
||||
socket.emit('error-message', { error: 'DOUBLE_CONNECTION' });
|
||||
return;
|
||||
}
|
||||
|
||||
SfuController.clients.set(socket.id, { socket, channelId, user });
|
||||
|
||||
// Update Discord username for dispatcher
|
||||
SfuController.observer.emit('channel-changed', channelId, user);
|
||||
|
||||
const userInPilot = PilotController.clients.get(user._id.toString());
|
||||
|
||||
if (userInPilot) {
|
||||
userInPilot.voiceChannel = channelId;
|
||||
PilotController.clients.set(user._id.toString(), userInPilot);
|
||||
PilotController.observer.emit('stations-changed');
|
||||
}
|
||||
|
||||
channel.handleSocket(socket, user);
|
||||
|
||||
socket.on('get-producers', (getPcb) => {
|
||||
getPcb(channel.producers.map((p) => ({ producerId: p.id, user: p.appData.user, paused: p.paused })));
|
||||
});
|
||||
socket.on('disconnect', () => {
|
||||
socket.removeAllListeners();
|
||||
SfuController.clients.delete(socket.id);
|
||||
const userInPilotDisconnect = PilotController.clients.get(user._id.toString());
|
||||
|
||||
if (userInPilotDisconnect) {
|
||||
userInPilotDisconnect.voiceChannel = undefined;
|
||||
PilotController.clients.set(user._id.toString(), userInPilotDisconnect);
|
||||
PilotController.observer.emit('stations-changed');
|
||||
}
|
||||
});
|
||||
socket.on('set-should-transmit', (eventData: { shouldTransmit: boolean; source: string }) => {
|
||||
SfuController.clients.forEach((client) => {
|
||||
if (client.user._id.toString() === user._id.toString()) {
|
||||
client.socket.emit('set-should-transmit', eventData);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
SfuController.init();
|
||||
|
||||
export default SfuController;
|
||||
Reference in New Issue
Block a user