feat: server image

This commit is contained in:
2026-04-29 18:54:08 +02:00
parent 3d81c34159
commit e1ac1d1bc0
27 changed files with 1340 additions and 615 deletions

View File

@@ -34,6 +34,9 @@ export type IncomingSignalingMessage = Omit<Partial<SignalingMessage>, 'type' |
users?: SignalingUserSummary[];
displayName?: string;
fromUserId?: string;
icon?: string;
iconUpdatedAt?: number;
targetUserId?: string;
};
interface IncomingSignalingMessageHandlerDependencies {
@@ -60,9 +63,7 @@ export class IncomingSignalingMessageHandler {
/** Tracks when we first started waiting for a remote-initiated offer from each peer. */
private readonly nonInitiatorWaitStart = new Map<string, number>();
constructor(
private readonly dependencies: IncomingSignalingMessageHandlerDependencies
) {}
constructor(private readonly dependencies: IncomingSignalingMessageHandlerDependencies) {}
handleMessage(message: IncomingSignalingMessage, signalUrl: string): void {
this.dependencies.logger.info('Signaling message', {
@@ -76,6 +77,7 @@ export class IncomingSignalingMessageHandler {
return;
case SIGNALING_TYPE_SERVER_USERS:
case 'server_icon_sync_peers':
this.handleServerUsersSignalingMessage(message, signalUrl);
return;
@@ -138,11 +140,9 @@ export class IncomingSignalingMessageHandler {
}
for (const user of users) {
if (!user.oderId)
continue;
if (!user.oderId) continue;
if (localOderId && user.oderId === localOderId)
continue;
if (localOderId && user.oderId === localOderId) continue;
this.clearUserJoinedFallbackOffer(user.oderId);
@@ -295,9 +295,9 @@ export class IncomingSignalingMessageHandler {
const hasRemainingSharedServers = Array.isArray(message.serverIds)
? this.dependencies.signalingCoordinator.replacePeerSharedServers(message.oderId, signalUrl, message.serverIds)
: (message.serverId
: message.serverId
? this.dependencies.signalingCoordinator.untrackPeerFromServer(message.oderId, signalUrl, message.serverId)
: false);
: false;
if (!hasRemainingSharedServers) {
this.dependencies.peerManager.removePeer(message.oderId);
@@ -310,11 +310,9 @@ export class IncomingSignalingMessageHandler {
const fromUserId = message.fromUserId;
const sdp = message.payload?.sdp;
if (!fromUserId || !sdp)
return;
if (!fromUserId || !sdp) return;
if (fromUserId === this.dependencies.getLocalOderId())
return;
if (fromUserId === this.dependencies.getLocalOderId()) return;
this.clearUserJoinedFallbackOffer(fromUserId);
this.nonInitiatorWaitStart.delete(fromUserId);
@@ -334,11 +332,9 @@ export class IncomingSignalingMessageHandler {
const fromUserId = message.fromUserId;
const sdp = message.payload?.sdp;
if (!fromUserId || !sdp)
return;
if (!fromUserId || !sdp) return;
if (fromUserId === this.dependencies.getLocalOderId())
return;
if (fromUserId === this.dependencies.getLocalOderId()) return;
this.clearUserJoinedFallbackOffer(fromUserId);
@@ -350,11 +346,9 @@ export class IncomingSignalingMessageHandler {
const fromUserId = message.fromUserId;
const candidate = message.payload?.candidate;
if (!fromUserId || !candidate)
return;
if (!fromUserId || !candidate) return;
if (fromUserId === this.dependencies.getLocalOderId())
return;
if (fromUserId === this.dependencies.getLocalOderId()) return;
this.clearUserJoinedFallbackOffer(fromUserId);
@@ -513,18 +507,15 @@ export class IncomingSignalingMessageHandler {
}
private shouldInitiatePeer(peerId: string, localOderId: string | null = this.dependencies.getLocalOderId()): boolean {
if (!localOderId)
return false;
if (!localOderId) return false;
if (peerId === localOderId)
return false;
if (peerId === localOderId) return false;
return localOderId < peerId;
}
private hasActivePeerConnection(peer: PeerData | undefined): boolean {
if (!peer)
return false;
if (!peer) return false;
const connectionState = peer.connection?.connectionState;
@@ -532,13 +523,11 @@ export class IncomingSignalingMessageHandler {
}
private isPeerConnectionNegotiating(peer: PeerData | undefined): boolean {
if (!peer || this.hasActivePeerConnection(peer))
return false;
if (!peer || this.hasActivePeerConnection(peer)) return false;
const connectionState = peer.connection?.connectionState;
if (connectionState === 'closed' || connectionState === 'failed')
return false;
if (connectionState === 'closed' || connectionState === 'failed') return false;
const signalingState = peer.connection?.signalingState;
const ageMs = Date.now() - peer.createdAt;
@@ -546,13 +535,11 @@ export class IncomingSignalingMessageHandler {
// If a local offer (or pranswer) has already been sent, the peer is actively
// negotiating with the remote side. Use a much longer grace period so that
// a slow signaling round-trip does not trigger a premature teardown.
if (signalingState === 'have-local-offer' || signalingState === 'have-local-pranswer')
return ageMs < PEER_NEGOTIATION_OFFER_SENT_GRACE_MS;
if (signalingState === 'have-local-offer' || signalingState === 'have-local-pranswer') return ageMs < PEER_NEGOTIATION_OFFER_SENT_GRACE_MS;
// ICE negotiation in progress (offer/answer exchange already complete, candidates being checked).
// TURN relay can take 5-15 s on high-latency networks, so use the same extended grace.
if (connectionState === 'connecting')
return ageMs < PEER_NEGOTIATION_OFFER_SENT_GRACE_MS;
if (connectionState === 'connecting') return ageMs < PEER_NEGOTIATION_OFFER_SENT_GRACE_MS;
return ageMs < PEER_NEGOTIATION_GRACE_MS;
}