[webrtc-pc] A simpler non-glare-prone setLocalDescription() (#2165)

jan-ivar has just created a new issue for https://github.com/w3c/webrtc-pc:

== A simpler non-glare-prone setLocalDescription() ==
In [my latest blog](https://blog.mozilla.org/webrtc/perfect-negotiation-in-webrtc/) on *"Perfect negotiation in WebRTC"*, I discovered that most `negotiationneeded` code is glare-prone. E.g.
```js
pc.onnegotiationneeded = async () => {
  await pc.setLocalDescription(await pc.createOffer());
  io.send({desc: pc.localDescription});
}
```
In short, *createOffer* is asynchronous and takes time, so a remote offer may race us here and sometimes take us out of `"stable"` to `"have-remote-offer"`, beating our call to *setLocalDescription*, causing it to fail. To safeguard against this requires testing against `"stable"` right beforehand:
```js
pc.onnegotiationneeded = async () => {
  const offer = await pc.createOffer();
  if (pc.signalingState != "stable") return;
  await pc.setLocalDescription(offer);
  io.send({desc: pc.localDescription});
}
```
That's a bit much, so I'm proposing we allow a simpler version that's glare-safe:
```js
pc.onnegotiationneeded = async () => io.send({desc: await pc.setLocalDescription()});
```

Basically, allow *setLocalDescription* without argument, and treat it as follows:
 1. Default *type* to `pc.signalingState.includes("offer")? "answer" : "offer"`.
 2. if [[LastOffer]](https://w3c.github.io/webrtc-pc/#dfn-lastoffer)/[[LastAnswer](https://w3c.github.io/webrtc-pc/#dfn-lastanswer)] is `""`, implicitly invoke *createOffer()*/*createAnswer()* respectively.
 3. Resolve with `pc.localDescription`.

This is glare-safe because the peer connection's [operations queue](https://w3c.github.io/webrtc-pc/#dfn-operations-queue) does not allow an opportunity for JS to insert any method calls before the signaling state is changed (on success).

Fun fact: the sdp passed to *setLocalDescription()* is already unused; a ritual:
```js
await pc.setLocalDescription(await pc.createOffer());
```
...is already equivalent to (and no more flexible than):
```js
await pc.createOffer(); await pc.setLocalDescription({type: "offer"});
```
So this change is smaller than it might seem.

This would be fully backwards compatible; *setRemoteDescription()* would remain unchanged.


Please view or discuss this issue at https://github.com/w3c/webrtc-pc/issues/2165 using your GitHub account

Received on Sunday, 7 April 2019 21:09:36 UTC