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
commit
7800474234
|
|
@ -129,8 +129,6 @@ export default class RoomClient
|
|||
|
||||
login()
|
||||
{
|
||||
this._dispatch(stateActions.setLoginInProgress(true));
|
||||
|
||||
const url = `/login?roomId=${this._room.roomId}&peerName=${this._peerName}`;
|
||||
|
||||
this._loginWindow = window.open(url, 'loginWindow');
|
||||
|
|
@ -1079,8 +1077,6 @@ export default class RoomClient
|
|||
logger.debug('got auth event from server', request.data);
|
||||
accept();
|
||||
|
||||
if (request.data.verified == true)
|
||||
{
|
||||
this.changeDisplayName(request.data.name);
|
||||
|
||||
this.changeProfilePicture(request.data.picture);
|
||||
|
|
@ -1091,20 +1087,10 @@ export default class RoomClient
|
|||
text : `Authenticated successfully: ${request.data}`
|
||||
}
|
||||
));
|
||||
}
|
||||
else
|
||||
{
|
||||
this._dispatch(requestActions.notify(
|
||||
{
|
||||
text : `Authentication failed: ${request.data}`
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
this.closeLoginWindow();
|
||||
|
||||
this._dispatch(stateActions.setLoginInProgress(false));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case 'raisehand-message':
|
||||
|
|
|
|||
|
|
@ -129,9 +129,7 @@ class Sidebar extends Component
|
|||
|
||||
{me.loginEnabled ?
|
||||
<div
|
||||
className={classnames('button', 'login', 'off', {
|
||||
disabled : me.loginInProgress
|
||||
})}
|
||||
className='button login off'
|
||||
data-tip='Login'
|
||||
data-type='dark'
|
||||
onClick={() => onLogin()}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ const initialState =
|
|||
webcamInProgress : false,
|
||||
audioInProgress : false,
|
||||
screenShareInProgress : false,
|
||||
loginInProgress : false,
|
||||
loginEnabled : false,
|
||||
audioOnly : false,
|
||||
audioOnlyInProgress : false,
|
||||
|
|
@ -124,13 +123,6 @@ const me = (state = initialState, action) =>
|
|||
return { ...state, screenShareInProgress: flag };
|
||||
}
|
||||
|
||||
case 'SET_LOGIN_IN_PROGRESS':
|
||||
{
|
||||
const { flag } = action.payload;
|
||||
|
||||
return { ...state, loginInProgress: flag };
|
||||
}
|
||||
|
||||
case 'SET_DISPLAY_NAME':
|
||||
{
|
||||
let { displayName } = action.payload;
|
||||
|
|
|
|||
|
|
@ -147,14 +147,6 @@ export const setMyRaiseHandState = (flag) =>
|
|||
};
|
||||
};
|
||||
|
||||
export const setLoginInProgress = (flag) =>
|
||||
{
|
||||
return {
|
||||
type : 'SET_LOGIN_IN_PROGRESS',
|
||||
payload : { flag }
|
||||
};
|
||||
};
|
||||
|
||||
export const toggleSettings = () =>
|
||||
{
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,15 +3,9 @@ module.exports =
|
|||
// oAuth2 conf
|
||||
oauth2 :
|
||||
{
|
||||
client_id : '',
|
||||
client_secret : '',
|
||||
providerID : '',
|
||||
redirect_uri : 'https://mYDomainName:port/auth-callback',
|
||||
authorization_endpoint : '',
|
||||
userinfo_endpoint : '',
|
||||
token_endpoint : '',
|
||||
scopes : { request : [ 'openid', 'userid','profile'] },
|
||||
response_type : 'code'
|
||||
clientID : '',
|
||||
clientSecret : '',
|
||||
callbackURL : 'https://mYDomainName:port/auth-callback'
|
||||
},
|
||||
// Listening hostname for `gulp live|open`.
|
||||
domain : 'localhost',
|
||||
|
|
|
|||
|
|
@ -15,20 +15,30 @@ const gulp = require('gulp');
|
|||
const plumber = require('gulp-plumber');
|
||||
const eslint = require('gulp-eslint');
|
||||
|
||||
gulp.task('lint', () =>
|
||||
{
|
||||
const src =
|
||||
[
|
||||
const LINTING_FILES =
|
||||
[
|
||||
'gulpfile.js',
|
||||
'server.js',
|
||||
'config.example.js',
|
||||
'lib/**/*.js'
|
||||
];
|
||||
];
|
||||
|
||||
return gulp.src(src)
|
||||
gulp.task('lint', () =>
|
||||
{
|
||||
|
||||
return gulp.src(LINTING_FILES)
|
||||
.pipe(plumber())
|
||||
.pipe(eslint())
|
||||
.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'));
|
||||
|
|
|
|||
|
|
@ -233,8 +233,8 @@ class Room extends EventEmitter
|
|||
accept();
|
||||
|
||||
this._protooRoom.spread('profile-picture-changed', {
|
||||
peerName: protooPeer.id,
|
||||
picture: request.data.picture
|
||||
peerName : protooPeer.id,
|
||||
picture : request.data.picture
|
||||
}, [ protooPeer ]);
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,10 +7,12 @@
|
|||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
"dependencies": {
|
||||
"base-64": "^0.1.0",
|
||||
"colors": "^1.1.2",
|
||||
"debug": "^3.1.0",
|
||||
"express": "^4.16.2",
|
||||
"express": "^4.16.3",
|
||||
"mediasoup": "^2.1.0",
|
||||
"passport-dataporten": "^1.3.0",
|
||||
"protoo-server": "^2.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
196
server/router.js
196
server/router.js
|
|
@ -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);
|
||||
};
|
||||
414
server/server.js
414
server/server.js
|
|
@ -5,6 +5,16 @@
|
|||
process.title = 'multiparty-meeting-server';
|
||||
|
||||
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 */
|
||||
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);
|
||||
/* eslint-enable no-console */
|
||||
|
||||
const fs = require('fs');
|
||||
const https = require('https');
|
||||
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');
|
||||
// Start the mediasoup server.
|
||||
const mediaServer = require('./mediasoup');
|
||||
|
||||
const logger = new Logger();
|
||||
|
||||
// Map of Room instances indexed by roomId.
|
||||
const rooms = new Map();
|
||||
|
||||
// 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;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// HTTPS server
|
||||
// TLS server configuration.
|
||||
const tls =
|
||||
{
|
||||
cert : fs.readFileSync(config.tls.cert),
|
||||
key : fs.readFileSync(config.tls.key)
|
||||
};
|
||||
|
||||
const httpsServer = https.createServer(tls, router.handleRequest);
|
||||
httpsServer.listen(config.listeningPort, '0.0.0.0', () =>
|
||||
const app = express();
|
||||
|
||||
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){
|
||||
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)
|
||||
}
|
||||
}
|
||||
})
|
||||
dataporten.setupLogout(app, '/logout');
|
||||
|
||||
// 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
|
||||
const webSocketServer = new protooServer.WebSocketServer(httpsServer,
|
||||
{
|
||||
|
|
@ -179,268 +172,3 @@ webSocketServer.on('connectionrequest', (info, accept, reject) =>
|
|||
|
||||
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));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue