WebRTC “Perfect Renegotiation” collision problem

I have a chat application which I want to extend with voice and video chat capabilities. It is basically done but I can’t seem to fix a problem with renegotiation.

I used the Mozilla docs about Perfect Negotiation and it still gets into soft-locks which I can’t seem to fix.

The Problem:

  • User A sends a renegotiation Offer
  • User B receives Offer
  • User B sends Answer
  • User B sends Renegotiation Offer immediately after the Answer
  • User A receives Answer and starts processing…
  • User A receives Offer and drops it because Answer is still processing
  • User A Finishes processing Answer
  • User B is stuck in waiting for Answer

Code that handles SDP-s:

public async createSDP() {
  await this.rtcPeerConnection.setLocalDescription();
  const sdp = this.rtcPeerConnection.localDescription;
  if (!sdp) return false;
  return sdp;
}

public async readSDP(sdp: any) {
  let ignoreOffer = false;
  try {
    const offerCollision =
      sdp.type === "offer" &&
      (this.makingOffer || this.rtcPeerConnection.signalingState !== "stable");
    ignoreOffer = !this.polite && offerCollision;
    if (ignoreOffer) {
      return false;
    }
    await this.rtcPeerConnection.setRemoteDescription(sdp);
    return true;
  } catch (err) {
    console.error(err);
  }
  return false;
}

I tried adding an iteration if ignoreOffer is true, to try 3 times with gradually encreasing delays to process the offer that would be dropped. I expected it to read it properly and send out an Answer, but got an error of “invalid order of m-lines”

I tried adding a timeout after sending out a renegotiation offer to check if after ~20 seconds signalingState is still in “have-local-offer”, got the same “invalid order of m-lines” error.