UNPKG

@oiij/web-rtc

Version:
197 lines (196 loc) 5.34 kB
// src/class.ts var WebRTC = class { #options; #controller = new AbortController(); #id; #connected = []; #status = "pending"; #iceConnectionState = "new"; #signalingState = "stable"; #connectionState = "new"; ws; peer; #sendMessage(data) { this.ws.send(JSON.stringify(data)); } async #onMessage(ev) { try { const { type, payload } = JSON.parse(ev.data); const { key, desc, candidate } = payload; switch (type) { case "register": this.#id = key; this.#status = "ready"; this.#onReady(); break; case "offer": { if (!desc || !key) return; await this.peer.setRemoteDescription(desc); const answer = await this.peer.createAnswer(); await this.peer.setLocalDescription(answer); this.#sendMessage({ type: "answer", payload: { key, desc: answer } }); } break; case "answer": if (!desc || !key) return; await this.peer.setRemoteDescription(desc); this.#sendMessage({ type: "answer-ok", payload: { key } }); break; case "answer-ok": if (!key) { return; } this.#status = "connected"; if (!this.#connected.includes(key)) { this.#connected.push(key); } break; case "ice-candidate": if (!candidate) return; try { await this.peer.addIceCandidate(candidate); } catch (error) { console.error(error); } break; default: break; } } catch (error) { console.error(error); } } #onIcecandidate(ev) { if (ev.candidate) { this.#sendMessage({ type: "ice-candidate", payload: { candidate: ev.candidate } }); } } #onReadyFn = null; #onReady() { if (this.#onReadyFn && typeof this.#onReadyFn === "function") { this.#onReadyFn(); } } #onConnectionFn = null; #onConnection(ev) { if (this.#onConnectionFn && typeof this.#onConnectionFn === "function") { this.#onConnectionFn(ev); } } #onConnectionStreamFn = null; #onConnectionStream(ev) { if (this.#onConnectionStreamFn && typeof this.#onConnectionStreamFn === "function") { this.#onConnectionStreamFn(ev); } } constructor(options) { this.#options = { host: "127.0.0.1", port: 6789, path: "/_web-rtc", ...options }; const { host, port, path, protocols, ...rtcConfig } = this.#options; this.ws = new WebSocket(`ws://${host}:${port}${path}`, protocols); this.ws.addEventListener("message", this.#onMessage, { signal: this.#controller.signal }); this.peer = new RTCPeerConnection(rtcConfig); this.#iceConnectionState = this.peer.iceConnectionState; this.#signalingState = this.peer.signalingState; this.#connectionState = this.peer.connectionState; this.peer.addEventListener("iceconnectionstatechange", () => { this.#iceConnectionState = this.peer.iceConnectionState; }, { signal: this.#controller.signal }); this.peer.addEventListener("signalingstatechange", () => { this.#signalingState = this.peer.signalingState; }, { signal: this.#controller.signal }); this.peer.addEventListener("connectionstatechange", () => { this.#connectionState = this.peer.connectionState; }, { signal: this.#controller.signal }); this.peer.addEventListener("icecandidate", this.#onIcecandidate, { signal: this.#controller.signal }); this.peer.addEventListener("datachannel", this.#onConnection, { signal: this.#controller.signal }); this.peer.addEventListener("track", this.#onConnectionStream, { signal: this.#controller.signal }); } get id() { return this.#id; } get connected() { return this.#connected; } get status() { return this.#status; } get iceConnectionState() { return this.#iceConnectionState; } get signalingState() { return this.#signalingState; } get connectionState() { return this.#connectionState; } async connect(id, label = "label") { const dataChannel = this.peer.createDataChannel(label); const offer = await this.peer.createOffer(); await this.peer.setLocalDescription(offer); this.#sendMessage({ type: "offer", payload: { key: id, desc: offer } }); return dataChannel; } async connectStream(id, stream) { stream.getTracks().forEach((track) => { this.peer.addTrack(track, stream); }); const offer = await this.peer.createOffer(); await this.peer.setLocalDescription(offer); this.#sendMessage({ type: "offer", payload: { key: id, desc: offer } }); return this.peer; } onReady(fn) { this.#onReadyFn = fn; } onConnection(fn) { this.#onConnectionFn = fn; } onConnectionStream(fn) { this.#onConnectionStreamFn = fn; } destroy() { this.#controller.abort(); this.ws.close(); this.peer.close(); } }; export { WebRTC };