[mirotalksfu] - #87 auto-detect announcedIP if not set

هذا الالتزام موجود في:
Miroslav Pejic
2022-12-29 16:48:14 +01:00
الأصل 9a2bc897f2
التزام 931cf38248
2 ملفات معدلة مع 722 إضافات و699 حذوفات

عرض الملف

@@ -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&notify=1 // http://localhost:3010/join?room=test&password=0&name=mirotalksfu&audio=1&video=1&screen=1&notify=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,