[mirotalksfu] - #87 auto-detect announcedIP if not set
هذا الالتزام موجود في:
@@ -46,6 +46,7 @@ const compression = require('compression');
|
|||||||
const https = require('httpolyglot');
|
const https = require('httpolyglot');
|
||||||
const mediasoup = require('mediasoup');
|
const mediasoup = require('mediasoup');
|
||||||
const mediasoupClient = require('mediasoup-client');
|
const mediasoupClient = require('mediasoup-client');
|
||||||
|
const http = require('http');
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const ngrok = require('ngrok');
|
const ngrok = require('ngrok');
|
||||||
@@ -82,7 +83,6 @@ const io = require('socket.io')(httpsServer, {
|
|||||||
transports: ['websocket'],
|
transports: ['websocket'],
|
||||||
});
|
});
|
||||||
const host = 'https://' + 'localhost' + ':' + config.listenPort; // config.listenIp
|
const host = 'https://' + 'localhost' + ':' + config.listenPort; // config.listenIp
|
||||||
const announcedIP = config.mediasoup.webRtcTransport.listenIps[0].announcedIp;
|
|
||||||
|
|
||||||
const hostCfg = {
|
const hostCfg = {
|
||||||
protected: config.hostProtected,
|
protected: config.hostProtected,
|
||||||
@@ -118,16 +118,6 @@ if (sentryEnabled) {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authenticated IP by Login
|
|
||||||
let authHost;
|
|
||||||
|
|
||||||
// all mediasoup workers
|
|
||||||
let workers = [];
|
|
||||||
let nextMediasoupWorkerIdx = 0;
|
|
||||||
|
|
||||||
// all Room lists
|
|
||||||
let roomList = new Map();
|
|
||||||
|
|
||||||
// directory
|
// directory
|
||||||
const dir = {
|
const dir = {
|
||||||
public: path.join(__dirname, '../../', 'public'),
|
public: path.join(__dirname, '../../', 'public'),
|
||||||
@@ -145,20 +135,52 @@ const views = {
|
|||||||
room: path.join(__dirname, '../../', 'public/views/Room.html'),
|
room: path.join(__dirname, '../../', 'public/views/Room.html'),
|
||||||
};
|
};
|
||||||
|
|
||||||
app.use(cors());
|
let announcedIP = config.mediasoup.webRtcTransport.listenIps[0].announcedIp; // AnnouncedIP (server public IPv4)
|
||||||
app.use(compression());
|
|
||||||
app.use(express.json());
|
|
||||||
app.use(express.static(dir.public));
|
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
|
||||||
app.use(apiBasePath + '/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); // api docs
|
|
||||||
|
|
||||||
// all start from here
|
let authHost; // Authenticated IP by Login
|
||||||
app.get('*', function (next) {
|
|
||||||
|
let roomList = new Map();
|
||||||
|
|
||||||
|
// All mediasoup workers
|
||||||
|
let workers = [];
|
||||||
|
let nextMediasoupWorkerIdx = 0;
|
||||||
|
|
||||||
|
// Autodetect announcedIP (https://www.ipify.org)
|
||||||
|
if (!announcedIP) {
|
||||||
|
http.get(
|
||||||
|
{
|
||||||
|
host: 'api.ipify.org',
|
||||||
|
port: 80,
|
||||||
|
path: '/',
|
||||||
|
},
|
||||||
|
(resp) => {
|
||||||
|
resp.on('data', (ip) => {
|
||||||
|
announcedIP = ip.toString();
|
||||||
|
config.mediasoup.webRtcTransport.listenIps[0].announcedIp = announcedIP;
|
||||||
|
startServer();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
startServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
function startServer() {
|
||||||
|
// Start the app
|
||||||
|
app.use(cors());
|
||||||
|
app.use(compression());
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.static(dir.public));
|
||||||
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
app.use(apiBasePath + '/docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); // api docs
|
||||||
|
|
||||||
|
// all start from here
|
||||||
|
app.get('*', function (next) {
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove trailing slashes in url handle bad requests
|
// Remove trailing slashes in url handle bad requests
|
||||||
app.use((err, req, res, next) => {
|
app.use((err, req, res, next) => {
|
||||||
if (err instanceof SyntaxError || err.status === 400 || 'body' in err) {
|
if (err instanceof SyntaxError || err.status === 400 || 'body' in err) {
|
||||||
log.error('Request Error', {
|
log.error('Request Error', {
|
||||||
header: req.headers,
|
header: req.headers,
|
||||||
@@ -173,20 +195,20 @@ app.use((err, req, res, next) => {
|
|||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// main page
|
// main page
|
||||||
app.get(['/'], (req, res) => {
|
app.get(['/'], (req, res) => {
|
||||||
if (hostCfg.protected == true) {
|
if (hostCfg.protected == true) {
|
||||||
hostCfg.authenticated = false;
|
hostCfg.authenticated = false;
|
||||||
res.sendFile(views.login);
|
res.sendFile(views.login);
|
||||||
} else {
|
} else {
|
||||||
res.sendFile(views.landing);
|
res.sendFile(views.landing);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// handle login on host protected
|
// handle login on host protected
|
||||||
app.get(['/login'], (req, res) => {
|
app.get(['/login'], (req, res) => {
|
||||||
if (hostCfg.protected == true) {
|
if (hostCfg.protected == true) {
|
||||||
let ip = getIP(req);
|
let ip = getIP(req);
|
||||||
log.debug(`Request login to host from: ${ip}`, req.query);
|
log.debug(`Request login to host from: ${ip}`, req.query);
|
||||||
@@ -204,10 +226,10 @@ app.get(['/login'], (req, res) => {
|
|||||||
} else {
|
} else {
|
||||||
res.redirect('/');
|
res.redirect('/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// set new room name and join
|
// set new room name and join
|
||||||
app.get(['/newroom'], (req, res) => {
|
app.get(['/newroom'], (req, res) => {
|
||||||
if (hostCfg.protected == true) {
|
if (hostCfg.protected == true) {
|
||||||
let ip = getIP(req);
|
let ip = getIP(req);
|
||||||
if (allowedIP(ip)) {
|
if (allowedIP(ip)) {
|
||||||
@@ -219,10 +241,10 @@ app.get(['/newroom'], (req, res) => {
|
|||||||
} else {
|
} else {
|
||||||
res.sendFile(views.newRoom);
|
res.sendFile(views.newRoom);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// no room name specified to join || direct join
|
// no room name specified to join || direct join
|
||||||
app.get('/join/', (req, res) => {
|
app.get('/join/', (req, res) => {
|
||||||
if (hostCfg.authenticated && Object.keys(req.query).length > 0) {
|
if (hostCfg.authenticated && Object.keys(req.query).length > 0) {
|
||||||
log.debug('Direct Join', req.query);
|
log.debug('Direct Join', req.query);
|
||||||
// http://localhost:3010/join?room=test&password=0&name=mirotalksfu&audio=1&video=1&screen=1¬ify=1
|
// http://localhost:3010/join?room=test&password=0&name=mirotalksfu&audio=1&video=1&screen=1¬ify=1
|
||||||
@@ -232,38 +254,38 @@ app.get('/join/', (req, res) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
res.redirect('/');
|
res.redirect('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
// join room
|
// join room
|
||||||
app.get('/join/*', (req, res) => {
|
app.get('/join/*', (req, res) => {
|
||||||
if (hostCfg.authenticated) {
|
if (hostCfg.authenticated) {
|
||||||
res.sendFile(views.room);
|
res.sendFile(views.room);
|
||||||
} else {
|
} else {
|
||||||
res.redirect('/');
|
res.redirect('/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// if not allow video/audio
|
// if not allow video/audio
|
||||||
app.get(['/permission'], (req, res) => {
|
app.get(['/permission'], (req, res) => {
|
||||||
res.sendFile(views.permission);
|
res.sendFile(views.permission);
|
||||||
});
|
});
|
||||||
|
|
||||||
// privacy policy
|
// privacy policy
|
||||||
app.get(['/privacy'], (req, res) => {
|
app.get(['/privacy'], (req, res) => {
|
||||||
res.sendFile(views.privacy);
|
res.sendFile(views.privacy);
|
||||||
});
|
});
|
||||||
|
|
||||||
// mirotalk about
|
// mirotalk about
|
||||||
app.get(['/about'], (req, res) => {
|
app.get(['/about'], (req, res) => {
|
||||||
res.sendFile(views.about);
|
res.sendFile(views.about);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// API
|
// API
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|
||||||
// request meeting room endpoint
|
// request meeting room endpoint
|
||||||
app.post(['/api/v1/meeting'], (req, res) => {
|
app.post(['/api/v1/meeting'], (req, res) => {
|
||||||
// check if user was authorized for the api call
|
// check if user was authorized for the api call
|
||||||
let host = req.headers.host;
|
let host = req.headers.host;
|
||||||
let authorization = req.headers.authorization;
|
let authorization = req.headers.authorization;
|
||||||
@@ -285,10 +307,10 @@ app.post(['/api/v1/meeting'], (req, res) => {
|
|||||||
body: req.body,
|
body: req.body,
|
||||||
meeting: meetingURL,
|
meeting: meetingURL,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// request join room endpoint
|
// request join room endpoint
|
||||||
app.post(['/api/v1/join'], (req, res) => {
|
app.post(['/api/v1/join'], (req, res) => {
|
||||||
// check if user was authorized for the api call
|
// check if user was authorized for the api call
|
||||||
let host = req.headers.host;
|
let host = req.headers.host;
|
||||||
let authorization = req.headers.authorization;
|
let authorization = req.headers.authorization;
|
||||||
@@ -310,13 +332,13 @@ app.post(['/api/v1/join'], (req, res) => {
|
|||||||
body: req.body,
|
body: req.body,
|
||||||
join: joinURL,
|
join: joinURL,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// SLACK API
|
// SLACK API
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|
||||||
app.post('/slack', (req, res) => {
|
app.post('/slack', (req, res) => {
|
||||||
if (!slackEnabled) return res.end('`Under maintenance` - Please check back soon.');
|
if (!slackEnabled) return res.end('`Under maintenance` - Please check back soon.');
|
||||||
|
|
||||||
log.debug('Slack', req.headers);
|
log.debug('Slack', req.headers);
|
||||||
@@ -341,18 +363,18 @@ app.post('/slack', (req, res) => {
|
|||||||
return res.end(meetingURL);
|
return res.end(meetingURL);
|
||||||
}
|
}
|
||||||
return res.end('`Wrong signature` - Verification failed!');
|
return res.end('`Wrong signature` - Verification failed!');
|
||||||
});
|
});
|
||||||
|
|
||||||
// not match any of page before, so 404 not found
|
// not match any of page before, so 404 not found
|
||||||
app.get('*', function (req, res) {
|
app.get('*', function (req, res) {
|
||||||
res.sendFile(views.notFound);
|
res.sendFile(views.notFound);
|
||||||
});
|
});
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// NGROK
|
// NGROK
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|
||||||
async function ngrokStart() {
|
async function ngrokStart() {
|
||||||
try {
|
try {
|
||||||
await ngrok.authtoken(config.ngrokAuthToken);
|
await ngrok.authtoken(config.ngrokAuthToken);
|
||||||
await ngrok.connect(config.listenPort);
|
await ngrok.connect(config.listenPort);
|
||||||
@@ -376,13 +398,13 @@ async function ngrokStart() {
|
|||||||
log.error('Ngrok Start error: ', err.body);
|
log.error('Ngrok Start error: ', err.body);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// START SERVER
|
// START SERVER
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|
||||||
httpsServer.listen(config.listenPort, () => {
|
httpsServer.listen(config.listenPort, () => {
|
||||||
log.log(
|
log.log(
|
||||||
`%c
|
`%c
|
||||||
|
|
||||||
@@ -410,22 +432,22 @@ httpsServer.listen(config.listenPort, () => {
|
|||||||
mediasoup_client_version: mediasoupClient.version,
|
mediasoup_client_version: mediasoupClient.version,
|
||||||
sentry_enabled: sentryEnabled,
|
sentry_enabled: sentryEnabled,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// WORKERS
|
// WORKERS
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
await createWorkers();
|
await createWorkers();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error('Create Worker ERR --->', err);
|
log.error('Create Worker ERR --->', err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
async function createWorkers() {
|
async function createWorkers() {
|
||||||
let { numWorkers } = config.mediasoup;
|
let { numWorkers } = config.mediasoup;
|
||||||
|
|
||||||
log.debug('WORKERS:', numWorkers);
|
log.debug('WORKERS:', numWorkers);
|
||||||
@@ -443,19 +465,19 @@ async function createWorkers() {
|
|||||||
});
|
});
|
||||||
workers.push(worker);
|
workers.push(worker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getMediasoupWorker() {
|
async function getMediasoupWorker() {
|
||||||
const worker = workers[nextMediasoupWorkerIdx];
|
const worker = workers[nextMediasoupWorkerIdx];
|
||||||
if (++nextMediasoupWorkerIdx === workers.length) nextMediasoupWorkerIdx = 0;
|
if (++nextMediasoupWorkerIdx === workers.length) nextMediasoupWorkerIdx = 0;
|
||||||
return worker;
|
return worker;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ####################################################
|
// ####################################################
|
||||||
// SOCKET IO
|
// SOCKET IO
|
||||||
// ####################################################
|
// ####################################################
|
||||||
|
|
||||||
io.on('connection', (socket) => {
|
io.on('connection', (socket) => {
|
||||||
socket.on('createRoom', async ({ room_id }, callback) => {
|
socket.on('createRoom', async ({ room_id }, callback) => {
|
||||||
socket.room_id = room_id;
|
socket.room_id = room_id;
|
||||||
|
|
||||||
@@ -905,15 +927,15 @@ io.on('connection', (socket) => {
|
|||||||
let i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
let i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
||||||
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
|
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function getIP(req) {
|
function getIP(req) {
|
||||||
return req.headers['x-forwarded-for'] || req.socket.remoteAddress;
|
return req.headers['x-forwarded-for'] || req.socket.remoteAddress;
|
||||||
}
|
}
|
||||||
function allowedIP(ip) {
|
function allowedIP(ip) {
|
||||||
return authHost != null && authHost.isAuthorized(ip);
|
return authHost != null && authHost.isAuthorized(ip);
|
||||||
}
|
}
|
||||||
function removeIP(socket) {
|
function removeIP(socket) {
|
||||||
if (hostCfg.protected == true) {
|
if (hostCfg.protected == true) {
|
||||||
let ip = socket.handshake.address;
|
let ip = socket.handshake.address;
|
||||||
if (ip && allowedIP(ip)) {
|
if (ip && allowedIP(ip)) {
|
||||||
@@ -922,4 +944,5 @@ function removeIP(socket) {
|
|||||||
log.debug('Remove IP from auth', { ip: ip });
|
log.debug('Remove IP from auth', { ip: ip });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ module.exports = {
|
|||||||
listenIps: [
|
listenIps: [
|
||||||
{
|
{
|
||||||
ip: '0.0.0.0',
|
ip: '0.0.0.0',
|
||||||
announcedIp: getLocalIp(), // replace by public static IP address https://api.ipify.org
|
announcedIp: getLocalIp(), // replace by public static IP address https://api.ipify.org or put '' and will be auto-detected on server start
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
initialAvailableOutgoingBitrate: 1000000,
|
initialAvailableOutgoingBitrate: 1000000,
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم