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.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
/////////////////////////////
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) {

View File

@ -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<NekoWebRTCEvents> {
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) {
throw new Error('browser does not support webrtc')
}
@ -143,19 +144,27 @@ export class NekoWebRTC extends EventEmitter<NekoWebRTCEvents> {
}
}
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<NekoWebRTCEvents> {
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() {