From 40d79e69b007147353127f157bfb8d30f62386f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0ediv=C3=BD?= Date: Wed, 24 Nov 2021 23:56:36 +0100 Subject: [PATCH] WebRTC: add onnegotiationneeded handler. --- src/component/internal/messages.ts | 38 +++++++++++++++++++----------- src/component/internal/webrtc.ts | 31 +++++++++++++++--------- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/component/internal/messages.ts b/src/component/internal/messages.ts index f4d108b6..6b46909c 100644 --- a/src/component/internal/messages.ts +++ b/src/component/internal/messages.ts @@ -73,6 +73,25 @@ export class NekoMessages extends EventEmitter { this._connection.websocket.send(EVENT.SIGNAL_CANDIDATE, candidate) this.emit('connection.webrtc.sdp.candidate', 'local', candidate) }) + + this._connection.webrtc.on('negotiation', ({ sdp, type }: RTCSessionDescriptionInit) => { + if (!sdp) { + this._remoteLog.warn(`sdp empty while negotiation event`) + return + } + + if (type == 'answer') { + this._connection.websocket.send(EVENT.SIGNAL_ANSWER, { sdp }) + //} else if (type == 'offer') { + // // Todo: Implement + // this._connection.websocket.send(EVENT.SIGNAL_OFFER, { sdp }) + } else { + this._remoteLog.warn(`unsupported negotiation type`, { type }) + } + + // TODO: Pass type as well. + this.emit('connection.webrtc.sdp', 'local', sdp) + }) } ///////////////////////////// @@ -121,29 +140,20 @@ export class NekoMessages extends EventEmitter { // Signal Events ///////////////////////////// - protected async [EVENT.SIGNAL_PROVIDE]({ sdp: remoteSdp, video, iceservers }: message.SignalProvide) { + protected async [EVENT.SIGNAL_PROVIDE]({ sdp, video, iceservers }: message.SignalProvide) { this._localLog.debug(`EVENT.SIGNAL_PROVIDE`) - this.emit('connection.webrtc.sdp', 'remote', remoteSdp) + this.emit('connection.webrtc.sdp', 'remote', sdp) - const localSdp = await this._connection.webrtc.connect(remoteSdp, iceservers) - this._connection.websocket.send(EVENT.SIGNAL_ANSWER, { - sdp: localSdp, - }) - - this.emit('connection.webrtc.sdp', 'local', localSdp) + await this._connection.webrtc.connect(sdp, iceservers) Vue.set(this._state.connection.webrtc, 'video', video) } + // Todo: Use on-offer event intead. protected async [EVENT.SIGNAL_RESTART]({ sdp }: message.SignalAnswer) { this._localLog.debug(`EVENT.SIGNAL_RESTART`) this.emit('connection.webrtc.sdp', 'remote', sdp) - const localSdp = await this._connection.webrtc.offer(sdp) - this._connection.websocket.send(EVENT.SIGNAL_ANSWER, { - sdp: localSdp, - }) - - this.emit('connection.webrtc.sdp', 'local', localSdp) + await this._connection.webrtc.setOffer(sdp) } protected [EVENT.SIGNAL_CANDIDATE](candidate: message.SignalCandidate) { diff --git a/src/component/internal/webrtc.ts b/src/component/internal/webrtc.ts index f125a146..d354be03 100644 --- a/src/component/internal/webrtc.ts +++ b/src/component/internal/webrtc.ts @@ -22,6 +22,7 @@ export interface NekoWebRTCEvents { disconnected: (error?: Error) => void track: (event: RTCTrackEvent) => void candidate: (candidate: RTCIceCandidateInit) => void + negotiation: (description: RTCSessionDescriptionInit) => void stats: (stats: WebRTCStats) => void ['cursor-position']: (data: CursorPosition) => void ['cursor-image']: (data: CursorImage) => void @@ -66,7 +67,7 @@ export class NekoWebRTC extends EventEmitter { this._log.debug(`adding remote ICE candidate`, { candidate }) } - public async connect(sdp: string, iceServers: ICEServer[]): Promise { + public async connect(sdp: string, iceServers: ICEServer[]) { if (!this.supported) { throw new Error('browser does not support webrtc') } @@ -143,19 +144,27 @@ export class NekoWebRTC extends EventEmitter { } } - this._peer.onnegotiationneeded = () => { - this._log.warn(`negotiation is needed`) + this._peer.onnegotiationneeded = async () => { + const state = this._peer!.iceConnectionState + this._log.warn(`negotiation is needed`, { state }) + + const offer = await this._peer?.createOffer() + this._peer!.setLocalDescription(offer) + + if (offer) { + this.emit('negotiation', offer) + } else { + this._log.warn(`megotiatoion offer is empty`) + } } this._peer.ontrack = this.onTrack.bind(this) this._peer.ondatachannel = this.onDataChannel.bind(this) - this._peer.addTransceiver('audio', { direction: 'recvonly' }) - this._peer.addTransceiver('video', { direction: 'recvonly' }) - return await this.offer(sdp) + await this.setOffer(sdp) } - public async offer(sdp: string) { + public async setOffer(sdp: string) { if (!this._peer) { throw new Error('attempting to set offer for nonexistent peer') } @@ -174,11 +183,11 @@ export class NekoWebRTC extends EventEmitter { const answer = await this._peer.createAnswer() this._peer!.setLocalDescription(answer) - if (!answer.sdp) { - throw new Error('sdp answer is empty') + if (answer) { + this.emit('negotiation', answer) + } else { + this._log.warn(`negiotation answer is empty`) } - - return answer.sdp } public disconnect() {