In WebRTC, both peers send an offer at the same moment after each adds a screen share; what is glare, and how does perfect negotiation resolve it?
answer
- one outstanding offer per session
- an offer meets have-local-offer
- roles fixed before the call
- one yields, one ignores
- rollback back to stable
basics
~20 sGlare is receiving an offer while your own is still unanswered. Perfect negotiation, the W3C WebRTC pattern, pre-assigns roles: the impolite peer ignores the colliding offer, while the polite peer rolls its own offer back, answers, and negotiates its own change afterwards.
solid answer
~50 sRFC 3264 allows one outstanding offer per session; receiving an offer after sending your own, before its answer, is glare. JSEP leaves glare to the application, and a remote offer is not valid in `have-local-offer`. The W3C WebRTC 1.0 specification recommends **perfect negotiation**: both peers run the same code (`negotiationneeded` triggers an argument-free `setLocalDescription()` and a send), but one is designated polite and the other impolite in advance. An incoming offer collides if the peer is making an offer or is not `stable`. The impolite peer ignores it and suppresses errors from that offer's candidates. The polite peer rolls back its own offer, which `setRemoteDescription` does implicitly (or explicitly with a `rollback` description), and answers. Its change is not lost: the incoming offer may already carry it, and anything still unnegotiated fires `negotiationneeded` again once it is back in `stable`.
go deeper
Recall that glare means two offers crossing in flight, and that WebRTC leaves resolving it to the application rather than the browser API.
Explain rollback: what it discards, which states allow it, and why the signalling state must return to stable before another offer.
Show you can implement perfect negotiation correctly: fixed roles, collision detection, implicit rollback on the polite side, ignored-offer candidate errors on the impolite side.
Weigh symmetric negotiation against a single designated offerer for a product's call model, considering extra round trips, code complexity and gateways that cannot roll back.
## Where glare comes from The offer/answer model (RFC 3264) lets either agent send a new offer at any time, but never while one is outstanding: an agent MUST NOT offer while it owes an answer or awaits one. If an agent "receives an offer after having sent one, but before receiving an answer to it", that is **glare**. The term is borrowed from telephone switching, where two switches seize the same trunk at once. In WebRTC this happens naturally once both sides can change the call. Both users click "share screen" within the same round trip; both peers fire `negotiationneeded`, apply their own offer (`have-local-offer`) and send it. Each then receives an offer it cannot apply as is. JSEP (RFC 9429) deliberately leaves glare handling to the application, along with every other signalling concern. ## Rollback, the primitive underneath JSEP gives the application one tool: a session description of type **`rollback`** with empty contents. Applying it abandons the current offer/answer transaction and returns the state to `stable`. Its rules, from RFC 9429: - A rollback is allowed in any state **except `stable`**. In `stable` it is an error, so once an answerer has applied its own answer that exchange cannot be rolled back. - It has the same effect through `setLocalDescription` or `setRemoteDescription`. - The pending local and remote descriptions become null, and resources or candidates allocated for the abandoned description are discarded. - Transceivers created by applying a remote offer that is rolled back are stopped and removed, **unless** a track was attached to them with `addTrack`. The W3C API also performs rollback **implicitly**. If `setRemoteDescription` receives an offer that is invalid for the current state, it first sets a local `{type: "rollback"}` and then applies the offer. ## Perfect negotiation, step by step The W3C WebRTC 1.0 specification presents perfect negotiation as a recommended pattern, with a worked example. It is application code, not a protocol: the two peers never negotiate it, they simply run matching logic. 1. **Assign roles.** One peer is *polite*, the other *impolite*. How they are chosen (caller and callee, or the signalling server deciding) is up to the application; the specification's example simply assumes a boolean. 2. **Offer whenever needed.** On `negotiationneeded`, record that an offer is being made, call `setLocalDescription()` with no argument, send the result, then clear the record. 3. **Detect a collision.** When a description arrives, it is an offer collision if it is an offer and this peer is either making an offer or not in `stable`. The example also treats a peer that is applying a remote answer as ready, because it will be `stable` by the time the queued offer runs. 4. **Impolite: ignore.** It drops the colliding offer and remembers that it did, so it can suppress the `addIceCandidate` errors caused by that offer's trickled candidates. 5. **Polite: yield.** It calls `setRemoteDescription(offer)`, which rolls its own offer back implicitly, then `setLocalDescription()` to create and apply the answer, and sends it. 6. **Re-offer if still needed.** Applying the remote offer may already pair the polite peer's screen-share transceiver, created by `addTrack` and disassociated by the rollback, with the impolite peer's new video section. Whatever is still unnegotiated when the polite peer reaches `stable` sets the negotiation-needed flag again, so `negotiationneeded` fires and it sends its own offer, now with no collision. | | Polite peer | Impolite peer | |---|---|---| | On a colliding offer | rolls back its own offer, then answers | ignores the incoming offer | | Its own pending change | carried by the answer, or offered again once `stable` | proceeds and is answered | | Candidate errors from the ignored offer | not applicable | suppressed | The example uses the argument-free `setLocalDescription()` and the implicit rollback in `setRemoteDescription` on purpose. Each is a single call, so no other signalling message can be processed between steps. ## Why not let one side always offer? A simpler scheme makes only one peer ever create offers; the other asks it, by an application message, to do so. That avoids glare too, but every change on the non-offering side costs an extra round trip and a second code path. The specification notes that perfect negotiation "lets applications operate on both peer connection objects simultaneously without risk of glare", with the negotiation logic kept separate from the rest of the application. ## Common misreadings - Getting the roles backwards. The *polite* peer yields; the impolite one keeps its offer. - Expecting rollback to undo a completed exchange. It cancels only a pending one. - Treating perfect negotiation as an IETF mechanism visible on the wire. It is a client-side pattern; each peer sees ordinary offers and answers. - Assuming the polite peer's change is lost. It is either carried by the answer or offered again once the polite peer reaches `stable`.
- In WebRTC perfect negotiation, why must the impolite peer suppress some addIceCandidate errors?Its `RTCPeerConnection` never applied the offer it ignored, so trickled candidates belonging to that offer refer to a remote description it does not have, and `addIceCandidate` rejects them. The W3C example swallows those errors only while it is ignoring an offer, and rethrows them otherwise so real failures still surface.
- In WebRTC, can an answerer roll back an exchange after applying its own answer?No. RFC 9429 allows rollback only outside the `stable` state, and applying the answer returns the answerer to `stable`; a rollback there is an error. Rollback cancels a pending proposal. To undo a completed change, a peer makes a new offer that reverses it.
- Why does the W3C perfect-negotiation example use setLocalDescription with no argument?Because it creates and applies the right description in one call, an offer or an answer depending on state. With separate `createOffer` and `setLocalDescription` calls, an incoming offer could be processed between them and change the state the draft was made for. The single call removes that race.
Two people reach a narrow doorway at the same moment. If both step back, or both push forward, nobody gets through. Agree beforehand that one of them always steps back: the polite one yields, lets the other through, and then walks through next.
saying these in an interview costs you the question
- Glare means both peers sent an answer at the same time.
- The polite peer ignores the incoming offer and keeps its own.
- Rollback can undo an answer the answerer already applied.
- Perfect negotiation is an IETF protocol both ends must agree on.
- After a rollback the polite peer's screen share is dropped for good.