diff --git a/frontend/WebRTC.ts b/frontend/WebRTC.ts index 668c63c..7b20b49 100644 --- a/frontend/WebRTC.ts +++ b/frontend/WebRTC.ts @@ -32,6 +32,12 @@ export default class WebRTC rtcpMuxPolicy:"require", }; + public isPolite() : boolean + { + let myId = this.peer?.mwse.peer('me').socketId as string; + let peerId = this.peer?.socketId as string; + return myId < peerId; + } public static defaultICEServers : RTCIceServer[] = [{ urls: "stun:stun.l.google.com:19302" @@ -49,6 +55,11 @@ export default class WebRTC public FileTransportChannel? : P2PFileSender; + public makingOffer = false; + public ignoreOffer = false; + public isSettingRemoteAnswerPending = false; + + constructor( rtcConfig?: RTCConfiguration, rtcServers?: RTCIceServer[] @@ -105,7 +116,23 @@ export default class WebRTC break; } case "offer":{ + let readyForOffer = !this.makingOffer && (this.rtc.signalingState == "stable" || this.isSettingRemoteAnswerPending); + + const offerCollision = !readyForOffer; + + this.ignoreOffer = !this.isPolite() && offerCollision; + + if(this.ignoreOffer){ + return; + } + + this.isSettingRemoteAnswerPending = false; + await this.rtc.setRemoteDescription(new RTCSessionDescription(data.value)); + + this.isSettingRemoteAnswerPending = false; + + let answer = await this.rtc.createAnswer({ offerToReceiveAudio: true, offerToReceiveVideo: true @@ -118,7 +145,19 @@ export default class WebRTC break; } case "answer":{ + + let readyForOffer = !this.makingOffer && (this.rtc.signalingState == "stable" || this.isSettingRemoteAnswerPending); + + const offerCollision = !readyForOffer; + + this.ignoreOffer = !this.isPolite() && offerCollision; + + if(this.ignoreOffer){ + return; + } + this.isSettingRemoteAnswerPending = true; await this.rtc.setRemoteDescription(new RTCSessionDescription(data.value)) + this.isSettingRemoteAnswerPending = false; break; } case "streamInfo":{ @@ -298,16 +337,24 @@ export default class WebRTC } public async eventNogationNeeded() { - let offer = await this.rtc.createOffer({ - iceRestart: true, - offerToReceiveAudio: true, - offerToReceiveVideo: true - }); - await this.rtc.setLocalDescription(offer); - this.send({ - type: 'offer', - value: offer - }); + try{ + this.makingOffer = true; + let offer = await this.rtc.createOffer({ + iceRestart: true, + offerToReceiveAudio: true, + offerToReceiveVideo: true + }); + await this.rtc.setLocalDescription(offer); + this.send({ + type: 'offer', + value: offer + }); + }catch(error){ + console.error(`Nogation Error:`, error) + } + finally{ + this.makingOffer = false; + } } public eventSignalingState() {