[+] 信令连接授权
This commit is contained in:
@@ -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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -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,
|
||||||
// Worker:https://mediasoup.org/documentation/v3/mediasoup/api/#WorkerSettings
|
// Worker:https://mediasoup.org/documentation/v3/mediasoup/api/#WorkerSettings
|
||||||
workerSettings: {
|
workerSettings: {
|
||||||
logLevel: "warn",
|
logLevel: "info",
|
||||||
logTags: [
|
logTags: [
|
||||||
"bwe",
|
"bwe",
|
||||||
"ice",
|
"ice",
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user