Authorize direct file invitations within paired rooms and parties

This commit is contained in:
Jonathan Sykes
2026-10-03 20:26:07 +08:00
parent ef70da1806
commit 88e2e67eeb
6 changed files with 136 additions and 5 deletions

View File

@@ -28,6 +28,8 @@
* reach the server from the same public IP (i.e. the same home/church Wi-Fi).
* ========================================================================== */
import { createDirectRelay } from './direct-relay.js';
import { createHash, createHmac, randomBytes, randomInt, timingSafeEqual } from 'node:crypto';
export const REMOTE_COMMANDS = new Set([
@@ -145,7 +147,7 @@ export function createRemoteHub({ requireSameNetwork = false } = {}) {
const id = roomIdFor(d.secret);
let room = rooms.get(id);
if (!room) {
room = { id, secret: d.secret, host: null, hostName: d.name, hostIp: d.ip, remotes: new Map(), state: null, queue: null, code: null, codeExpires: 0, lastSeen: Date.now() };
room = { direct: createDirectRelay(), id, secret: d.secret, host: null, hostName: d.name, hostIp: d.ip, remotes: new Map(), state: null, queue: null, code: null, codeExpires: 0, lastSeen: Date.now() };
rooms.set(id, room);
}
if (room.host && room.host !== ws) {
@@ -158,7 +160,7 @@ export function createRemoteHub({ requireSameNetwork = false } = {}) {
d.roomId = id;
issueCode(room);
send(ws, { type: 'hello', roomId: id, code: room.code, codeExpires: room.codeExpires, remotes: remoteList(room) });
for (const r of room.remotes.values()) send(r.ws, { type: 'hello', hostName: room.hostName, state: room.state, queue: room.queue });
for (const r of room.remotes.values()) send(r.ws, { type: 'hello', you: r.ws.data.rid, hostName: room.hostName, state: room.state, queue: room.queue });
}
function openRemote(ws) {
@@ -172,7 +174,7 @@ export function createRemoteHub({ requireSameNetwork = false } = {}) {
if (prev && prev.ws !== ws) { try { prev.ws.close(4000, 'replaced'); } catch { /* gone */ } }
room.remotes.set(d.rid, { ws, name: d.name, since: Date.now() });
room.lastSeen = Date.now();
send(ws, { type: 'hello', hostName: room.hostName, state: room.state, queue: room.queue });
send(ws, { type: 'hello', you: d.rid, hostName: room.hostName, state: room.state, queue: room.queue });
send(room.host, { type: 'remotes', remotes: remoteList(room), joined: d.name });
}
@@ -185,6 +187,14 @@ export function createRemoteHub({ requireSameNetwork = false } = {}) {
const room = rooms.get(d.roomId);
if (!room) return;
room.lastSeen = Date.now();
if (m.type === 'direct') {
const me = d.role === 'host' ? (room.host === ws ? 'host' : null) : (room.remotes.get(d.rid)?.ws === ws ? d.rid : null);
if (!me) return;
const peers = new Map([...room.remotes].map(([rid, r]) => [rid, r.ws]));
if (room.host) peers.set('host', room.host);
room.direct.handle(me, m, peers, send);
return;
}
if (d.role === 'host') {
if (room.host !== ws) return;