api/stream/manage: use cobalt Store for stream cache

This commit is contained in:
jj 2024-10-31 22:33:32 +00:00
parent 11314fb8d1
commit 132255b004
No known key found for this signature in database
2 changed files with 12 additions and 17 deletions

View file

@ -257,7 +257,7 @@ export const runAPI = (express, app, __dirname) => {
} }
}) })
app.get('/tunnel', apiTunnelLimiter, (req, res) => { app.get('/tunnel', apiTunnelLimiter, async (req, res) => {
const id = String(req.query.id); const id = String(req.query.id);
const exp = String(req.query.exp); const exp = String(req.query.exp);
const sig = String(req.query.sig); const sig = String(req.query.sig);
@ -276,7 +276,7 @@ export const runAPI = (express, app, __dirname) => {
return res.status(200).end(); return res.status(200).end();
} }
const streamInfo = verifyStream(id, sig, exp, sec, iv); const streamInfo = await verifyStream(id, sig, exp, sec, iv);
if (!streamInfo?.service) { if (!streamInfo?.service) {
return res.status(streamInfo.status).end(); return res.status(streamInfo.status).end();
} }

View file

@ -1,4 +1,4 @@
import NodeCache from "node-cache"; import Store from "../store/store.js";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
import { randomBytes } from "crypto"; import { randomBytes } from "crypto";
@ -12,16 +12,7 @@ import { decryptStream, encryptStream, generateHmac } from "../misc/crypto.js";
// optional dependency // optional dependency
const freebind = env.freebindCIDR && await import('freebind').catch(() => {}); const freebind = env.freebindCIDR && await import('freebind').catch(() => {});
const streamCache = new NodeCache({ const streamCache = new Store('streams');
stdTTL: env.streamLifespan,
checkperiod: 10,
deleteOnExpire: true,
useClones: false,
})
streamCache.on("expired", (key) => {
streamCache.del(key);
})
const internalStreamCache = new Map(); const internalStreamCache = new Map();
const hmacSalt = randomBytes(64).toString('hex'); const hmacSalt = randomBytes(64).toString('hex');
@ -51,10 +42,14 @@ export function createStream(obj) {
isHLS: obj.isHLS || false, isHLS: obj.isHLS || false,
}; };
// FIXME: this is now a Promise, but it is not awaited
// here. it may happen that the stream is not
// stored in the Store before it is requested.
streamCache.set( streamCache.set(
streamID, streamID,
encryptStream(streamData, iv, secret) encryptStream(streamData, iv, secret),
) env.streamLifespan
);
let streamLink = new URL('/tunnel', env.apiURL); let streamLink = new URL('/tunnel', env.apiURL);
@ -150,10 +145,10 @@ function wrapStream(streamInfo) {
return streamInfo; return streamInfo;
} }
export function verifyStream(id, hmac, exp, secret, iv) { export async function verifyStream(id, hmac, exp, secret, iv) {
try { try {
const ghmac = generateHmac(`${id},${exp},${iv},${secret}`, hmacSalt); const ghmac = generateHmac(`${id},${exp},${iv},${secret}`, hmacSalt);
const cache = streamCache.get(id.toString()); const cache = await streamCache.get(id.toString());
if (ghmac !== String(hmac)) return { status: 401 }; if (ghmac !== String(hmac)) return { status: 401 };
if (!cache) return { status: 404 }; if (!cache) return { status: 404 };