[+] 合并事件监听还有协议

This commit is contained in:
acgist
2023-02-17 07:07:56 +08:00
parent 948b628937
commit 95f2221ebb
90 changed files with 1098 additions and 1265 deletions

View File

@@ -3,7 +3,7 @@
const fs = require("fs");
const ws = require("ws");
const https = require("https");
// const mediasoup = require("mediasoup");
const mediasoup = require("mediasoup");
const config = require("./Config");
const Logger = require("./Logger");
const Signal = require("./Signal");
@@ -31,8 +31,8 @@ const signal = new Signal(mediasoupWorkers);
*/
async function buildMediasoupWorkers() {
const { workerSize } = config.mediasoup;
logger.info("启动Mediasoup Worker", workerSize);
for (let i = 0; i < workerSize; i++) {
logger.info("启动Worker", workerSize);
for (let index = 0; index < workerSize; index++) {
// 新建Worker
const worker = await mediasoup.createWorker({
logLevel: config.mediasoup.workerSettings.logLevel,
@@ -42,30 +42,23 @@ async function buildMediasoupWorkers() {
});
// 监听Worker事件
worker.on("died", () => {
logger.warn("Mediasoup Worker停止服务", worker.pid);
logger.warn("Worker停止服务", worker.pid);
setTimeout(() => process.exit(1), 2000);
});
worker.observer.on("close", () => {
logger.warn("Worker关闭服务", worker.pid);
});
// 配置WebRTC服务
const webRtcServerOptions = JSON.parse(
JSON.stringify(config.mediasoup.webRtcServerOptions)
);
for (const listenInfo of webRtcServerOptions.listenInfos) {
listenInfo.port = listenInfo.port + mediasoupWorkers.length - 1;
}
const webRtcServer = await worker.createWebRtcServer(webRtcServerOptions);
worker.appData.webRtcServer = webRtcServer;
// 加入Worker队列
mediasoupWorkers.push(worker);
// 配置WebRTC服务
if (process.env.MEDIASOUP_USE_WEBRTC_SERVER !== "false") {
// 配置Worker端口
const portIncrement = mediasoupWorkers.length - 1;
const webRtcServerOptions = JSON.parse(
JSON.stringify(config.mediasoup.webRtcServerOptions)
);
for (const listenInfo of webRtcServerOptions.listenInfos) {
listenInfo.port += portIncrement;
}
// 配置WebRTC服务
const webRtcServer = await worker.createWebRtcServer(webRtcServerOptions);
worker.appData.webRtcServer = webRtcServer;
}
// 定时记录使用日志
setInterval(async () => {
const usage = await worker.getResourceUsage();
logger.info("Mediasoup Worker使用情况", worker.pid, usage);
}, 120 * 1000);
}
}
@@ -75,14 +68,14 @@ async function buildMediasoupWorkers() {
async function buildSignalServer() {
const tls = {
cert: fs.readFileSync(config.https.tls.cert),
key: fs.readFileSync(config.https.tls.key),
key: fs.readFileSync(config.https.tls.key),
};
// 配置HTTPS
// 配置HTTPS Server
httpsServer = https.createServer(tls, (request, response) => {
response.writeHead(200);
response.end(fs.readFileSync(config.welcome));
});
// 配置WebSocket
// 配置WebSocket Server
webSocketServer = new ws.Server({ server: httpsServer });
webSocketServer.on("connection", (session) => {
logger.info("打开信令通道", session._socket.remoteAddress);
@@ -115,76 +108,56 @@ async function buildSignalServer() {
}
/**
* 定时清理无效信令终端
* 定时任务
*/
async function buildClientInterval() {
async function buildInterval() {
// 定时清理过期无效终端
setInterval(() => {
const datetime = Date.now();
let failSize = 0;
let silentSize = 0;
let successSize = 0;
for (let i = 0; i < clients.length; i++) {
const session = clients[i];
// 超过五秒自动关闭
if (datetime - session.datetime >= 5000) {
clients.splice(i, 1);
if(session.authorize) {
successSize++;
} else {
failSize++;
session.close();
}
i--;
const datetime = Date.now();
for (let index = 0; index < clients.length; index++) {
const session = clients[index];
if (session.authorize) {
clients.splice(index, 1);
successSize++;
index--;
} else if (datetime - session.datetime >= 5000) {
clients.splice(index, 1);
session.close();
failSize++;
index--;
} else {
silentSize++;
}
}
logger.info("定时清理无效信令终端", failSize, successSize, clients.length);
logger.info("定时清理无效信令终端(无效|静默|成功|现存)", failSize, silentSize, successSize, clients.length);
}, 60 * 1000);
}
/**
* 交互式控制台
*/
async function buildCommandConsole() {
if (!config.command) {
return;
}
process.stdin.setEncoding("UTF-8");
process.stdin.resume();
process.stdin.on("data", (data) => {
process.stdin.pause();
const command = data.replace(/^\s*/, "").replace(/\s*$/, "");
logger.info("");
switch (command) {
case "h":
case "help": {
logger.info("- h, help 帮助信息");
logger.info("- os 系统信息");
break;
}
case "":
default: {
logger.warn(`未知命令:'${command}'`);
logger.info("查询命令:'h' | 'help'");
break;
}
// 定时打印Worker使用情况
setInterval(async () => {
for (const worker of mediasoupWorkers) {
const usage = await worker.getResourceUsage();
logger.info("Worker使用情况", worker.pid, usage);
}
logger.info("");
process.stdin.resume();
});
}, 120 * 1000);
}
/**
* 启动方法
*/
async function main() {
logger.debug("闹市早行客");
logger.info("江边独钓翁");
logger.warn("山中与谁同");
logger.error("绿竹细雨风");
logger
.info("桃之夭夭,灼灼其华。")
.info("之子于归,宜其室家。")
.debug("DEBUG")
.info("INFO")
.warn("WARN")
.error("ERROR");
logger.info("开始启动", config.name);
// await buildMediasoupWorkers();
await buildMediasoupWorkers();
await buildSignalServer();
await buildClientInterval();
await buildCommandConsole();
await buildInterval();
logger.info("启动完成", config.name);
}

View File

@@ -31,7 +31,7 @@ const config = require("./Config");
* @returns 信令消息
*/
buildMessage: function (signal, roomId, body = {}, id) {
let message = {
const message = {
header: {
v: config.version,
id: id || this.buildId(),
@@ -46,6 +46,24 @@ const config = require("./Config");
},
};
/**
* Peer
*/
class Peer {
peerId;
device;
displayName;
rtpCapabilities;
sctpCapabilities;
transports = new Map();
producers = new Map();
consumers = new Map();
dataProducers = new Map();
dataConsumers = new Map();
}
/**
* 房间
*/
@@ -53,6 +71,8 @@ class Room {
// 是否关闭
close = false;
// 终端
peers = new Map();
// 房间ID
roomId = null;
// 网络节流
@@ -104,7 +124,7 @@ class Room {
}
});
// 静音
this.audioLevelObserver.on('silence', () => {
this.audioLevelObserver.on("silence", () => {
this.signal.push(protocol.buildMessage(
"audio::active::speaker",
this.roomId,
@@ -116,11 +136,18 @@ class Room {
}
handleActiveSpeakerObserver() {
this.activeSpeakerObserver.on('dominantspeaker', (dominantSpeaker) => {
this.activeSpeakerObserver.on("dominantspeaker", (dominantSpeaker) => {
logger.debug("dominantspeaker", dominantSpeaker.producer.id);
});
}
close() {
this.close = true;
if(this.mediasoupRouter) {
this.mediasoupRouter.close();
}
}
}
/**
@@ -134,9 +161,9 @@ class Signal {
clients = [];
// 日志
logger = new Logger();
// Mediasoup Worker列表
// Worker列表
mediasoupWorkers = [];
// Mediasoup Worker索引
// Worker索引
nextMediasoupWorkerIndex = 0;
constructor(mediasoupWorkers) {
@@ -245,7 +272,7 @@ class Signal {
* @param {*} message 消息
* @param {*} body 消息主体
*
* @returns 路由
* @returns 房间
*/
async roomCreate(session, message, body) {
const roomId = body.roomId;
@@ -256,6 +283,12 @@ class Signal {
const mediasoupWorker = this.nextMediasoupWorker();
const { mediaCodecs } = config.mediasoup.routerOptions;
const mediasoupRouter = await mediasoupWorker.createRouter({ mediaCodecs });
mediasoupRouter.on("workerclose", () => {
// TODO通知房间关闭
});
mediasoupRouter.observer.on("close", () => {
// TODO通知房间关闭
});
// TODO下面两个监控改为配置启用
const audioLevelObserver = await mediasoupRouter.createAudioLevelObserver({
maxEntries: 1,