Download src/handlers/signalingHandler.ts from Collabos/chatapi: direct link, hf CLI and curl.
- Browser
- Download file 2.75 kB
-
https://huggingface.co/spaces/Collabos/chatapi/resolve/main/src/handlers/signalingHandler.ts
- Command line
-
hf download hf://spaces/Collabos/chatapi/src/handlers/signalingHandler.ts
-
curl -L -o signalingHandler.ts https://huggingface.co/spaces/Collabos/chatapi/resolve/main/src/handlers/signalingHandler.ts
2.75 kB
| import WebSocket from 'ws'; | |
| import { ClientMessage } from '../utils/protocol'; | |
| import { safeSend, ServerMessageType } from '../utils/protocol'; | |
| import { isOnline } from '../redis/presenceClient'; | |
| import { enqueueOfflineMessage } from '../redis/messageClient'; | |
| import { registry } from '../services/connectionRegistry'; | |
| import { logger } from '../utils/logger'; | |
| /** | |
| * Handles WebRTC signaling: | |
| * - offer / answer / ice-candidate are forwarded to the target peer. | |
| * - If the peer is offline, the signal is dropped (SDP signals don't | |
| * queue — they are ephemeral). Only chat messages queue offline. | |
| * | |
| * WebRTC fallback to WS relay: | |
| * When a client detects iceConnectionState === 'failed' or 'disconnected', | |
| * it switches to type: 'relay' messages instead. | |
| * The server relays those via handleRelay in connectionHandler.ts. | |
| * This handler is only responsible for SDP/ICE forwarding. | |
| */ | |
| export async function handleSignaling( | |
| _senderWs: WebSocket, | |
| fromUid: string, | |
| msg: ClientMessage | |
| ): Promise<void> { | |
| const toUid = msg.payload.toUid as string | undefined; | |
| if (!toUid || typeof toUid !== 'string') { | |
| logger.warn('Signaling message missing toUid', { fromUid, type: msg.type }); | |
| return; | |
| } | |
| // Security: block self-signaling | |
| if (toUid === fromUid) return; | |
| const target = registry.getByUid(toUid); | |
| if (!target) { | |
| // Peer not on this process — check Redis | |
| const online = await isOnline(toUid).catch(() => false); | |
| if (!online) { | |
| // Peer offline — signal is ephemeral, inform the sender | |
| safeSend(_senderWs, 'peer-offline', { uid: toUid }); | |
| } | |
| // In a multi-node deployment: publish to Redis pub/sub here | |
| // for cross-node delivery. Single-node (HF): nothing to do. | |
| return; | |
| } | |
| // Forward the signal verbatim to the peer | |
| const forwardType = msg.type as ServerMessageType; | |
| safeSend( | |
| target.ws, | |
| forwardType, | |
| { | |
| fromUid, | |
| sdp: msg.payload.sdp, | |
| candidate: msg.payload.candidate, | |
| }, | |
| msg.requestId | |
| ); | |
| logger.debug('Signal forwarded', { type: msg.type, fromUid, toUid }); | |
| } | |
| /** | |
| * Notify a user that a specific peer has come online. | |
| * Called from connectionHandler after the user connects. | |
| */ | |
| export function notifyPeerOnline(targetUid: string, peerUid: string): void { | |
| const target = registry.getByUid(targetUid); | |
| if (!target) return; | |
| safeSend(target.ws, 'peer-online', { uid: peerUid }); | |
| } | |
| /** | |
| * Notify a user that a specific peer has gone offline. | |
| * Called from connectionHandler on disconnect. | |
| */ | |
| export function notifyPeerOffline(targetUid: string, peerUid: string): void { | |
| const target = registry.getByUid(targetUid); | |
| if (!target) return; | |
| safeSend(target.ws, 'peer-offline', { uid: peerUid }); | |
| } | |