Merge pull request #28 from torjusti/fix/server-refactor

[WIP] Use Express instead of custom server, passport for auth and refactor server files

Remember: config.example.js changed!
master
Stefan Otto 2018-07-23 13:51:35 +02:00 committed by GitHub
commit 7800474234
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 3003 additions and 3241 deletions

View File

@ -129,8 +129,6 @@ export default class RoomClient
login() login()
{ {
this._dispatch(stateActions.setLoginInProgress(true));
const url = `/login?roomId=${this._room.roomId}&peerName=${this._peerName}`; const url = `/login?roomId=${this._room.roomId}&peerName=${this._peerName}`;
this._loginWindow = window.open(url, 'loginWindow'); this._loginWindow = window.open(url, 'loginWindow');
@ -1079,32 +1077,20 @@ export default class RoomClient
logger.debug('got auth event from server', request.data); logger.debug('got auth event from server', request.data);
accept(); accept();
if (request.data.verified == true) this.changeDisplayName(request.data.name);
{
this.changeDisplayName(request.data.name);
this.changeProfilePicture(request.data.picture); this.changeProfilePicture(request.data.picture);
this._dispatch(stateActions.setPicture(request.data.picture)); this._dispatch(stateActions.setPicture(request.data.picture));
this._dispatch(requestActions.notify(
{
text : `Authenticated successfully: ${request.data}`
}
));
this._dispatch(requestActions.notify(
{
text : `Authenticated successfully: ${request.data}`
}
));
}
else
{
this._dispatch(requestActions.notify(
{
text : `Authentication failed: ${request.data}`
}
));
}
this.closeLoginWindow(); this.closeLoginWindow();
this._dispatch(stateActions.setLoginInProgress(false));
break; break;
} }
case 'raisehand-message': case 'raisehand-message':

View File

@ -129,9 +129,7 @@ class Sidebar extends Component
{me.loginEnabled ? {me.loginEnabled ?
<div <div
className={classnames('button', 'login', 'off', { className='button login off'
disabled : me.loginInProgress
})}
data-tip='Login' data-tip='Login'
data-type='dark' data-type='dark'
onClick={() => onLogin()} onClick={() => onLogin()}

View File

@ -15,7 +15,6 @@ const initialState =
webcamInProgress : false, webcamInProgress : false,
audioInProgress : false, audioInProgress : false,
screenShareInProgress : false, screenShareInProgress : false,
loginInProgress : false,
loginEnabled : false, loginEnabled : false,
audioOnly : false, audioOnly : false,
audioOnlyInProgress : false, audioOnlyInProgress : false,
@ -124,13 +123,6 @@ const me = (state = initialState, action) =>
return { ...state, screenShareInProgress: flag }; return { ...state, screenShareInProgress: flag };
} }
case 'SET_LOGIN_IN_PROGRESS':
{
const { flag } = action.payload;
return { ...state, loginInProgress: flag };
}
case 'SET_DISPLAY_NAME': case 'SET_DISPLAY_NAME':
{ {
let { displayName } = action.payload; let { displayName } = action.payload;

View File

@ -147,14 +147,6 @@ export const setMyRaiseHandState = (flag) =>
}; };
}; };
export const setLoginInProgress = (flag) =>
{
return {
type : 'SET_LOGIN_IN_PROGRESS',
payload : { flag }
};
};
export const toggleSettings = () => export const toggleSettings = () =>
{ {
return { return {

View File

@ -3,15 +3,9 @@ module.exports =
// oAuth2 conf // oAuth2 conf
oauth2 : oauth2 :
{ {
client_id : '', clientID : '',
client_secret : '', clientSecret : '',
providerID : '', callbackURL : 'https://mYDomainName:port/auth-callback'
redirect_uri : 'https://mYDomainName:port/auth-callback',
authorization_endpoint : '',
userinfo_endpoint : '',
token_endpoint : '',
scopes : { request : [ 'openid', 'userid','profile'] },
response_type : 'code'
}, },
// Listening hostname for `gulp live|open`. // Listening hostname for `gulp live|open`.
domain : 'localhost', domain : 'localhost',
@ -22,7 +16,7 @@ module.exports =
}, },
// Listening port for https server. // Listening port for https server.
listeningPort : 3443, listeningPort : 3443,
mediasoup : mediasoup :
{ {
// mediasoup Server settings. // mediasoup Server settings.
logLevel : 'warn', logLevel : 'warn',

View File

@ -15,20 +15,30 @@ const gulp = require('gulp');
const plumber = require('gulp-plumber'); const plumber = require('gulp-plumber');
const eslint = require('gulp-eslint'); const eslint = require('gulp-eslint');
const LINTING_FILES =
[
'gulpfile.js',
'server.js',
'config.example.js',
'lib/**/*.js'
];
gulp.task('lint', () => gulp.task('lint', () =>
{ {
const src =
[
'gulpfile.js',
'server.js',
'config.example.js',
'lib/**/*.js'
];
return gulp.src(src) return gulp.src(LINTING_FILES)
.pipe(plumber()) .pipe(plumber())
.pipe(eslint()) .pipe(eslint())
.pipe(eslint.format()); .pipe(eslint.format());
}); });
gulp.task('lint-fix', function()
{
return gulp.src(LINTING_FILES)
.pipe(plumber())
.pipe(eslint({ fix: true }))
.pipe(eslint.format())
.pipe(gulp.dest((file) => file.base));
});
gulp.task('default', gulp.series('lint')); gulp.task('default', gulp.series('lint'));

View File

@ -233,8 +233,8 @@ class Room extends EventEmitter
accept(); accept();
this._protooRoom.spread('profile-picture-changed', { this._protooRoom.spread('profile-picture-changed', {
peerName: protooPeer.id, peerName : protooPeer.id,
picture: request.data.picture picture : request.data.picture
}, [ protooPeer ]); }, [ protooPeer ]);
break; break;
@ -284,7 +284,7 @@ class Room extends EventEmitter
this._protooRoom.spread( this._protooRoom.spread(
'raisehand-message', 'raisehand-message',
{ {
peerName : protooPeer.id, peerName : protooPeer.id,
raiseHandState : raiseHandState raiseHandState : raiseHandState
}, },
[ protooPeer ]); [ protooPeer ]);

321
server/mediasoup.js 100644
View File

@ -0,0 +1,321 @@
const mediasoup = require('mediasoup');
const readline = require('readline');
const colors = require('colors/safe');
const repl = require('repl');
const homer = require('./lib/homer');
const config = require('./config');
// mediasoup server.
const mediaServer = mediasoup.Server(
{
numWorkers : 1,
logLevel : config.mediasoup.logLevel,
logTags : config.mediasoup.logTags,
rtcIPv4 : config.mediasoup.rtcIPv4,
rtcIPv6 : config.mediasoup.rtcIPv6,
rtcAnnouncedIPv4 : config.mediasoup.rtcAnnouncedIPv4,
rtcAnnouncedIPv6 : config.mediasoup.rtcAnnouncedIPv6,
rtcMinPort : config.mediasoup.rtcMinPort,
rtcMaxPort : config.mediasoup.rtcMaxPort
});
// Do Homer stuff.
if (process.env.MEDIASOUP_HOMER_OUTPUT)
homer(mediaServer);
global.SERVER = mediaServer;
mediaServer.on('newroom', (room) =>
{
global.ROOM = room;
room.on('newpeer', (peer) =>
{
global.PEER = peer;
if (peer.consumers.length > 0)
global.CONSUMER = peer.consumers[peer.consumers.length - 1];
peer.on('newtransport', (transport) =>
{
global.TRANSPORT = transport;
});
peer.on('newproducer', (producer) =>
{
global.PRODUCER = producer;
});
peer.on('newconsumer', (consumer) =>
{
global.CONSUMER = consumer;
});
});
});
// Listen for keyboard input.
let cmd;
let terminal;
openCommandConsole();
function openCommandConsole()
{
stdinLog('[opening Readline Command Console...]');
closeCommandConsole();
closeTerminal();
cmd = readline.createInterface(
{
input : process.stdin,
output : process.stdout
});
cmd.on('SIGINT', () =>
{
process.exit();
});
readStdin();
function readStdin()
{
cmd.question('cmd> ', (answer) =>
{
switch (answer)
{
case '':
{
readStdin();
break;
}
case 'h':
case 'help':
{
stdinLog('');
stdinLog('available commands:');
stdinLog('- h, help : show this message');
stdinLog('- sd, serverdump : execute server.dump()');
stdinLog('- rd, roomdump : execute room.dump() for the latest created mediasoup Room');
stdinLog('- pd, peerdump : execute peer.dump() for the latest created mediasoup Peer');
stdinLog('- td, transportdump : execute transport.dump() for the latest created mediasoup Transport');
stdinLog('- prd, producerdump : execute producer.dump() for the latest created mediasoup Producer');
stdinLog('- cd, consumerdump : execute consumer.dump() for the latest created mediasoup Consumer');
stdinLog('- t, terminal : open REPL Terminal');
stdinLog('');
readStdin();
break;
}
case 'sd':
case 'serverdump':
{
mediaServer.dump()
.then((data) =>
{
stdinLog(`server.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`mediaServer.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'rd':
case 'roomdump':
{
if (!global.ROOM)
{
readStdin();
break;
}
global.ROOM.dump()
.then((data) =>
{
stdinLog(`room.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`room.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'pd':
case 'peerdump':
{
if (!global.PEER)
{
readStdin();
break;
}
global.PEER.dump()
.then((data) =>
{
stdinLog(`peer.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`peer.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'td':
case 'transportdump':
{
if (!global.TRANSPORT)
{
readStdin();
break;
}
global.TRANSPORT.dump()
.then((data) =>
{
stdinLog(`transport.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`transport.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'prd':
case 'producerdump':
{
if (!global.PRODUCER)
{
readStdin();
break;
}
global.PRODUCER.dump()
.then((data) =>
{
stdinLog(`producer.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`producer.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'cd':
case 'consumerdump':
{
if (!global.CONSUMER)
{
readStdin();
break;
}
global.CONSUMER.dump()
.then((data) =>
{
stdinLog(`consumer.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`consumer.dump() failed: ${error}`);
readStdin();
});
break;
}
case 't':
case 'terminal':
{
openTerminal();
break;
}
default:
{
stdinError(`unknown command: ${answer}`);
stdinLog('press \'h\' or \'help\' to get the list of available commands');
readStdin();
}
}
});
}
}
function openTerminal()
{
stdinLog('[opening REPL Terminal...]');
closeCommandConsole();
closeTerminal();
terminal = repl.start(
{
prompt : 'terminal> ',
useColors : true,
useGlobal : true,
ignoreUndefined : false
});
terminal.on('exit', () => openCommandConsole());
}
function closeCommandConsole()
{
if (cmd)
{
cmd.close();
cmd = undefined;
}
}
function closeTerminal()
{
if (terminal)
{
terminal.removeAllListeners('exit');
terminal.close();
terminal = undefined;
}
}
function stdinLog(msg)
{
// eslint-disable-next-line no-console
console.log(colors.green(msg));
}
function stdinError(msg)
{
// eslint-disable-next-line no-console
console.error(colors.red.bold('ERROR: ') + colors.red(msg));
}
module.exports = mediaServer;

5209
server/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -7,10 +7,12 @@
"license": "MIT", "license": "MIT",
"main": "lib/index.js", "main": "lib/index.js",
"dependencies": { "dependencies": {
"base-64": "^0.1.0",
"colors": "^1.1.2", "colors": "^1.1.2",
"debug": "^3.1.0", "debug": "^3.1.0",
"express": "^4.16.2", "express": "^4.16.3",
"mediasoup": "^2.1.0", "mediasoup": "^2.1.0",
"passport-dataporten": "^1.3.0",
"protoo-server": "^2.0.7" "protoo-server": "^2.0.7"
}, },
"devDependencies": { "devDependencies": {

View File

@ -1,196 +0,0 @@
'use strict';
const EventEmitter = require( 'events' );
const eventEmitter = new EventEmitter();
const path = require('path');
const url = require('url');
const httpHelpers = require('./http-helpers');
const fs = require('fs');
const config = require('./config');
const utils = require('./util');
const querystring = require('querystring');
const https = require('https')
const Logger = require('./lib/Logger');
const logger = new Logger();
let authRequests = {}; // ongoing auth requests :
/*
{
state:
{
peerName:'peerName'
code:'oauth2 code',
roomId: 'romid',
}
}
*/
const actions = {
'GET': function(req, res) {
var parsedUrl = url.parse(req.url,true);
if ( parsedUrl.pathname === '/auth-callback' )
{
if ( typeof(authRequests[parsedUrl.query.state]) != 'undefined' )
{
console.log('got authorization code for access token: ',parsedUrl.query,authRequests[parsedUrl.query.state]);
const auth = "Basic " + new Buffer(config.oauth2.client_id + ":" + config.oauth2.client_secret).toString("base64");
const postUrl = url.parse(config.oauth2.token_endpoint);
let postData = querystring.stringify({
"grant_type":"authorization_code",
"code":parsedUrl.query.code,
"redirect_uri":config.oauth2.redirect_uri
});
let request = https.request( {
host : postUrl.hostname,
path : postUrl.pathname,
port : postUrl.port,
method : 'POST',
headers :
{
'Content-Type' : 'application/x-www-form-urlencoded',
'Authorization' : auth,
'Content-Length': Buffer.byteLength(postData)
}
}, function(res)
{
res.setEncoding("utf8");
let body = "";
res.on("data", data => {
body += data;
});
res.on("end", () => {
if ( res.statusCode == 200 )
{
console.log('We\'ve got an access token!', body);
body = JSON.parse(body);
authRequests[parsedUrl.query.state].access_token =
body.access_token;
const auth = "Bearer " + body.access_token;
const getUrl = url.parse(config.oauth2.userinfo_endpoint);
let request = https.request( {
host : getUrl.hostname,
path : getUrl.pathname,
port : getUrl.port,
method : 'GET',
headers :
{
'Authorization' : auth,
}
}, function(res)
{
res.setEncoding("utf8");
let body = '';
res.on("data", data => {
body += data;
});
res.on("end", () => {
// we don't need this any longer:
delete authRequests[parsedUrl.query.state].access_token;
body = JSON.parse(body);
console.log(body);
if ( res.statusCode == 200 )
{
authRequests[parsedUrl.query.state].verified = true;
if ( typeof(body.sub) != 'undefined')
{
authRequests[parsedUrl.query.state].sub = body.sub;
}
if ( typeof(body.name) != 'undefined')
{
authRequests[parsedUrl.query.state].name = body.name;
}
if ( typeof(body.picture) != 'undefined')
{
authRequests[parsedUrl.query.state].picture = body.picture;
}
} else {
{
authRequests[parsedUrl.query.state].verified = false;
}
}
eventEmitter.emit('auth',
authRequests[parsedUrl.query.state]);
delete authRequests[parsedUrl.query.state];
});
});
request.write(' ');
request.end;
}
else
{
console.log('access_token denied',body);
authRequests[parsedUrl.query.state].verified = false;
delete authRequests[parsedUrl.query.state].access_token;
eventEmitter.emit('auth',
authRequests[parsedUrl.query.state]);
}
});
});
request.write(postData);
request.end;
}
else
{
logger.warn('Got authorization_code for unseen state:', parsedUrl)
}
}
else if (parsedUrl.pathname === '/login') {
const state = utils.random(10);
httpHelpers.redirector(res, config.oauth2.authorization_endpoint
+ '?client_id=' + config.oauth2.client_id
+ '&redirect_uri=' + config.oauth2.redirect_uri
+ '&state=' + state
+ '&scopes=' + config.oauth2.scopes.request.join('+')
+ '&response_type=' + config.oauth2.response_type);
authRequests[state] =
{
'roomId' : parsedUrl.query.roomId,
'peerName' : parsedUrl.query.peerName
};
console.log('Started authorization process: ', parsedUrl.query);
}
else
{
console.log('requested url:', parsedUrl.pathname);
var resolvedBase = path.resolve('./public');
var safeSuffix = path.normalize(req.url).replace(/^(\.\.[\/\\])+/, '');
var fileLoc = path.join(resolvedBase, safeSuffix);
var headers = {};
var stream = fs.createReadStream(fileLoc);
// Handle non-existent file -> delivering index.html
stream.on('error', function(error) {
stream = fs.createReadStream(path.resolve('./public/index.html'));
res.statusCode = 200;
stream.pipe(res);
});
// File exists, stream it to user
if (parsedUrl.pathname.indexOf('svg') === parsedUrl.pathname.length -3) {headers = {'Content-Type': 'image/svg+xml'}};
res.writeHead(200, headers);
stream.pipe(res);
}
},
'POST': function(req, res) {
httpHelpers.prepareResponse(req, function(data) {
// Do something with the data that was just collected by the helper
// e.g., validate and save to db
// either redirect or respond
// should be based on result of the operation performed in response to the POST request intent
// e.g., if user wants to save, and save fails, throw error
httpHelpers.redirector(res, /* redirect path , optional status code - defaults to 302 */);
});
}
};
module.exports = eventEmitter;
module.exports.handleRequest = function(req, res) {
var action = actions[req.method];
action ? action(req, res) : httpHelpers.send404(res);
};

View File

@ -5,6 +5,16 @@
process.title = 'multiparty-meeting-server'; process.title = 'multiparty-meeting-server';
const config = require('./config'); const config = require('./config');
const fs = require('fs');
const https = require('https');
const express = require('express');
const url = require('url');
const protooServer = require('protoo-server');
const Logger = require('./lib/Logger');
const Room = require('./lib/Room');
const Dataporten = require('passport-dataporten');
const utils = require('./util');
const base64 = require('base-64');
/* eslint-disable no-console */ /* eslint-disable no-console */
console.log('- process.env.DEBUG:', process.env.DEBUG); console.log('- process.env.DEBUG:', process.env.DEBUG);
@ -12,100 +22,83 @@ console.log('- config.mediasoup.logLevel:', config.mediasoup.logLevel);
console.log('- config.mediasoup.logTags:', config.mediasoup.logTags); console.log('- config.mediasoup.logTags:', config.mediasoup.logTags);
/* eslint-enable no-console */ /* eslint-enable no-console */
const fs = require('fs'); // Start the mediasoup server.
const https = require('https'); const mediaServer = require('./mediasoup');
const router = require('./router');
const url = require('url');
const path = require('path');
const protooServer = require('protoo-server');
const mediasoup = require('mediasoup');
const readline = require('readline');
const colors = require('colors/safe');
const repl = require('repl');
const Logger = require('./lib/Logger');
const Room = require('./lib/Room');
const homer = require('./lib/homer');
const logger = new Logger(); const logger = new Logger();
// Map of Room instances indexed by roomId. // Map of Room instances indexed by roomId.
const rooms = new Map(); const rooms = new Map();
// mediasoup server. // TLS server configuration.
const mediaServer = mediasoup.Server(
{
numWorkers : 1,
logLevel : config.mediasoup.logLevel,
logTags : config.mediasoup.logTags,
rtcIPv4 : config.mediasoup.rtcIPv4,
rtcIPv6 : config.mediasoup.rtcIPv6,
rtcAnnouncedIPv4 : config.mediasoup.rtcAnnouncedIPv4,
rtcAnnouncedIPv6 : config.mediasoup.rtcAnnouncedIPv6,
rtcMinPort : config.mediasoup.rtcMinPort,
rtcMaxPort : config.mediasoup.rtcMaxPort
});
// Do Homer stuff.
if (process.env.MEDIASOUP_HOMER_OUTPUT)
homer(mediaServer);
global.SERVER = mediaServer;
mediaServer.on('newroom', (room) =>
{
global.ROOM = room;
room.on('newpeer', (peer) =>
{
global.PEER = peer;
if (peer.consumers.length > 0)
global.CONSUMER = peer.consumers[peer.consumers.length - 1];
peer.on('newtransport', (transport) =>
{
global.TRANSPORT = transport;
});
peer.on('newproducer', (producer) =>
{
global.PRODUCER = producer;
});
peer.on('newconsumer', (consumer) =>
{
global.CONSUMER = consumer;
});
});
});
// HTTPS server
const tls = const tls =
{ {
cert : fs.readFileSync(config.tls.cert), cert : fs.readFileSync(config.tls.cert),
key : fs.readFileSync(config.tls.key) key : fs.readFileSync(config.tls.key)
}; };
const httpsServer = https.createServer(tls, router.handleRequest); const app = express();
httpsServer.listen(config.listeningPort, '0.0.0.0', () =>
const dataporten = new Dataporten.Setup(config.oauth2);
app.use(dataporten.passport.initialize());
app.use(dataporten.passport.session());
app.get('/login', (req, res, next) =>
{ {
logger.info('Server running, port: ',config.listeningPort); dataporten.passport.authenticate('dataporten', {
state : base64.encode(JSON.stringify({
roomId : req.query.roomId,
peerName : req.query.peerName,
code : utils.random(10)
}))
})(req, res, next);
}); });
router.on('auth',function(event){ dataporten.setupLogout(app, '/logout');
console.log('router: Got an event: ',event)
if ( rooms.has(event.roomId) )
{
const room = rooms.get(event.roomId)._protooRoom;
if ( room.hasPeer(event.peerName) )
{
const peer = room.getPeer(event.peerName);
peer.send('auth', event)
}
}
})
// Protoo WebSocket server listens to same webserver so everythink is available app.get(
'/auth-callback',
dataporten.passport.authenticate('dataporten', { failureRedirect: '/login' }),
(req, res) =>
{
const state = JSON.parse(base64.decode(req.query.state));
if (rooms.has(state.roomId))
{
const room = rooms.get(state.roomId)._protooRoom;
if (room.hasPeer(state.peerName))
{
const peer = room.getPeer(state.peerName);
peer.send('auth', {
name : req.user.data.displayName,
picture : req.user.data.photos[0]
});
}
}
res.send('');
}
);
// Serve all files in the public folder as static files.
app.use(express.static('public'));
app.use((req, res) => res.sendFile(`${__dirname}/public/index.html`));
const httpsServer = https.createServer(tls, app);
httpsServer.listen(config.listeningPort, '0.0.0.0', () =>
{
logger.info('Server running on port: ', config.listeningPort);
});
// Protoo WebSocket server listens to same webserver so everything is available
// via same port // via same port
const webSocketServer = new protooServer.WebSocketServer(httpsServer, const webSocketServer = new protooServer.WebSocketServer(httpsServer,
{ {
@ -178,269 +171,4 @@ webSocketServer.on('connectionrequest', (info, accept, reject) =>
const transport = accept(); const transport = accept();
room.handleConnection(peerName, transport); room.handleConnection(peerName, transport);
}); });
// Listen for keyboard input.
let cmd;
let terminal;
openCommandConsole();
function openCommandConsole()
{
stdinLog('[opening Readline Command Console...]');
closeCommandConsole();
closeTerminal();
cmd = readline.createInterface(
{
input : process.stdin,
output : process.stdout
});
cmd.on('SIGINT', () =>
{
process.exit();
});
readStdin();
function readStdin()
{
cmd.question('cmd> ', (answer) =>
{
switch (answer)
{
case '':
{
readStdin();
break;
}
case 'h':
case 'help':
{
stdinLog('');
stdinLog('available commands:');
stdinLog('- h, help : show this message');
stdinLog('- sd, serverdump : execute server.dump()');
stdinLog('- rd, roomdump : execute room.dump() for the latest created mediasoup Room');
stdinLog('- pd, peerdump : execute peer.dump() for the latest created mediasoup Peer');
stdinLog('- td, transportdump : execute transport.dump() for the latest created mediasoup Transport');
stdinLog('- prd, producerdump : execute producer.dump() for the latest created mediasoup Producer');
stdinLog('- cd, consumerdump : execute consumer.dump() for the latest created mediasoup Consumer');
stdinLog('- t, terminal : open REPL Terminal');
stdinLog('');
readStdin();
break;
}
case 'sd':
case 'serverdump':
{
mediaServer.dump()
.then((data) =>
{
stdinLog(`server.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`mediaServer.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'rd':
case 'roomdump':
{
if (!global.ROOM)
{
readStdin();
break;
}
global.ROOM.dump()
.then((data) =>
{
stdinLog(`room.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`room.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'pd':
case 'peerdump':
{
if (!global.PEER)
{
readStdin();
break;
}
global.PEER.dump()
.then((data) =>
{
stdinLog(`peer.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`peer.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'td':
case 'transportdump':
{
if (!global.TRANSPORT)
{
readStdin();
break;
}
global.TRANSPORT.dump()
.then((data) =>
{
stdinLog(`transport.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`transport.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'prd':
case 'producerdump':
{
if (!global.PRODUCER)
{
readStdin();
break;
}
global.PRODUCER.dump()
.then((data) =>
{
stdinLog(`producer.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`producer.dump() failed: ${error}`);
readStdin();
});
break;
}
case 'cd':
case 'consumerdump':
{
if (!global.CONSUMER)
{
readStdin();
break;
}
global.CONSUMER.dump()
.then((data) =>
{
stdinLog(`consumer.dump() succeeded:\n${JSON.stringify(data, null, ' ')}`);
readStdin();
})
.catch((error) =>
{
stdinError(`consumer.dump() failed: ${error}`);
readStdin();
});
break;
}
case 't':
case 'terminal':
{
openTerminal();
break;
}
default:
{
stdinError(`unknown command: ${answer}`);
stdinLog('press \'h\' or \'help\' to get the list of available commands');
readStdin();
}
}
});
}
}
function openTerminal()
{
stdinLog('[opening REPL Terminal...]');
closeCommandConsole();
closeTerminal();
terminal = repl.start(
{
prompt : 'terminal> ',
useColors : true,
useGlobal : true,
ignoreUndefined : false
});
terminal.on('exit', () => openCommandConsole());
}
function closeCommandConsole()
{
if (cmd)
{
cmd.close();
cmd = undefined;
}
}
function closeTerminal()
{
if (terminal)
{
terminal.removeAllListeners('exit');
terminal.close();
terminal = undefined;
}
}
function stdinLog(msg)
{
// eslint-disable-next-line no-console
console.log(colors.green(msg));
}
function stdinError(msg)
{
// eslint-disable-next-line no-console
console.error(colors.red.bold('ERROR: ') + colors.red(msg));
}