@hyperttp/transport-webrtc 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/webrtc.ts"],
4
- "sourcesContent": ["import type {\n HyperTransport,\n TransportListenOptions,\n TransportRequest,\n TransportResponse,\n TransportServer,\n} from \"@hyperttp/types\";\nimport {\n MAX_SIGNALING_BODY_BYTES,\n type ClientSession,\n type WebRtcServerSessionContext,\n type WebRtcServerSessionEvent,\n type PendingResponse,\n type ServerSession,\n type WebRtcSessionView,\n type WebRtcTrackEvent,\n type WebRtcTransportOptions as InternalWebRtcTransportOptions,\n type WebRtcTransportRequest,\n} from \"./types/types.js\";\nimport { abortError, decodeWireBody, encodeWireBody, errorFromUnknown } from \"./utils/helper.js\";\nimport { createServer, type Server as HttpServer } from \"node:http\";\nimport {\n MediaStream as WeriftMediaStream,\n RTCPeerConnection as WeriftPeerConnection,\n RTCDataChannel as WeriftDataChannel,\n type MediaStreamTrack as WeriftMediaStreamTrack,\n} from \"werift\";\n\ndeclare module \"@hyperttp/types\" {\n interface TransportServer {\n readonly webrtc?: Pick<\n WebRtcTransport,\n \"getSession\" | \"getServerSession\" | \"onTrack\" | \"closeServerSession\" | \"onServerSession\"\n >;\n }\n}\n\ntype WeriftPeerConfig = NonNullable<ConstructorParameters<typeof WeriftPeerConnection>[0]>;\ntype WeriftIceServers = WeriftPeerConfig[\"iceServers\"];\n\nfunction normalizeIceServers(servers: RTCIceServer[] | undefined): WeriftIceServers {\n const normalized = (servers ?? []).flatMap((server) => {\n const urls = Array.isArray(server.urls) ? server.urls : [server.urls];\n if (server.credential !== undefined && typeof server.credential !== \"string\") {\n throw new TypeError(\"Werift currently requires ICE server credentials to be strings.\");\n }\n return urls.map((url) => ({\n urls: url,\n ...(server.username !== undefined ? { username: server.username } : {}),\n ...(server.credential !== undefined ? { credential: server.credential } : {}),\n }));\n });\n return normalized as unknown as WeriftIceServers;\n}\n\nfunction createWeriftPeerConnection(configuration: RTCConfiguration): WeriftPeerConnection {\n const config = {\n iceServers: normalizeIceServers(configuration.iceServers),\n ...(configuration.iceTransportPolicy !== undefined\n ? { iceTransportPolicy: configuration.iceTransportPolicy }\n : {}),\n } as unknown as WeriftPeerConfig;\n return new WeriftPeerConnection(config);\n}\n\nfunction createWeriftMediaStream(): WeriftMediaStream {\n return new WeriftMediaStream();\n}\n\nexport type WebRtcTransportOptions = InternalWebRtcTransportOptions;\n\nexport interface WebRtcServerSessionView {\n readonly id: string;\n readonly context: WebRtcServerSessionContext;\n readonly peerConnection: WeriftPeerConnection;\n readonly remoteStream: WeriftMediaStream;\n readonly localStream?: WeriftMediaStream;\n}\n\nexport interface WebRtcTransportServer extends TransportServer {\n readonly webrtc: Pick<\n WebRtcTransport,\n \"getSession\" | \"getServerSession\" | \"onTrack\" | \"closeServerSession\" | \"onServerSession\"\n >;\n}\n\nexport class WebRtcTransport implements HyperTransport {\n private readonly sessions = new Map<string, ClientSession>();\n private readonly connecting = new Map<string, Promise<ClientSession>>();\n private readonly serverSessions = new Map<string, ServerSession>();\n private readonly sessionListeners = new Set<(event: WebRtcServerSessionEvent) => void>();\n private readonly closingServerSessions = new Map<string, Promise<void>>();\n private readonly trackListeners = new Set<(event: WebRtcTrackEvent) => void>();\n private readonly serverClosers = new Set<() => Promise<void>>();\n private requestSequence = 0;\n private closing = false;\n private readonly pendingPeers = new Set<WeriftPeerConnection>();\n private readonly iceServers: RTCIceServer[];\n private readonly iceGatheringTimeoutMs: number;\n private readonly signalingTimeoutMs: number;\n private readonly connectionTimeoutMs: number;\n private readonly requestTimeoutMs: number;\n readonly createMediaStream: () => WeriftMediaStream;\n private readonly createPeerConnection: (configuration: RTCConfiguration) => WeriftPeerConnection;\n private readonly options: InternalWebRtcTransportOptions;\n\n constructor(options: WebRtcTransportOptions = {}) {\n this.options = options as unknown as InternalWebRtcTransportOptions;\n this.createPeerConnection = options.createPeerConnection ?? createWeriftPeerConnection;\n this.createMediaStream =\n (options.createMediaStream as unknown as (() => WeriftMediaStream) | undefined) ??\n createWeriftMediaStream;\n this.iceServers = options.iceServers ?? [{ urls: \"stun:stun.l.google.com:19302\" }];\n this.iceGatheringTimeoutMs = options.iceGatheringTimeoutMs ?? 10_000;\n this.signalingTimeoutMs = options.signalingTimeoutMs ?? 10_000;\n this.connectionTimeoutMs = options.connectionTimeoutMs ?? 15_000;\n this.requestTimeoutMs = options.requestTimeoutMs ?? 15_000;\n }\n\n private log(level: \"debug\" | \"info\" | \"warn\" | \"error\", message: string, meta?: unknown): void {\n if (this.options.logger) {\n this.options.logger(level, message, meta);\n return;\n }\n if (!this.options.verbose && level !== \"error\") return;\n const output = level === \"debug\" ? console.debug : console[level];\n if (meta === undefined) output(message);\n else output(message, meta);\n }\n\n onTrack(listener: (event: WebRtcTrackEvent) => void): () => void {\n this.trackListeners.add(listener);\n return () => this.trackListeners.delete(listener);\n }\n\n onServerSession(listener: (event: WebRtcServerSessionEvent) => void): () => void {\n this.sessionListeners.add(listener);\n return () => this.sessionListeners.delete(listener);\n }\n\n private emitServerSession(session: ServerSession, type: \"created\" | \"closed\") {\n for (const listener of this.sessionListeners) {\n try {\n listener({ ...session.context, type });\n } catch (error) {\n this.log(\"error\", \"WebRTC session listener failed\", error);\n }\n }\n }\n\n getServerSession(sessionId: string): WebRtcServerSessionView | undefined {\n const session = this.serverSessions.get(sessionId);\n if (!session || session.closed) return undefined;\n return {\n id: session.id,\n context: session.context,\n peerConnection: session.peerConnection,\n remoteStream: session.remoteStream,\n ...(session.localStream ? { localStream: session.localStream } : {}),\n };\n }\n\n getSession(peerUrl: string): WebRtcSessionView | undefined {\n const session = this.sessions.get(peerUrl);\n if (!session || session.closed) return undefined;\n\n return {\n id: session.id,\n peerUrl: session.peerUrl,\n peerConnection: session.peerConnection,\n dataChannel: session.dataChannel,\n remoteStream: session.remoteStream,\n media: session.mediaController,\n ...(session.localStream ? { localStream: session.localStream } : {}),\n };\n }\n\n async execute(request: TransportRequest): Promise<TransportResponse> {\n if (this.closing) throw new Error(\"WebRTC transport is closed\");\n const rtcRequest = request as WebRtcTransportRequest;\n const peerUrl = rtcRequest.peerUrl ?? request.url;\n\n if (request.signal?.aborted) throw abortError(request.signal);\n\n const session = await this.getOrCreateSession(peerUrl, rtcRequest);\n await this.ensureMedia(session, rtcRequest);\n\n if (request.signal?.aborted) throw abortError(request.signal);\n\n return this.sendRequest(session, request, rtcRequest.timeout);\n }\n\n public async listen(options: TransportListenOptions): Promise<WebRtcTransportServer> {\n if (this.closing) throw new Error(\"WebRTC transport is closed\");\n const ownedSessions = new Set<string>();\n const port = options.port ?? 3000;\n const host = options.host ?? \"127.0.0.1\";\n const signalingPath = options.signaling?.path ?? \"/signal\";\n if (\n !signalingPath.startsWith(\"/\") ||\n signalingPath.startsWith(\"//\") ||\n /[?#\\\\\\s]/u.test(signalingPath) ||\n Array.from(signalingPath).some((char) => {\n const code = char.codePointAt(0)!;\n return code <= 0x1f || (code >= 0x7f && code <= 0x9f);\n }) ||\n new URL(signalingPath, \"http://localhost\").pathname !== signalingPath\n ) {\n throw new TypeError(\n \"WebRTC signaling path must be an absolute literal pathname without query or fragment\",\n );\n }\n\n if (options.signal?.aborted) {\n throw new Error(\"WebRtcTransport: server startup aborted\");\n }\n\n let closed = false;\n let closePromise: Promise<void> | undefined;\n const pendingAuthorizations = new Set<AbortController>();\n\n const httpServer: HttpServer = createServer((req, res) => {\n void (async () => {\n const sendJson = (status: number, body: unknown) => {\n if (res.headersSent || res.destroyed) return;\n res.writeHead(status, { \"content-type\": \"application/json\" });\n res.end(JSON.stringify(body));\n };\n\n if (closed || this.closing) {\n sendJson(503, { error: \"WebRTC server is closing\" });\n return;\n }\n\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(req.url ?? \"/\", \"http://localhost\");\n } catch {\n sendJson(400, { error: \"Invalid request URL\" });\n return;\n }\n\n if (parsedUrl.pathname !== signalingPath) {\n sendJson(404, { error: \"Signaling endpoint not found\" });\n return;\n }\n\n let ownerId: string | undefined;\n let authorization: unknown;\n if ((req.method === \"POST\" || req.method === \"DELETE\") && options.signaling?.authorize) {\n const controller = new AbortController();\n const onDisconnect = () => controller.abort();\n const onAuthorizationAbort = () => {\n sendJson(503, { error: \"WebRTC signaling request aborted\" });\n };\n req.once(\"aborted\", onDisconnect);\n res.once(\"close\", onDisconnect);\n controller.signal.addEventListener(\"abort\", onAuthorizationAbort, { once: true });\n pendingAuthorizations.add(controller);\n try {\n const headers: Record<string, string | string[]> = {};\n for (const [name, value] of Object.entries(req.headers)) {\n if (value !== undefined) headers[name] = value;\n }\n const allowed = await options.signaling.authorize({\n protocol: \"webrtc\",\n method: req.method,\n url: req.url ?? \"/\",\n headers,\n signal: controller.signal,\n });\n if (controller.signal.aborted || req.aborted || res.destroyed) return;\n if (closed || this.closing || options.signal?.aborted) {\n sendJson(503, { error: \"WebRTC server is closing\" });\n return;\n }\n if (typeof allowed === \"object\" && allowed !== null) {\n if (typeof allowed.ownerId !== \"string\" || !allowed.ownerId.trim()) {\n sendJson(403, { error: \"Invalid signaling identity\" });\n return;\n }\n ownerId = allowed.ownerId;\n authorization = allowed.context;\n } else if (allowed !== true) {\n sendJson(403, { error: \"Signaling forbidden\" });\n return;\n }\n } catch {\n sendJson(403, { error: \"Signaling forbidden\" });\n return;\n } finally {\n pendingAuthorizations.delete(controller);\n req.off(\"aborted\", onDisconnect);\n res.off(\"close\", onDisconnect);\n controller.signal.removeEventListener(\"abort\", onAuthorizationAbort);\n }\n }\n\n if (req.method === \"DELETE\") {\n const sessionId = parsedUrl.searchParams.get(\"sessionId\");\n const existing = sessionId ? this.serverSessions.get(sessionId) : undefined;\n if (\n existing &&\n (!ownedSessions.has(sessionId!) || existing.context.ownerId !== ownerId)\n ) {\n sendJson(403, { error: \"Signaling forbidden\" });\n return;\n }\n if (sessionId && ownedSessions.has(sessionId)) {\n await this.closeServerSession(sessionId);\n ownedSessions.delete(sessionId);\n }\n res.writeHead(204).end();\n return;\n }\n\n if (req.method !== \"POST\") {\n sendJson(405, { error: \"Method not allowed\" });\n return;\n }\n\n let raw = \"\";\n try {\n for await (const chunk of req) {\n raw += Buffer.isBuffer(chunk) ? chunk.toString(\"utf8\") : String(chunk);\n if (Buffer.byteLength(raw, \"utf8\") > MAX_SIGNALING_BODY_BYTES) {\n sendJson(413, { error: \"Signaling payload too large\" });\n return;\n }\n }\n } catch (error) {\n sendJson(400, { error: errorFromUnknown(error, \"Failed to read body\").message });\n return;\n }\n\n let pc: WeriftPeerConnection | undefined;\n let session: ServerSession | undefined;\n\n try {\n const payload = JSON.parse(raw) as {\n sessionId?: unknown;\n sdp?: RTCSessionDescriptionInit;\n };\n\n if (\n typeof payload.sessionId !== \"string\" ||\n payload.sessionId.length < 1 ||\n payload.sessionId.length > 200 ||\n payload.sdp?.type !== \"offer\" ||\n typeof payload.sdp.sdp !== \"string\"\n ) {\n sendJson(400, { error: \"Expected sessionId and a valid SDP offer\" });\n return;\n }\n\n if (closed || this.closing || options.signal?.aborted || req.aborted || res.destroyed) {\n throw new Error(\"WebRTC signaling request aborted\");\n }\n const sessionId = payload.sessionId;\n session = this.serverSessions.get(sessionId);\n if (session && !ownedSessions.has(sessionId)) {\n sendJson(409, { error: \"Session belongs to another listener\" });\n return;\n }\n if (session && session.context.ownerId !== ownerId) {\n sendJson(403, { error: \"Signaling forbidden\" });\n return;\n }\n if (this.closingServerSessions.has(sessionId)) {\n sendJson(409, { error: \"Session is closing\" });\n return;\n }\n if (session?.negotiating) {\n sendJson(409, { error: \"Session negotiation already in progress\" });\n return;\n }\n\n if (!session || session.closed) {\n pc = this.createPeerConnection({ iceServers: this.iceServers });\n const controller = new AbortController();\n session = {\n controller,\n context: Object.freeze({\n sessionId,\n ownerId,\n authorization,\n signal: controller.signal,\n }),\n release: () => ownedSessions.delete(sessionId),\n id: sessionId,\n peerConnection: pc,\n remoteStream: this.createMediaStream(),\n localTrackIds: new Set<string>(),\n localStreamResolved: false,\n ownsLocalStream: false,\n closed: false,\n };\n ownedSessions.add(sessionId);\n this.serverSessions.set(sessionId, session);\n this.attachServerPeerEvents(session, options.onRequest);\n this.emitServerSession(session, \"created\");\n } else {\n pc = session.peerConnection;\n }\n\n session.negotiating = true;\n const activeSession = session;\n const disconnect = () => {\n if (!res.writableEnded) void this.closeServerSession(activeSession.id);\n };\n res.once(\"close\", disconnect);\n const onSessionAbort = () => sendJson(503, { error: \"WebRTC session closed\" });\n activeSession.controller.signal.addEventListener(\"abort\", onSessionAbort, { once: true });\n res.once(\"finish\", () => {\n activeSession.controller.signal.removeEventListener(\"abort\", onSessionAbort);\n res.off(\"close\", disconnect);\n });\n await this.setRemoteDescription(pc, payload.sdp);\n await this.attachConfiguredServerStream(session);\n if (session.closed) throw new Error(\"WebRTC session closed\");\n\n const answer = await pc.createAnswer();\n await this.withDeadline(pc.setLocalDescription(answer), this.iceGatheringTimeoutMs);\n if (!(await this.waitForIceGatheringComplete(pc, this.iceGatheringTimeoutMs)))\n throw new Error(\"Full ICE gathering timed out; trickle ICE is not supported\");\n\n const localDescription = pc.localDescription;\n if (!localDescription?.sdp || localDescription.type !== \"answer\") {\n throw new Error(\"Local SDP answer was not generated\");\n }\n\n if (closed || session.closed) throw new Error(\"WebRTC session closed\");\n session.negotiating = false;\n sendJson(200, localDescription);\n } catch (error) {\n this.log(\"error\", \"[WebRtcTransport Server] \u041E\u0448\u0438\u0431\u043A\u0430 \u0441\u0438\u0433\u043D\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438:\", error);\n if (session) {\n await this.closeServerSession(session.id);\n } else if (pc) {\n try {\n await pc.close();\n } catch {}\n }\n sendJson(400, { error: errorFromUnknown(error, \"Signaling failed\").message });\n }\n })();\n });\n\n await new Promise<void>((resolve, reject) => {\n const onError = (error: Error) => {\n httpServer.off(\"listening\", onListening);\n reject(error);\n };\n const onListening = () => {\n httpServer.off(\"error\", onError);\n resolve();\n };\n httpServer.once(\"error\", onError);\n httpServer.once(\"listening\", onListening);\n httpServer.listen(port, host);\n });\n\n this.log(\"info\", `[WebRtcTransport] Listening on http://${host}:${port}${signalingPath}`);\n\n const onAbort = () => {\n void closeServer().catch((error) => {\n this.log(\"error\", \"[WebRtcTransport] Server shutdown failed:\", error);\n });\n };\n\n const closeServer = (): Promise<void> => {\n if (closePromise) return closePromise;\n closed = true;\n for (const controller of pendingAuthorizations) controller.abort();\n options.signal?.removeEventListener(\"abort\", onAbort);\n closePromise = (async () => {\n const stopped = httpServer.listening\n ? new Promise<void>((resolve, reject) => {\n httpServer.close((error) => (error ? reject(error) : resolve()));\n })\n : Promise.resolve();\n await Promise.all([...ownedSessions].map((id) => this.closeServerSession(id)));\n ownedSessions.clear();\n await stopped;\n this.serverClosers.delete(closeServer);\n })();\n return closePromise;\n };\n\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n this.serverClosers.add(closeServer);\n if (options.signal?.aborted && !closed) await closeServer();\n\n return {\n close: closeServer,\n webrtc: {\n getSession: this.getSession.bind(this),\n getServerSession: this.getServerSession.bind(this),\n onTrack: this.onTrack.bind(this),\n closeServerSession: (id: string) =>\n ownedSessions.has(id) ? this.closeServerSession(id) : Promise.resolve(),\n onServerSession: this.onServerSession.bind(this),\n },\n };\n }\n\n async close(): Promise<void> {\n this.closing = true;\n await Promise.all([...this.pendingPeers].map((pc) => pc.close().catch(() => {})));\n await Promise.allSettled(this.connecting.values());\n await Promise.all(\n [...this.sessions.values()].map((session) => this.disposeClientSession(session, true)),\n );\n await Promise.all([...this.serverClosers].map((closeServer) => closeServer()));\n }\n\n async destroy(): Promise<void> {\n await this.close();\n }\n\n private async getOrCreateSession(\n peerUrl: string,\n request: WebRtcTransportRequest,\n ): Promise<ClientSession> {\n const existing = this.sessions.get(peerUrl);\n if (\n existing &&\n !existing.closed &&\n existing.dataChannel.readyState === \"open\" &&\n existing.peerConnection.connectionState !== \"failed\" &&\n existing.peerConnection.connectionState !== \"closed\"\n ) {\n return existing;\n }\n\n if (existing) {\n await this.disposeClientSession(existing, true);\n }\n\n const inFlight = this.connecting.get(peerUrl);\n if (inFlight) return inFlight;\n\n const connectionPromise = this.createClientSession(peerUrl, request);\n this.connecting.set(peerUrl, connectionPromise);\n\n try {\n const session = await connectionPromise;\n if (this.closing || session.closed) {\n await this.disposeClientSession(session, true);\n throw new Error(\"WebRTC transport is closed\");\n }\n this.sessions.set(peerUrl, session);\n return session;\n } finally {\n if (this.connecting.get(peerUrl) === connectionPromise) {\n this.connecting.delete(peerUrl);\n }\n }\n }\n\n private async createClientSession(\n peerUrl: string,\n request: WebRtcTransportRequest,\n ): Promise<ClientSession> {\n const signalingUrl = this.toSignalingUrl(peerUrl);\n const id = this.createId(\"session\");\n const pc = this.createPeerConnection({\n iceServers: request.iceServers ?? this.iceServers,\n });\n this.pendingPeers.add(pc);\n const channel = pc.createDataChannel(request.channelLabel ?? \"hyperttp-webrtc-transport\", {\n ordered: true,\n });\n\n const session: ClientSession = {\n id,\n peerUrl,\n signalingUrl,\n peerConnection: pc,\n dataChannel: channel,\n remoteStream: this.createMediaStream(),\n ...(request.localStream ? { localStream: request.localStream } : {}),\n localTrackIds: new Set<string>(),\n pending: new Map<string, PendingResponse>(),\n negotiation: Promise.resolve(),\n closed: false,\n mediaController: {} as any,\n };\n\n const trackListeners = new Set<\n (e: { track: WeriftMediaStreamTrack; stream: WeriftMediaStream }) => void\n >();\n const trackEndedListeners = new Set<(e: { track: WeriftMediaStreamTrack }) => void>();\n const streamListeners = new Set<(e: { stream: WeriftMediaStream }) => void>();\n\n pc.addEventListener(\"track\", (event: WebRtcTrackEvent) => {\n const { track } = event;\n if (!session.remoteStream.getTracks().includes(track)) session.remoteStream.addTrack(track);\n for (const listener of trackListeners) listener({ track, stream: session.remoteStream });\n for (const listener of streamListeners) listener({ stream: session.remoteStream });\n track.addEventListener(\"ended\", () => {\n for (const listener of trackEndedListeners) listener({ track });\n });\n });\n\n session.mediaController = {\n localStream: session.localStream,\n remoteStream: session.remoteStream,\n addTrack: (track, stream) =>\n this.queueNegotiation(session, async () => {\n pc.addTrack(track, stream ?? session.localStream ?? this.createMediaStream());\n if (track.id) session.localTrackIds.add(track.id);\n await this.negotiate(session);\n }),\n replaceTrack: async (kind: \"audio\" | \"video\", track: any | null) => {\n const sender = pc.getSenders().find((s: any) => s.track && s.track.kind === kind);\n if (sender) {\n await sender.replaceTrack(track);\n }\n },\n removeTrack: (track) =>\n this.queueNegotiation(session, async () => {\n const sender = pc.getSenders().find((item) => item.track === track);\n if (sender) {\n pc.removeTrack(sender);\n if (track.id) session.localTrackIds.delete(track.id);\n await this.negotiate(session);\n }\n }),\n close: async () => {\n await this.disposeClientSession(session, true);\n },\n on(event: string, listener: any) {\n if (event === \"track\") trackListeners.add(listener);\n if (event === \"trackEnded\") trackEndedListeners.add(listener);\n if (event === \"stream\") streamListeners.add(listener);\n return () => {\n trackListeners.delete(listener);\n trackEndedListeners.delete(listener);\n streamListeners.delete(listener);\n };\n },\n };\n\n try {\n this.attachClientPeerEvents(session);\n this.addLocalTracks(session, request.localStream);\n this.addReceiveTransceivers(session, request.receiveAudio, request.receiveVideo);\n await this.negotiate(session, request.signal);\n await this.waitForChannelOpen(channel, this.connectionTimeoutMs, request.signal);\n return session;\n } catch (error) {\n await this.disposeClientSession(session, true);\n throw error;\n } finally {\n this.pendingPeers.delete(pc);\n }\n }\n\n private attachClientPeerEvents(session: ClientSession): void {\n const { peerConnection: pc, dataChannel: channel } = session;\n\n pc.addEventListener(\"track\", (event: any) => {\n const track = event.track;\n if (!session.remoteStream.getTracks().some((item: any) => item.id === track.id)) {\n session.remoteStream.addTrack(track);\n }\n\n this.emitTrack({\n side: \"client\",\n sessionId: session.id,\n peerUrl: session.peerUrl,\n peerConnection: pc,\n track,\n stream: session.remoteStream,\n streams: event.streams,\n });\n });\n\n pc.addEventListener(\"connectionstatechange\", () => {\n if (pc.connectionState === \"failed\" || pc.connectionState === \"closed\") {\n void this.disposeClientSession(session, true);\n }\n });\n\n channel.addEventListener(\"message\", (event: MessageEvent) => {\n let message: Record<string, unknown>;\n try {\n message = JSON.parse(String(event.data)) as Record<string, unknown>;\n } catch {\n return;\n }\n\n if (!message || typeof message !== \"object\" || typeof message.requestId !== \"string\") return;\n const pending = session.pending.get(message.requestId);\n if (!pending) return;\n\n try {\n const body = decodeWireBody(message.body);\n this.finishPending(session, message.requestId);\n pending.resolve({\n status: typeof message.status === \"number\" ? message.status : 200,\n statusText: typeof message.statusText === \"string\" ? message.statusText : \"OK\",\n headers:\n message.headers && typeof message.headers === \"object\"\n ? (message.headers as TransportResponse[\"headers\"])\n : {},\n body,\n url: typeof message.url === \"string\" ? message.url : session.peerUrl,\n });\n } catch (error) {\n this.finishPending(session, message.requestId);\n pending.reject(errorFromUnknown(error, \"Invalid WebRTC response\"));\n }\n });\n\n channel.addEventListener(\"close\", () => {\n this.rejectAllPending(session, new Error(\"WebRTC DataChannel closed\"));\n void this.disposeClientSession(session, true);\n });\n\n channel.addEventListener(\"error\", () => {\n this.rejectAllPending(session, new Error(\"WebRTC DataChannel error\"));\n });\n }\n\n private queueNegotiation(session: ClientSession, operation: () => Promise<void>): Promise<void> {\n const pending = session.negotiation\n .catch(() => undefined)\n .then(async () => {\n if (session.closed) throw new Error(\"WebRTC session closed\");\n try {\n await operation();\n } catch (error) {\n await this.disposeClientSession(session, true);\n throw error;\n }\n });\n session.negotiation = pending;\n return pending;\n }\n\n private async ensureMedia(\n session: ClientSession,\n request: WebRtcTransportRequest,\n ): Promise<void> {\n const needsPotentialChanges =\n Boolean(request.localStream) ||\n Boolean(request.receiveAudio) ||\n Boolean(request.receiveVideo);\n if (!needsPotentialChanges || session.closed) return;\n\n await this.queueNegotiation(session, async () => {\n let changed = this.addLocalTracks(session, request.localStream);\n changed =\n this.addReceiveTransceivers(session, request.receiveAudio, request.receiveVideo) || changed;\n\n if (request.localStream) {\n session.localStream = request.localStream;\n (session.mediaController as { localStream?: WeriftMediaStream }).localStream =\n request.localStream;\n }\n if (changed) await this.negotiate(session, request.signal);\n });\n }\n\n private addLocalTracks(session: ClientSession, stream?: WeriftMediaStream): boolean {\n if (!stream) return false;\n let changed = false;\n\n for (const track of stream.getTracks()) {\n if (track.readyState !== \"live\" || session.localTrackIds.has(track.id!)) continue;\n session.peerConnection.addTrack(track, stream);\n session.localTrackIds.add(track.id!);\n changed = true;\n }\n\n return changed;\n }\n\n private addReceiveTransceivers(\n session: ClientSession,\n receiveAudio?: boolean,\n receiveVideo?: boolean,\n ): boolean {\n const pc = session.peerConnection;\n let changed = false;\n\n const ensureReceive = (kind: \"audio\" | \"video\", enabled: boolean | undefined) => {\n if (!enabled) return;\n const transceivers = pc\n .getTransceivers()\n .find(\n (item: any) =>\n item.receiver.track.kind === kind &&\n (item.direction === \"recvonly\" || item.direction === \"sendrecv\"),\n );\n if (!transceivers) {\n pc.addTransceiver(kind, { direction: \"recvonly\" });\n changed = true;\n }\n };\n\n ensureReceive(\"audio\", receiveAudio);\n ensureReceive(\"video\", receiveVideo);\n\n return changed;\n }\n\n private async negotiate(session: ClientSession, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) throw abortError(signal);\n\n const pc = session.peerConnection;\n if (pc.signalingState !== \"stable\") {\n throw new Error(`Cannot negotiate WebRTC session in state ${pc.signalingState}`);\n }\n\n const offer = await pc.createOffer();\n await this.withDeadline(pc.setLocalDescription(offer), this.iceGatheringTimeoutMs, signal);\n await this.waitForIceGatheringComplete(pc, this.iceGatheringTimeoutMs);\n\n const localDescription = pc.localDescription;\n if (!localDescription?.sdp || localDescription.type !== \"offer\") {\n throw new Error(\"Local SDP offer was not generated\");\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.signalingTimeoutMs);\n const abortListener = () => controller.abort(signal?.reason);\n signal?.addEventListener(\"abort\", abortListener, { once: true });\n if (signal?.aborted) abortListener();\n\n try {\n const response = await fetch(session.signalingUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ sessionId: session.id, sdp: localDescription }),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `Signaling HTTP error: ${response.status} ${response.statusText}${text ? ` \u2014 ${text}` : \"\"}`,\n );\n }\n\n const answer = (await response.json()) as RTCSessionDescriptionInit;\n if (answer.type !== \"answer\" || typeof answer.sdp !== \"string\") {\n throw new Error(\"Signaling server returned an invalid SDP answer\");\n }\n\n await this.setRemoteDescription(pc, answer);\n } catch (error) {\n if (signal?.aborted) throw abortError(signal);\n if (controller.signal.aborted) {\n throw new Error(`Signaling timed out after ${this.signalingTimeoutMs} ms`);\n }\n throw errorFromUnknown(error, \"WebRTC signaling failed\");\n } finally {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", abortListener);\n }\n }\n\n private async setRemoteDescription(\n pc: WeriftPeerConnection,\n description: RTCSessionDescriptionInit,\n ): Promise<void> {\n const previous = new Set(pc.dtlsTransports);\n try {\n await pc.setRemoteDescription(description);\n } finally {\n // Werift can replace transports while applying BUNDLE without stopping the\n // displaced ICE sockets. They are no longer reachable by pc.close().\n const active = new Set(pc.dtlsTransports);\n await Promise.all(\n [...previous]\n .filter((transport) => !active.has(transport))\n .map((transport) => transport.stop()),\n );\n }\n }\n\n private async withDeadline<T>(\n operation: Promise<T>,\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n let onAbort: (() => void) | undefined;\n try {\n return await Promise.race([\n operation,\n new Promise<never>((_resolve, reject) => {\n timer = setTimeout(\n () => reject(new Error(`WebRTC operation timed out after ${timeoutMs} ms`)),\n timeoutMs,\n );\n onAbort = () => reject(abortError(signal));\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n if (signal?.aborted) onAbort();\n }),\n ]);\n } finally {\n clearTimeout(timer);\n if (onAbort) signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n private async waitForIceGatheringComplete(\n pc: WeriftPeerConnection,\n timeoutMs: number,\n ): Promise<boolean> {\n if (pc.iceGatheringState === \"complete\") return true;\n\n const completed = await new Promise<boolean>((resolve) => {\n let settled = false;\n let timer: ReturnType<typeof setTimeout>;\n\n const cleanup = () => {\n clearTimeout(timer);\n pc.removeEventListener(\"icegatheringstatechange\", onStateChange);\n };\n\n const finish = (value: boolean) => {\n if (settled) return;\n settled = true;\n cleanup();\n resolve(value);\n };\n\n const onStateChange = () => {\n if (pc.iceGatheringState === \"complete\") finish(true);\n };\n\n timer = setTimeout(() => finish(false), timeoutMs);\n pc.addEventListener(\"icegatheringstatechange\", onStateChange);\n onStateChange();\n });\n\n if (!completed) throw new Error(`ICE gathering timed out after ${timeoutMs} ms`);\n return true;\n }\n\n private async waitForChannelOpen(\n channel: WeriftDataChannel,\n timeoutMs: number,\n signal?: AbortSignal,\n ): Promise<void> {\n if (channel.readyState === \"open\") return;\n if (signal?.aborted) throw abortError(signal);\n\n await new Promise<void>((resolve, reject) => {\n let settled = false;\n const cleanup = () => {\n clearTimeout(timer);\n channel.removeEventListener(\"open\", onOpen);\n channel.removeEventListener(\"error\", onError);\n channel.removeEventListener(\"close\", onClose);\n signal?.removeEventListener(\"abort\", onAbort);\n };\n const finish = (error?: Error) => {\n if (settled) return;\n settled = true;\n cleanup();\n if (error) reject(error);\n else resolve();\n };\n const onOpen = () => finish();\n const onError = () => finish(new Error(\"WebRTC DataChannel failed to open\"));\n const onClose = () => finish(new Error(\"WebRTC DataChannel closed before opening\"));\n const onAbort = () => finish(abortError(signal));\n const timer = setTimeout(\n () => finish(new Error(`DataChannel open timeout after ${timeoutMs} ms`)),\n timeoutMs,\n );\n\n channel.addEventListener(\"open\", onOpen);\n channel.addEventListener(\"error\", onError);\n channel.addEventListener(\"close\", onClose);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n if (channel.readyState === \"open\") finish();\n else if (channel.readyState === \"closed\") finish(new Error(\"WebRTC DataChannel is closed\"));\n });\n }\n\n private sendRequest(\n session: ClientSession,\n request: TransportRequest,\n requestedTimeout?: number,\n ): Promise<TransportResponse> {\n if (request.signal?.aborted) return Promise.reject(abortError(request.signal));\n if (session.dataChannel.readyState !== \"open\") {\n return Promise.reject(new Error(\"WebRTC DataChannel is not open\"));\n }\n\n const requestId = this.createId(`request${++this.requestSequence}`);\n const timeoutMs =\n requestedTimeout && requestedTimeout > 0 ? requestedTimeout : this.requestTimeoutMs;\n\n return new Promise<TransportResponse>((resolve, reject) => {\n const pending: PendingResponse = {\n resolve,\n reject,\n timer: setTimeout(() => {\n this.finishPending(session, requestId);\n reject(new Error(`WebRTC request timed out after ${timeoutMs} ms`));\n }, timeoutMs),\n ...(request.signal ? { signal: request.signal } : {}),\n };\n\n if (request.signal) {\n pending.abortListener = () => {\n this.finishPending(session, requestId);\n reject(abortError(request.signal));\n };\n request.signal.addEventListener(\"abort\", pending.abortListener, { once: true });\n }\n\n session.pending.set(requestId, pending);\n\n try {\n session.dataChannel.send(\n JSON.stringify({\n requestId,\n method: request.method,\n url: request.url,\n headers: request.headers,\n body: encodeWireBody(request.body),\n protocol: request.protocol,\n }),\n );\n } catch (error) {\n this.finishPending(session, requestId);\n reject(errorFromUnknown(error, \"Failed to send WebRTC request\"));\n }\n });\n }\n\n private finishPending(session: ClientSession, requestId: string): void {\n const pending = session.pending.get(requestId);\n if (!pending) return;\n clearTimeout(pending.timer);\n if (pending.signal && pending.abortListener) {\n pending.signal.removeEventListener(\"abort\", pending.abortListener);\n }\n session.pending.delete(requestId);\n }\n\n private rejectAllPending(session: ClientSession, error: Error): void {\n for (const [requestId, pending] of session.pending) {\n this.finishPending(session, requestId);\n pending.reject(error);\n }\n }\n\n private async disposeClientSession(session: ClientSession, notifyRemote: boolean): Promise<void> {\n if (session.closed) return;\n session.closed = true;\n\n if (this.sessions.get(session.peerUrl) === session) {\n this.sessions.delete(session.peerUrl);\n }\n this.rejectAllPending(session, new Error(\"WebRTC session closed\"));\n\n try {\n session.dataChannel.close();\n } catch {}\n try {\n await session.peerConnection.close();\n } catch {}\n\n if (notifyRemote) {\n try {\n const url = new URL(session.signalingUrl);\n url.searchParams.set(\"sessionId\", session.id);\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 2_000);\n try {\n await fetch(url, { method: \"DELETE\", signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n } catch {}\n }\n }\n\n private attachServerPeerEvents(\n session: ServerSession,\n onRequest: TransportListenOptions[\"onRequest\"],\n ): void {\n const pc = session.peerConnection;\n\n pc.addEventListener(\"datachannel\", (event: any) => {\n const channel = event.channel;\n channel.addEventListener(\"message\", (messageEvent: MessageEvent) => {\n void (async () => {\n let requestId: string | undefined;\n try {\n const message = JSON.parse(String(messageEvent.data)) as {\n requestId?: unknown;\n method?: unknown;\n url?: unknown;\n headers?: unknown;\n body?: unknown;\n protocol?: unknown;\n };\n\n requestId = typeof message.requestId === \"string\" ? message.requestId : undefined;\n if (\n !requestId ||\n typeof message.method !== \"string\" ||\n typeof message.url !== \"string\"\n ) {\n throw new Error(\"Invalid WebRTC transport request\");\n }\n\n const request: TransportRequest = {\n method: message.method,\n url: message.url,\n headers:\n message.headers && typeof message.headers === \"object\"\n ? {\n ...(message.headers as TransportRequest[\"headers\"]),\n \"x-webrtc-session-id\": session.id,\n }\n : { \"x-webrtc-session-id\": session.id },\n body: decodeWireBody(message.body),\n protocol:\n typeof message.protocol === \"string\"\n ? (message.protocol as TransportRequest[\"protocol\"])\n : \"webrtc\",\n };\n\n let response: TransportResponse;\n if (!onRequest) {\n response = {\n status: 501,\n statusText: \"Not Implemented\",\n headers: { \"content-type\": \"application/json\" },\n body: { error: \"No server request handler configured\" },\n url: request.url,\n };\n } else {\n response = await onRequest(request);\n }\n\n if (channel.readyState !== \"open\") return;\n channel.send(\n JSON.stringify({\n requestId,\n status: response.status,\n statusText: response.statusText ?? \"\",\n headers: response.headers,\n body: encodeWireBody(response.body),\n url: response.url ?? request.url,\n }),\n );\n } catch (error) {\n this.log(\"error\", \"[WebRtcTransport Server] Request failed:\", error);\n if (requestId && channel.readyState === \"open\") {\n try {\n channel.send(\n JSON.stringify({\n requestId,\n status: 500,\n statusText: \"Internal Server Error\",\n headers: { \"content-type\": \"application/json\" },\n body: { error: errorFromUnknown(error, \"Request handler failed\").message },\n }),\n );\n } catch {}\n }\n }\n })();\n });\n });\n\n pc.addEventListener(\"track\", (event: any) => {\n const track = event.track;\n if (!session.remoteStream.getTracks().some((item: any) => item.id === track.id)) {\n session.remoteStream.addTrack(track);\n }\n this.emitTrack({\n side: \"server\",\n sessionId: session.id,\n peerConnection: pc,\n track,\n stream: session.remoteStream,\n streams: event.streams,\n });\n });\n\n pc.addEventListener(\"connectionstatechange\", () => {\n if (pc.connectionState === \"failed\" || pc.connectionState === \"closed\") {\n void this.closeServerSession(session.id);\n }\n });\n }\n\n private async attachConfiguredServerStream(session: ServerSession): Promise<void> {\n if (session.closed) return;\n\n if (!session.localStreamResolved) {\n const configured = this.options.localStream;\n const isFactory = typeof configured === \"function\";\n const stream = isFactory ? await configured(session.id, session.context) : configured;\n if (session.closed) {\n if (stream && isFactory) {\n session.localStream = stream;\n session.ownsLocalStream = true;\n this.disposeServerLocalStream(session);\n }\n return;\n }\n session.localStreamResolved = true;\n\n if (stream) {\n session.localStream = stream;\n session.ownsLocalStream = isFactory;\n }\n }\n\n const stream = session.localStream;\n if (!stream) return;\n\n const pc = session.peerConnection;\n for (const track of stream.getTracks()) {\n if (session.closed || track.readyState !== \"live\" || session.localTrackIds.has(track.id!)) {\n continue;\n }\n pc.addTrack(track, stream);\n session.localTrackIds.add(track.id!);\n }\n }\n\n private disposeServerLocalStream(session: ServerSession): void {\n const stream = session.localStream;\n const ownsStream = session.ownsLocalStream;\n\n delete session.localStream;\n session.ownsLocalStream = false;\n\n if (!stream || !ownsStream) return;\n\n try {\n this.options.disposeLocalStream?.(session.id, stream);\n } catch {\n } finally {\n for (const track of stream.getTracks()) {\n if (track.readyState !== \"ended\") track.stop();\n }\n }\n }\n\n /** Idempotent: concurrent closes share peer/resource cleanup. */\n public closeServerSession(sessionId: string): Promise<void> {\n const pending = this.closingServerSessions.get(sessionId);\n if (pending) return pending;\n const session = this.serverSessions.get(sessionId);\n if (!session || session.closed) return Promise.resolve();\n session.closed = true;\n session.controller.abort();\n session.release();\n this.serverSessions.delete(sessionId);\n const closing = Promise.resolve()\n .then(async () => {\n try {\n await session.peerConnection.close();\n } catch (error) {\n this.log(\"warn\", \"WebRTC peer close failed\", error);\n } finally {\n this.disposeServerLocalStream(session);\n this.emitServerSession(session, \"closed\");\n }\n })\n .finally(() => this.closingServerSessions.delete(sessionId));\n this.closingServerSessions.set(sessionId, closing);\n return closing;\n }\n\n private emitTrack(event: WebRtcTrackEvent): void {\n for (const listener of this.trackListeners) {\n try {\n listener(event);\n } catch (error) {\n this.log(\"error\", \"[WebRtcTransport] onTrack listener failed:\", error);\n }\n }\n }\n\n private toSignalingUrl(peerUrl: string): string {\n if (peerUrl.startsWith(\"webrtcs://\")) return peerUrl.replace(/^webrtcs:\\/\\//, \"https://\");\n if (peerUrl.startsWith(\"webrtc://\")) return peerUrl.replace(/^webrtc:\\/\\//, \"http://\");\n throw new Error(`Unsupported WebRTC signaling URL: ${peerUrl}`);\n }\n\n private createId(prefix: string): string {\n return `${prefix}-${crypto.randomUUID()}`;\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["MAX_SIGNALING_BODY_BYTES", "abortError", "decodeWireBody", "encodeWireBody", "errorFromUnknown", "createServer", "WeriftMediaStream", "WeriftPeerConnection", "normalizeIceServers", "servers", "server", "urls", "url", "__name", "createWeriftPeerConnection", "configuration", "config", "createWeriftMediaStream", "WebRtcTransport", "options", "level", "message", "meta", "output", "listener", "session", "type", "error", "sessionId", "peerUrl", "request", "rtcRequest", "ownedSessions", "port", "host", "signalingPath", "char", "code", "closed", "closePromise", "pendingAuthorizations", "httpServer", "req", "res", "sendJson", "status", "body", "parsedUrl", "ownerId", "authorization", "controller", "onDisconnect", "onAuthorizationAbort", "headers", "name", "value", "allowed", "existing", "raw", "chunk", "pc", "payload", "activeSession", "disconnect", "onSessionAbort", "answer", "localDescription", "resolve", "reject", "onError", "onListening", "onAbort", "closeServer", "stopped", "id", "inFlight", "connectionPromise", "signalingUrl", "channel", "trackListeners", "trackEndedListeners", "streamListeners", "event", "track", "stream", "kind", "sender", "s", "item", "pending", "operation", "changed", "receiveAudio", "receiveVideo", "ensureReceive", "enabled", "signal", "offer", "timer", "abortListener", "response", "text", "description", "previous", "active", "transport", "timeoutMs", "_resolve", "settled", "cleanup", "onStateChange", "finish", "onOpen", "onClose", "requestedTimeout", "requestId", "notifyRemote", "onRequest", "messageEvent", "configured", "isFactory", "ownsStream", "closing", "prefix"]
7
- }
File without changes
File without changes
File without changes