WebRTC: add onnegotiationneeded handler.

This commit is contained in:
Miroslav Šedivý 2021-11-24 23:56:36 +01:00
parent 3d78186094
commit 40d79e69b0
2 changed files with 44 additions and 25 deletions

View File

@ -73,6 +73,25 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
this._connection.websocket.send(EVENT.SIGNAL_CANDIDATE, candidate) this._connection.websocket.send(EVENT.SIGNAL_CANDIDATE, candidate)
this.emit('connection.webrtc.sdp.candidate', 'local', 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<NekoEvents> {
// Signal Events // 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._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) await this._connection.webrtc.connect(sdp, iceservers)
this._connection.websocket.send(EVENT.SIGNAL_ANSWER, {
sdp: localSdp,
})
this.emit('connection.webrtc.sdp', 'local', localSdp)
Vue.set(this._state.connection.webrtc, 'video', video) Vue.set(this._state.connection.webrtc, 'video', video)
} }
// Todo: Use on-offer event intead.
protected async [EVENT.SIGNAL_RESTART]({ sdp }: message.SignalAnswer) { protected async [EVENT.SIGNAL_RESTART]({ sdp }: message.SignalAnswer) {
this._localLog.debug(`EVENT.SIGNAL_RESTART`) this._localLog.debug(`EVENT.SIGNAL_RESTART`)
this.emit('connection.webrtc.sdp', 'remote', sdp) this.emit('connection.webrtc.sdp', 'remote', sdp)
const localSdp = await this._connection.webrtc.offer(sdp) await this._connection.webrtc.setOffer(sdp)
this._connection.websocket.send(EVENT.SIGNAL_ANSWER, {
sdp: localSdp,
})
this.emit('connection.webrtc.sdp', 'local', localSdp)
} }
protected [EVENT.SIGNAL_CANDIDATE](candidate: message.SignalCandidate) { protected [EVENT.SIGNAL_CANDIDATE](candidate: message.SignalCandidate) {

View File

@ -22,6 +22,7 @@ export interface NekoWebRTCEvents {
disconnected: (error?: Error) => void disconnected: (error?: Error) => void
track: (event: RTCTrackEvent) => void track: (event: RTCTrackEvent) => void
candidate: (candidate: RTCIceCandidateInit) => void candidate: (candidate: RTCIceCandidateInit) => void
negotiation: (description: RTCSessionDescriptionInit) => void
stats: (stats: WebRTCStats) => void stats: (stats: WebRTCStats) => void
['cursor-position']: (data: CursorPosition) => void ['cursor-position']: (data: CursorPosition) => void
['cursor-image']: (data: CursorImage) => void ['cursor-image']: (data: CursorImage) => void
@ -66,7 +67,7 @@ export class NekoWebRTC extends EventEmitter<NekoWebRTCEvents> {
this._log.debug(`adding remote ICE candidate`, { candidate }) this._log.debug(`adding remote ICE candidate`, { candidate })
} }
public async connect(sdp: string, iceServers: ICEServer[]): Promise<string> { public async connect(sdp: string, iceServers: ICEServer[]) {
if (!this.supported) { if (!this.supported) {
throw new Error('browser does not support webrtc') throw new Error('browser does not support webrtc')
} }
@ -143,19 +144,27 @@ export class NekoWebRTC extends EventEmitter<NekoWebRTCEvents> {
} }
} }
this._peer.onnegotiationneeded = () => { this._peer.onnegotiationneeded = async () => {
this._log.warn(`negotiation is needed`) 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.ontrack = this.onTrack.bind(this)
this._peer.ondatachannel = this.onDataChannel.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) { if (!this._peer) {
throw new Error('attempting to set offer for nonexistent peer') throw new Error('attempting to set offer for nonexistent peer')
} }
@ -174,11 +183,11 @@ export class NekoWebRTC extends EventEmitter<NekoWebRTCEvents> {
const answer = await this._peer.createAnswer() const answer = await this._peer.createAnswer()
this._peer!.setLocalDescription(answer) this._peer!.setLocalDescription(answer)
if (!answer.sdp) { if (answer) {
throw new Error('sdp answer is empty') this.emit('negotiation', answer)
} else {
this._log.warn(`negiotation answer is empty`)
} }
return answer.sdp
} }
public disconnect() { public disconnect() {