- From: Jan-Ivar Bruaroey via GitHub <sysbot+gh@w3.org>
- Date: Thu, 09 Jul 2020 15:21:50 +0000
- To: public-webrtc@w3.org
jan-ivar has just created a new issue for https://github.com/w3c/webrtc-extensions: == When is negotiation complete? == A problem arose while writing [perfect negotiation](https://w3c.github.io/webrtc-pc/#perfect-negotiation-example) [wpt tests](https://phabricator.services.mozilla.com/D66817#C2294894NL1): When is negotiation complete? You know, something like: ```js const transceiver = pc.addTransceiver("video"); await /* some event or promise */ assert_equals(transceiver.currentDirection, "sendonly", "negotiates to sendonly"); ``` Naively, one might think this works: ```js const state = (pc, s) => new Promise(r => pc.onsignalingstatechange = () => pc.signalingState == s && r()); const transceiver = pc.addTransceiver("video"); await state(pc, "stable"); assert_equals(transceiver.currentDirection, "sendonly", "negotiates to sendonly"); ``` Unfortunately, outside a lab, →`"stable"` might come from rollback, or answering a remote offer. Or even from _juuust_ missing our own negotiation train triggered by a previous local action. This leaves us stuck writing action-specific spin-tests, not a great API: ```js const transceiver = pc.addTransceiver("video"); while (!transceiver.currentDirection) { await state(pc, "stable"); } assert_true(true, "we didn't time out!"); assert_equals(transceiver.currentDirection, "sendonly", "negotiates to sendonly"); ``` So I tried solving this in JS by dispatching my own `negotiated` event in SRD(answer): ```js // - The perfect negotiation logic, separated from the rest of the application --- signaling.onmessage = async ({data: {description, candidate}}) => { try { if (description) { const offerCollision = description.type == "offer" && (makingOffer || pc.signalingState != "stable"); ignoreOffer = !polite && offerCollision; if (ignoreOffer) { return; } await pc.setRemoteDescription(description); // SRD rolls back as needed if (description.type == "offer") { await pc.setLocalDescription(); signaling.send({description: pc.localDescription}); } else { pc.dispatchEvent(new Event("negotiated")); // <--- here! } } else if (candidate) { ``` This avoids rollbacks and remote offers, but we _still_ have to account for just missing a local train: ```js const negotiated = pc => new Promise(r => pc.addEventListener("negotiated", r, {once: true}); const transceiver = pc.addTransceiver("video"); await negotiated(pc); if (!transceiver.currentDirection) { await negotiated(pc); // catch the next train } assert_equals(transceiver.currentDirection, "sendonly", "We're negotiated!"); ``` This avoids the dreaded `while` loop. But who's going to remember this over some intermittent? Please view or discuss this issue at https://github.com/w3c/webrtc-extensions/issues/45 using your GitHub account
Received on Thursday, 9 July 2020 15:21:52 UTC