[+] 信令连接授权

This commit is contained in:
acgist
2023-02-04 21:11:30 +08:00
parent 3ec45914c7
commit 15bb1cd804
5 changed files with 102 additions and 76 deletions

View File

@@ -1,40 +0,0 @@
const Logger = require("./Logger");
const logger = new Logger();
/**
* 交互式控制台
*/
function openCommandConsole() {
logger.info("打开交互式控制台...");
process.stdin.resume();
process.stdin.setEncoding("utf-8");
process.stdin.on("data", (data) => {
process.stdin.pause();
const command = data.replace(/^\s\s*/, "").replace(/\s\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`");
}
}
logger.info("");
process.stdin.resume();
});
}
module.exports = async function () {
try {
openCommandConsole();
} catch (error) {
logger.error("执行命令异常:%o", error);
}
};

View File

@@ -4,7 +4,7 @@
const os = require("os"); const os = require("os");
module.exports = { module.exports = {
// 系统名称 // 服务名称
name: "taoyao-media-server", name: "taoyao-media-server",
// 交互式命令行 // 交互式命令行
command: true, command: true,
@@ -28,7 +28,7 @@ module.exports = {
numWorkers: Object.keys(os.cpus()).length, numWorkers: Object.keys(os.cpus()).length,
// Workerhttps://mediasoup.org/documentation/v3/mediasoup/api/#WorkerSettings // Workerhttps://mediasoup.org/documentation/v3/mediasoup/api/#WorkerSettings
workerSettings: { workerSettings: {
logLevel: "warn", logLevel: "info",
logTags: [ logTags: [
"bwe", "bwe",
"ice", "ice",

View File

@@ -19,22 +19,60 @@ class Logger {
} }
} }
/**
* debug
*
* @param {...any} args 参数
*
* @returns this
*/
debug(...args) { debug(...args) {
return this.log(console.debug, '37m', 'DEBUG', args); return this.log(console.debug, '37m', 'DEBUG', args);
} }
/**
* info
*
* @param {...any} args 参数
*
* @returns this
*/
info(...args) { info(...args) {
return this.log(console.info, '32m', 'INFO', args); return this.log(console.info, '32m', 'INFO', args);
} }
/**
* warn
*
* @param {...any} args 参数
*
* @returns this
*/
warn(...args) { warn(...args) {
return this.log(console.warn, '33m', 'WARN', args); return this.log(console.warn, '33m', 'WARN', args);
} }
/**
* error
*
* @param {...any} args 参数
*
* @returns this
*/
error(...args) { error(...args) {
return this.log(console.error, '31m', 'ERROR', args); return this.log(console.error, '31m', 'ERROR', args);
} }
/**
* 日志
*
* @param {*} out 输出位置
* @param {*} color 颜色
* @param {*} level 级别
* @param {*} args 参数
*
* @returns this
*/
log(out, color, level, args) { log(out, color, level, args) {
if(!args || this.level.indexOf(level) < this.levelIndex) { if(!args || this.level.indexOf(level) < this.levelIndex) {
return this; return this;
@@ -44,6 +82,7 @@ class Logger {
} else if(args.length === 1 && args[0].length > 0) { } else if(args.length === 1 && args[0].length > 0) {
out(`\x1B[${color}${this.name} ${moment().format('yyyy-MM-DD HH:mm:ss')} : [${level.padEnd(5, ' ')}] : ${args[0]}\x1B[0m`); out(`\x1B[${color}${this.name} ${moment().format('yyyy-MM-DD HH:mm:ss')} : [${level.padEnd(5, ' ')}] : ${args[0]}\x1B[0m`);
} else { } else {
// 其他情况直接输出换行
out(""); out("");
} }
return this; return this;

View File

@@ -5,11 +5,10 @@
const fs = require("fs"); const fs = require("fs");
const ws = require("ws"); const ws = require("ws");
const https = require("https"); const https = require("https");
// const mediasoup = require("mediasoup"); const mediasoup = require("mediasoup");
const config = require("./Config"); const config = require("./Config");
const Logger = require("./Logger"); const Logger = require("./Logger");
const Signal = require("./Signal"); const Signal = require("./Signal");
const command = require("./Command");
// HTTPS server // HTTPS server
let httpsServer; let httpsServer;
@@ -19,9 +18,9 @@ let webSocketServer;
const logger = new Logger(); const logger = new Logger();
// 信令 // 信令
const signal = new Signal(); const signal = new Signal();
// 信令终端 // 无效信令终端列表
const client = []; const client = [];
// Mediasoup Worker // Mediasoup Worker列表
const mediasoupWorker = []; const mediasoupWorker = [];
process.title = config.name; process.title = config.name;
@@ -31,7 +30,7 @@ process.title = config.name;
*/ */
async function buildMediasoupWorker() { async function buildMediasoupWorker() {
const { numWorkers } = config.mediasoup; const { numWorkers } = config.mediasoup;
logger.info("启动Mediasoup服务(%d Worker...", numWorkers); logger.info("启动Mediasoup Worker%d...", numWorkers);
for (let i = 0; i < numWorkers; i++) { for (let i = 0; i < numWorkers; i++) {
// 新建Worker // 新建Worker
const worker = await mediasoup.createWorker({ const worker = await mediasoup.createWorker({
@@ -40,7 +39,7 @@ async function buildMediasoupWorker() {
rtcMinPort: Number(config.mediasoup.workerSettings.rtcMinPort), rtcMinPort: Number(config.mediasoup.workerSettings.rtcMinPort),
rtcMaxPort: Number(config.mediasoup.workerSettings.rtcMaxPort), rtcMaxPort: Number(config.mediasoup.workerSettings.rtcMaxPort),
}); });
// 监听停止服务事件 // 监听Worker事件
worker.on("died", () => { worker.on("died", () => {
logger.error( logger.error(
"Mediasoup Worker停止服务两秒之后自动退出... [PID%d]", "Mediasoup Worker停止服务两秒之后自动退出... [PID%d]",
@@ -48,18 +47,17 @@ async function buildMediasoupWorker() {
); );
setTimeout(() => process.exit(1), 2000); setTimeout(() => process.exit(1), 2000);
}); });
// 加入队列 // 加入Worker队列
mediasoupWorker.push(worker); mediasoupWorker.push(worker);
// 配置WebRTC服务 // 配置WebRTC服务
if (process.env.MEDIASOUP_USE_WEBRTC_SERVER !== "false") { if (process.env.MEDIASOUP_USE_WEBRTC_SERVER !== "false") {
// 每个Worker端口不能相同 // 配置Worker端口
const portIncrement = mediasoupWorker.length - 1; const portIncrement = mediasoupWorker.length - 1;
const webRtcServerOptions = JSON.parse( const webRtcServerOptions = JSON.parse(JSON.stringify(config.mediasoup.webRtcServerOptions));
JSON.stringify(config.mediasoup.webRtcServerOptions)
);
for (const listenInfo of webRtcServerOptions.listenInfos) { for (const listenInfo of webRtcServerOptions.listenInfos) {
listenInfo.port += portIncrement; listenInfo.port += portIncrement;
} }
// 配置WebRTC服务
const webRtcServer = await worker.createWebRtcServer(webRtcServerOptions); const webRtcServer = await worker.createWebRtcServer(webRtcServerOptions);
worker.appData.webRtcServer = webRtcServer; worker.appData.webRtcServer = webRtcServer;
} }
@@ -87,21 +85,17 @@ async function buildSignalServer() {
logger.info("配置WebSocket服务..."); logger.info("配置WebSocket服务...");
webSocketServer = new ws.Server({ server: httpsServer }); webSocketServer = new ws.Server({ server: httpsServer });
webSocketServer.on("connection", (session) => { webSocketServer.on("connection", (session) => {
logger.info("打开信令通道: %s", session._socket.remoteAddress);
session.datetime = new Date().getTime(); session.datetime = new Date().getTime();
session.authorize = false; session.authorize = false;
client.push(session); client.push(session);
logger.info("信令通道连接: %s", session._socket.remoteAddress);
session.on("open", (message) => {
logger.info("打开信令通道: %s", message);
});
session.on("close", (code) => { session.on("close", (code) => {
logger.info("关闭信令通道: %o", code); logger.info("关闭信令通道: %o", code);
}); });
session.on("error", (e) => { session.on("error", (error) => {
logger.error("信令通道异常: %o", e); logger.error("信令通道异常: %o", error);
}); });
session.on("message", (message) => { session.on("message", (message) => {
logger.debug("收到信令消息: %s", message);
onmessage(message, session); onmessage(message, session);
}); });
}); });
@@ -115,14 +109,46 @@ async function buildSignalServer() {
); );
} }
/**
* 交互式控制台
*/
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;
}
}
logger.info("");
process.stdin.resume();
});
}
/** /**
* 定时清理无效信令终端 * 定时清理无效信令终端
*/ */
async function cleanClientInterval() { async function buildClientInterval() {
setInterval(() => { setInterval(() => {
const datetime = new Date().getTime(); const datetime = new Date().getTime();
const oldLength = client.length; const oldLength = client.length;
for (var i = 0; i < client.length; i++) { for (let i = 0; i < client.length; i++) {
const session = client[i]; const session = client[i];
// 超过五秒自动关闭 // 超过五秒自动关闭
if (datetime - session.datetime >= 5000) { if (datetime - session.datetime >= 5000) {
@@ -145,6 +171,7 @@ async function cleanClientInterval() {
async function onmessage(message, session) { async function onmessage(message, session) {
try { try {
const data = JSON.parse(message); const data = JSON.parse(message);
// 授权验证
if (!session.authorize) { if (!session.authorize) {
if ( if (
data.username === config.https.username && data.username === config.https.username &&
@@ -156,7 +183,7 @@ async function onmessage(message, session) {
logger.warn("授权失败:%s", session._socket.remoteAddress); logger.warn("授权失败:%s", session._socket.remoteAddress);
session.close(); session.close();
} }
for (var i = 0; i < client.length; i++) { for (let i = 0; i < client.length; i++) {
if (client[i] === session) { if (client[i] === session) {
client.splice(i, 1); client.splice(i, 1);
break; break;
@@ -164,6 +191,8 @@ async function onmessage(message, session) {
} }
return; return;
} }
// 处理信令
logger.debug("处理信令消息: %s", message);
signal.on(data, session); signal.on(data, session);
} catch (error) { } catch (error) {
logger.error( logger.error(
@@ -176,20 +205,18 @@ async function onmessage(message, session) {
} }
} }
/**
* 启动方法
*/
async function main() { async function main() {
logger.debug("DEBUG").info("INFO").warn("WARN").error("ERROR"); logger.debug("DEBUG").info("INFO").warn("WARN").error("ERROR");
logger.info("开始启动:%s", config.name); logger.info("开始启动:%s", config.name);
// 启动Mediasoup服务 await buildMediasoupWorker();
// await buildMediasoupWorker();
// 启动服务
await buildSignalServer(); await buildSignalServer();
await buildCommandConsole();
await buildClientInterval();
logger.info("启动完成:%s", config.name); logger.info("启动完成:%s", config.name);
// 交互式命令行
if (config.command) {
await command();
}
// 定时清理无效信令终端
cleanClientInterval();
} }
// 启动
main(); main();

View File

@@ -6,12 +6,12 @@
class Signal { class Signal {
// Mediasoup Worker列表 // Mediasoup Worker列表
mediasoupWorkers = []; mediasoupWorker = [];
// Mediasoup Worker下个索引 // Mediasoup Worker索引
nextMediasoupWorkerIndex = 0; nextMediasoupWorkerIndex = 0;
constructor(mediasoupWorkers) { constructor(mediasoupWorker) {
this.mediasoupWorkers = mediasoupWorkers; this.mediasoupWorker = mediasoupWorker;
} }
/** /**