const { hasFilters, hasQuery, isValidSession, sortPaginate, getValidAttributes, uniqueAutocomplete } = require("./helper"); const { extractProjectKeyFromRequest, extractSessionIdFromRequest, extractPayloadFromRequest, } = require("./extractors"); const { RecordRequestDuration, IncreaseTotalRequests } = require('../utils/metrics'); const {fetchSockets} = require("./wsServer"); const {IDENTITIES} = require("./assistHelper"); const {logger} = require('./logger'); const respond = function (req, res, data) { logger.debug("responding with data: ", JSON.stringify(data)) let result = {data} if (process.env.uws !== "true") { res.statusCode = 200; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(result)); } else { if (!res.aborted) { res.cork(() => { res.writeStatus('200 OK').writeHeader('Content-Type', 'application/json').end(JSON.stringify(result)); }); } else { logger.debug("response aborted"); return; } } const duration = performance.now() - req.startTs; IncreaseTotalRequests(); RecordRequestDuration(req.method.toLowerCase(), res.handlerName, 200, duration/1000.0); } const getParticularSession = async function (roomId, filters) { let connected_sockets = await fetchSockets(roomId); if (connected_sockets.length === 0) { return null; } let sessInfo; for (let item of connected_sockets) { if (item.handshake.query.identity === IDENTITIES.session && item.handshake.query.sessionInfo) { sessInfo = item.handshake.query.sessionInfo; break; } } if (!sessInfo) { return null; } if (!hasFilters(filters)) { return sessInfo; } const result = isValidSession(sessInfo, filters.filter) if (result.matched) { return sessInfo; } return null; } const getAllSessions = async function (projectKey, filters, counters, onlineOnly= false) { const sessions = []; const connected_sockets = await fetchSockets(); if (connected_sockets.length === 0) { return sessions; } const rooms = new Map(); for (let item of connected_sockets) { // Prefilter checks if (rooms.has(item.handshake.query.roomId)) { continue; } if (item.handshake.query.projectKey !== projectKey || !item.handshake.query.sessionInfo) { continue; } if (onlineOnly && item.handshake.query.identity !== IDENTITIES.session) { continue; } // Mark this room as visited rooms.set(item.handshake.query.roomId, true); // Add session to the list without filtering if (!hasFilters(filters)) { sessions.push(item.handshake.query.sessionInfo); continue; } // Add session to the list if it passes the filter const result = isValidSession(item.handshake.query.sessionInfo, filters.filter) if (result.matched) { sessions.push(item.handshake.query.sessionInfo); // Add filter name/value to counter for (const [filterName, filterValue] of Object.entries(result.filters)) { if (counters[filterName] === undefined) { counters[filterName] = {}; } if (counters[filterName][filterValue] === undefined) { counters[filterName][filterValue] = 0; } counters[filterName][filterValue] += 1; } } } return sessions } // Sort by projectKey const socketsListByProject = async function (req, res) { logger.debug("[WS]looking for available sessions"); res.handlerName = 'socketsListByProject'; const _projectKey = extractProjectKeyFromRequest(req); const _sessionId = extractSessionIdFromRequest(req); const filters = await extractPayloadFromRequest(req, res); // find a particular session if (_sessionId) { const sessInfo = await getParticularSession(`${_projectKey}-${_sessionId}`, filters); return respond(req, res, sessInfo); } // find all sessions for a project const counters = {}; const sessions = await getAllSessions(_projectKey, filters, counters); // send response respond(req, res, sortPaginate(sessions, filters, counters)); } // Sort by projectKey const socketsLiveByProject = async function (req, res) { logger.debug("[WS]looking for available LIVE sessions"); res.handlerName = 'socketsLiveByProject'; const _projectKey = extractProjectKeyFromRequest(req); const _sessionId = extractSessionIdFromRequest(req); const filters = await extractPayloadFromRequest(req, res); // find a particular session if (_sessionId) { let sessInfo = await getParticularSession(`${_projectKey}-${_sessionId}`, filters); return respond(req, res, sessInfo); } // find all sessions for a project const counters = {}; const sessions = await getAllSessions(_projectKey, filters, counters, true); // send response respond(req, res, sortPaginate(sessions, filters, counters)); } // Sort by roomID (projectKey+sessionId) const socketsLiveBySession = async function (req, res) { logger.debug("[WS]looking for LIVE session"); res.handlerName = 'socketsLiveBySession'; const _projectKey = extractProjectKeyFromRequest(req); const _sessionId = extractSessionIdFromRequest(req); const filters = await extractPayloadFromRequest(req, res); // find a particular session if (_sessionId) { let sessInfo = await getParticularSession(`${_projectKey}-${_sessionId}`, filters); return respond(req, res, sessInfo); } return respond(req, res, null); } // Sort by projectKey const autocomplete = async function (req, res) { logger.debug("[WS]autocomplete"); res.handlerName = 'autocomplete'; const _projectKey = extractProjectKeyFromRequest(req); const filters = await extractPayloadFromRequest(req); let results = []; if (!hasQuery(filters)) { return respond(req, res, results); } let connected_sockets = await fetchSockets(); if (connected_sockets.length === 0) { return results; } const rooms = new Map(); for (let item of connected_sockets) { if (rooms.has(item.handshake.query.roomId)) { continue; } if (item.handshake.query.sessionInfo) { if ((item.handshake.query.projectKey !== _projectKey) || (item.handshake.query.identity !== IDENTITIES.session)) { continue; } // Mark this room as visited rooms.set(item.handshake.query.roomId, true); results.push(...getValidAttributes(item.handshake.query.sessionInfo, filters.query)) } } respond(req, res, uniqueAutocomplete(results)); } module.exports = { respond, socketsListByProject, socketsLiveByProject, socketsLiveBySession, autocomplete }