aae663ccea
Increment 1 server side. Move livekitToken() into server/livekit.js (shared by routes.js
and calls.js). calls.js now mints a per-callee LiveKit join token and calls.js/push.js
put {livekitUrl, livekitToken} in the VoIP invite payload, so the native plugin can
connect the LiveKit room immediately on answer — even from a killed state, before the
WebView loads. No behaviour change while CALLKIT_ENABLED=0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
24 lines
1.3 KiB
JavaScript
24 lines
1.3 KiB
JavaScript
// LiveKit helpers shared by routes.js (browser meeting/call join) and calls.js (native VoIP call payload).
|
|
// Mint an access token (HS256 JWT signed with the API secret) — hand-rolled, same approach as push.js's
|
|
// JWTs, so there's no SDK dependency. Grants join+publish+subscribe on exactly one room, as one identity.
|
|
// The secret stays server-side.
|
|
const crypto = require('crypto');
|
|
const { LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET, LIVEKIT_ENABLED } = require('./config');
|
|
|
|
const _b64u = (buf) => Buffer.from(buf).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
|
|
function livekitToken(identity, name, room, metadata) {
|
|
const nowSec = Math.floor(Date.now() / 1000);
|
|
const header = _b64u(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));
|
|
const payload = _b64u(JSON.stringify({
|
|
iss: LIVEKIT_API_KEY, sub: identity, name: name || identity,
|
|
nbf: nowSec, exp: nowSec + 6 * 3600, // 6h — long enough for any meeting/call
|
|
metadata: metadata || '',
|
|
video: { room, roomJoin: true, canPublish: true, canSubscribe: true, canPublishData: true },
|
|
}));
|
|
const sig = _b64u(crypto.createHmac('sha256', LIVEKIT_API_SECRET).update(header + '.' + payload).digest());
|
|
return header + '.' + payload + '.' + sig;
|
|
}
|
|
|
|
module.exports = { livekitToken, LIVEKIT_URL, LIVEKIT_ENABLED };
|