You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
4.5 KiB
178 lines
4.5 KiB
// dtp-media-engine.js
|
|
// Copyright (C) 2022 DTP Technologies, LLC
|
|
// All Rights Reserved
|
|
|
|
'use strict';
|
|
|
|
require('dotenv').config();
|
|
|
|
const path = require('path');
|
|
|
|
const mongoose = require('mongoose');
|
|
const mediasoup = require('mediasoup');
|
|
|
|
const { SiteAsync, SiteCommon, SitePlatform, SiteLog } = require(path.join(__dirname, 'lib', 'site-lib'));
|
|
|
|
module.rootPath = __dirname;
|
|
module.pkg = require(path.join(module.rootPath, 'package.json'));
|
|
module.config = {
|
|
component: { name: 'dtpMediaEngine', slug: 'dtp-media-engine' },
|
|
root: module.rootPath,
|
|
site: require(path.join(module.rootPath, 'config', 'site')),
|
|
webRtcServer: [
|
|
{
|
|
protocol: 'udp',
|
|
ip: process.env.MEDIASOUP_WEBRTC_BIND_ADDR || '127.0.0.1',
|
|
port: process.env.MEDIASOUP_WEBRTC_BIND_PORT || 20000,
|
|
}
|
|
]
|
|
};
|
|
|
|
module.log = new SiteLog(module, module.config.component);
|
|
|
|
class MediaEngineWorker extends SiteCommon {
|
|
|
|
constructor ( ) {
|
|
super(module, { name: 'dtpMediaWorker', slug: 'dtp-media-worker' });
|
|
this._id = mongoose.Types.ObjectId();
|
|
}
|
|
|
|
async start ( ) {
|
|
await super.start();
|
|
|
|
try {
|
|
this.worker = await mediasoup.createWorker({
|
|
logLevel: 'warn',
|
|
dtlsCertificateFile: process.env.HTTPS_SSL_CRT,
|
|
dtlsPrivateKeyFile: process.env.HTTPS_SSL_KEY,
|
|
});
|
|
} catch (error) {
|
|
throw new Error(`failed to start mediasoup worker process: ${error.message}`);
|
|
}
|
|
|
|
try {
|
|
const BIND_PORT = 20000 + module.nextWorkerIdx++;
|
|
this.webRtcServer = await this.worker.createWebRtcServer({
|
|
listenInfos: [
|
|
{
|
|
protocol: 'udp',
|
|
ip: '127.0.0.1',
|
|
port: BIND_PORT,
|
|
},
|
|
{
|
|
protocol: 'tcp',
|
|
ip: '127.0.0.1',
|
|
port: BIND_PORT,
|
|
},
|
|
],
|
|
});
|
|
} catch (error) {
|
|
throw new Error(`failed to start mediasoup WebRTC Server: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
async stop ( ) {
|
|
if (this.webRtcServer && !this.webRtcServer.closed) {
|
|
this.log.info('closing mediasoup WebRTC server');
|
|
this.webRtcServer.close();
|
|
delete this.webRtcServer;
|
|
}
|
|
|
|
if (this.worker && !this.worker.closed) {
|
|
this.log.info('closing mediasoup worker process');
|
|
this.worker.close();
|
|
delete this.worker;
|
|
}
|
|
|
|
await super.stop();
|
|
}
|
|
}
|
|
|
|
module.onNewWorker = async (worker) => {
|
|
module.log.info('new worker created', { worker: worker.pid });
|
|
worker.observer.on('close', ( ) => {
|
|
module.log.info('worker shutting down', { worker: worker.pid });
|
|
});
|
|
|
|
worker.observer.on('newrouter', (router) => {
|
|
module.log.info('new router created', { worker: worker.pid, router: router.id });
|
|
router.observer.on('close', ( ) => {
|
|
module.log.info('router shutting down', { worker: worker.pid, router: router.id });
|
|
});
|
|
});
|
|
};
|
|
|
|
module.createWorker = async ( ) => {
|
|
const worker = new MediaEngineWorker();
|
|
module.workers.push(worker);
|
|
await worker.start();
|
|
};
|
|
|
|
module.shutdown = async ( ) => {
|
|
await SiteAsync.each(module.workers, async (worker) => {
|
|
try {
|
|
await worker.stop();
|
|
} catch (error) {
|
|
module.log.error('failed to stop worker', { error });
|
|
}
|
|
});
|
|
};
|
|
|
|
/*
|
|
* SERVER PROCESS INIT
|
|
*/
|
|
|
|
(async ( ) => {
|
|
|
|
process.on('unhandledRejection', (error, p) => {
|
|
module.log.error('Unhandled rejection', {
|
|
error: error,
|
|
promise: p,
|
|
stack: error.stack
|
|
});
|
|
});
|
|
|
|
process.on('warning', (error) => {
|
|
module.log.alert('warning', { error });
|
|
});
|
|
|
|
process.once('SIGINT', async ( ) => {
|
|
module.log.info('SIGINT received');
|
|
module.log.info('requesting shutdown...');
|
|
await module.shutdown();
|
|
const exitCode = await SitePlatform.shutdown();
|
|
process.nextTick(( ) => {
|
|
process.exit(exitCode);
|
|
});
|
|
});
|
|
|
|
process.once('SIGUSR2', async ( ) => {
|
|
await SitePlatform.shutdown();
|
|
process.kill(process.pid, 'SIGUSR2');
|
|
});
|
|
|
|
try {
|
|
await SitePlatform.startPlatform(module);
|
|
} catch (error) {
|
|
module.log.error(`failed to start DTP ${module.config.component.className} process`, { error });
|
|
return;
|
|
}
|
|
|
|
try {
|
|
module.log.info('registering mediasoup observer callbacks');
|
|
mediasoup.observer.on('newworker', module.onNewWorker);
|
|
|
|
module.log.info('creating mediasoup worker instance');
|
|
|
|
module.nextWorkerIdx = 0;
|
|
module.workers = [ ];
|
|
|
|
await module.createWorker();
|
|
|
|
module.log.info('DTP Media Engine online');
|
|
} catch (error) {
|
|
module.log.error('failed to start DTP Media Engine', { error });
|
|
process.exit(-1);
|
|
}
|
|
|
|
})();
|