mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
mmtx integration / server installer
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
const { app } = require('../globals/http');
|
||||
const io = require('../globals/io');
|
||||
const logger = require('../globals/logger').child('videoAuth');
|
||||
const videoSessions = require('./videoSessions');
|
||||
const { getMode, MODES } = require('./modeManager');
|
||||
const { isAdmin, isLockdownAdmin, getRole } = require('./roleService');
|
||||
const roverManager = require('./roverManager');
|
||||
|
||||
function canView(socket) {
|
||||
const mode = getMode();
|
||||
if (!socket) {
|
||||
return false;
|
||||
}
|
||||
if (mode === MODES.LOCKDOWN) {
|
||||
return isLockdownAdmin(socket);
|
||||
}
|
||||
if (mode === MODES.ADMIN) {
|
||||
return isAdmin(socket);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
app.get('/mediamtx/auth', (req, res) => {
|
||||
const { session: sessionId, roverId } = req.query;
|
||||
if (!sessionId || !roverId) {
|
||||
logger.warn('auth missing session or rover');
|
||||
return res.status(401).end();
|
||||
}
|
||||
|
||||
const info = videoSessions.getSession(sessionId);
|
||||
if (!info || info.roverId !== roverId) {
|
||||
logger.warn('invalid session %s', sessionId);
|
||||
return res.status(401).end();
|
||||
}
|
||||
const socket = io.sockets.sockets.get(info.socketId);
|
||||
if (!socket) {
|
||||
videoSessions.revokeSession(sessionId);
|
||||
return res.status(401).end();
|
||||
}
|
||||
if (!canView(socket)) {
|
||||
return res.status(401).end();
|
||||
}
|
||||
// optionally ensure non-admin drivers only view their rover
|
||||
const role = getRole(socket);
|
||||
if (role !== 'spectator' && !isAdmin(socket)) {
|
||||
if (!roverManager.isDriver(roverId, socket)) {
|
||||
return res.status(401).end();
|
||||
}
|
||||
}
|
||||
|
||||
return res.status(200).end();
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const io = require('../globals/io');
|
||||
|
||||
const sessions = new Map(); // sessionId -> { socketId, roverId }
|
||||
const socketSessions = new Map(); // socketId -> Set(sessionId)
|
||||
|
||||
function createSession(socket, roverId) {
|
||||
const sessionId = uuidv4();
|
||||
sessions.set(sessionId, { socketId: socket.id, roverId });
|
||||
if (!socketSessions.has(socket.id)) {
|
||||
socketSessions.set(socket.id, new Set());
|
||||
}
|
||||
socketSessions.get(socket.id).add(sessionId);
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
function getSession(sessionId) {
|
||||
return sessions.get(sessionId);
|
||||
}
|
||||
|
||||
function revokeSession(sessionId) {
|
||||
const info = sessions.get(sessionId);
|
||||
if (!info) return;
|
||||
sessions.delete(sessionId);
|
||||
const bucket = socketSessions.get(info.socketId);
|
||||
if (bucket) {
|
||||
bucket.delete(sessionId);
|
||||
if (bucket.size === 0) {
|
||||
socketSessions.delete(info.socketId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function revokeBySocket(socketId) {
|
||||
const bucket = socketSessions.get(socketId);
|
||||
if (!bucket) return;
|
||||
for (const sessionId of bucket) {
|
||||
sessions.delete(sessionId);
|
||||
}
|
||||
socketSessions.delete(socketId);
|
||||
}
|
||||
|
||||
function revokeWhere(predicate) {
|
||||
for (const [sessionId, info] of Array.from(sessions.entries())) {
|
||||
if (predicate(info)) {
|
||||
revokeSession(sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
socket.on('disconnect', () => revokeBySocket(socket.id));
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
createSession,
|
||||
getSession,
|
||||
revokeSession,
|
||||
revokeBySocket,
|
||||
revokeWhere,
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
const io = require('../globals/io');
|
||||
const logger = require('../globals/logger').child('videoSocket');
|
||||
const { getMode, MODES } = require('./modeManager');
|
||||
const { isAdmin, isLockdownAdmin, getRole } = require('./roleService');
|
||||
const videoSessions = require('./videoSessions');
|
||||
const roverManager = require('./roverManager');
|
||||
const { loadConfig } = require('../helpers/configLoader');
|
||||
|
||||
const config = loadConfig();
|
||||
const mediaConfig = config.media || {};
|
||||
|
||||
function canView(socket, roverId) {
|
||||
const mode = getMode();
|
||||
if (mode === MODES.LOCKDOWN && !isLockdownAdmin(socket)) {
|
||||
return false;
|
||||
}
|
||||
if (mode === MODES.ADMIN && !isAdmin(socket)) {
|
||||
return false;
|
||||
}
|
||||
const role = getRole(socket);
|
||||
if (role === 'spectator' || isAdmin(socket)) {
|
||||
return true;
|
||||
}
|
||||
return roverManager.isDriver(roverId, socket);
|
||||
}
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
socket.on('video:request', ({ roverId } = {}, cb = () => {}) => {
|
||||
try {
|
||||
if (!mediaConfig.whepBaseUrl) {
|
||||
throw new Error('Server video base URL missing');
|
||||
}
|
||||
if (!roverId) {
|
||||
throw new Error('roverId required');
|
||||
}
|
||||
if (!canView(socket, roverId)) {
|
||||
throw new Error('Not authorized for video');
|
||||
}
|
||||
const sessionId = videoSessions.createSession(socket, roverId);
|
||||
const url = `${mediaConfig.whepBaseUrl.replace(/\/$/, '')}/${roverId}?session=${sessionId}`;
|
||||
cb({ url });
|
||||
} catch (err) {
|
||||
logger.warn('video request failed: %s', err.message);
|
||||
cb({ error: err.message });
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user