Files
Final-Year-Project/Backend/media/sfu/registry.ts

142 lines
4.5 KiB
TypeScript

import type {
SfuConsumerDescriptor,
SfuMediaKind,
SfuProducerDescriptor,
SfuSessionDescriptor,
SfuSessionState,
SfuTransportDescriptor,
SfuTransportDirection,
} from './types';
type StoredSfuSession = SfuSessionDescriptor & {
updatedAt: string;
};
const nowIso = (): string => new Date().toISOString();
export class SfuSessionRegistry {
private readonly sessions = new Map<string, StoredSfuSession>();
private readonly transports = new Map<string, SfuTransportDescriptor>();
private readonly producers = new Map<string, SfuProducerDescriptor>();
private readonly consumers = new Map<string, SfuConsumerDescriptor>();
get(streamSessionId: string): SfuSessionDescriptor | null {
const found = this.sessions.get(streamSessionId);
if (!found) return null;
const { updatedAt: _updatedAt, ...descriptor } = found;
return descriptor;
}
set(session: SfuSessionDescriptor): SfuSessionDescriptor {
this.sessions.set(session.streamSessionId, { ...session, updatedAt: nowIso() });
return session;
}
updateState(streamSessionId: string, state: SfuSessionState): SfuSessionDescriptor | null {
const existing = this.sessions.get(streamSessionId);
if (!existing) return null;
const next: StoredSfuSession = { ...existing, state, updatedAt: nowIso() };
this.sessions.set(streamSessionId, next);
const { updatedAt: _updatedAt, ...descriptor } = next;
return descriptor;
}
list(): SfuSessionDescriptor[] {
return Array.from(this.sessions.values()).map(({ updatedAt: _updatedAt, ...descriptor }) => descriptor);
}
addTransport(input: {
transportId: string;
streamSessionId: string;
ownerDeviceId: string;
direction: SfuTransportDirection;
}): SfuTransportDescriptor {
const descriptor: SfuTransportDescriptor = {
transportId: input.transportId,
streamSessionId: input.streamSessionId,
ownerDeviceId: input.ownerDeviceId,
direction: input.direction,
state: 'new',
createdAt: nowIso(),
};
this.transports.set(descriptor.transportId, descriptor);
return descriptor;
}
getTransport(transportId: string): SfuTransportDescriptor | null {
return this.transports.get(transportId) ?? null;
}
listTransports(streamSessionId: string): SfuTransportDescriptor[] {
return Array.from(this.transports.values()).filter((transport) => transport.streamSessionId === streamSessionId);
}
connectTransport(transportId: string): SfuTransportDescriptor | null {
const existing = this.transports.get(transportId);
if (!existing) return null;
const next: SfuTransportDescriptor = { ...existing, state: 'connected' };
this.transports.set(transportId, next);
return next;
}
addProducer(input: {
producerId: string;
streamSessionId: string;
transportId: string;
cameraDeviceId: string;
kind: SfuMediaKind;
rtpParameters: Record<string, unknown>;
}): SfuProducerDescriptor {
const descriptor: SfuProducerDescriptor = {
producerId: input.producerId,
streamSessionId: input.streamSessionId,
transportId: input.transportId,
cameraDeviceId: input.cameraDeviceId,
kind: input.kind,
rtpParameters: input.rtpParameters,
createdAt: nowIso(),
};
this.producers.set(descriptor.producerId, descriptor);
return descriptor;
}
getProducer(producerId: string): SfuProducerDescriptor | null {
return this.producers.get(producerId) ?? null;
}
listProducers(streamSessionId: string): SfuProducerDescriptor[] {
return Array.from(this.producers.values())
.filter((producer) => producer.streamSessionId === streamSessionId)
.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
}
addConsumer(input: {
consumerId: string;
streamSessionId: string;
transportId: string;
viewerDeviceId: string;
producerId: string;
kind: SfuMediaKind;
rtpParameters: Record<string, unknown>;
}): SfuConsumerDescriptor {
const descriptor: SfuConsumerDescriptor = {
consumerId: input.consumerId,
streamSessionId: input.streamSessionId,
transportId: input.transportId,
viewerDeviceId: input.viewerDeviceId,
producerId: input.producerId,
kind: input.kind,
rtpParameters: input.rtpParameters,
createdAt: nowIso(),
};
this.consumers.set(descriptor.consumerId, descriptor);
return descriptor;
}
listConsumers(streamSessionId: string): SfuConsumerDescriptor[] {
return Array.from(this.consumers.values()).filter((consumer) => consumer.streamSessionId === streamSessionId);
}
}