Subject: [Wish] Request ordering

From: Adam Roach <[email-masked]>
Date: Fri, 12 Nov 2021 11:28:57 -0600

Hi! In today's meeting, there was a brief discussion of ensuring WHIP 
requests can be processed in order on the server, even in the face of 
connection disruptions (as will frequently be the case when ICE restart 
is required).

The document that describes the general mechanisms for handling this in 
HTTP is RFC 7232: https://datatracker.ietf.org/doc/html/rfc7232

While there are multiple potential mechanisms described in RFC 7232 for 
ensuring that requests are handled in a consistent fashion, my preferred 
approach would be the use of ETags. While the RFC describes this in 
significantly more detail, the rough sketch is:

  * The server will send an "ETag" header field in all responses. The
    "ETag" is an opaque representation of the server state. you can
    basically think of it like a version number for resource state,
    except that its format is opaque to the client.
  * Whenever clients send requests to change the WHIP session state
    (aside from creating a new session), they include an "If-Match"
    header field containing the etag corresponding to the most recent
    server state they know about. If the etag in the "If-Match" header
    field doesn't match the state identifier the server is expecting,
    then the request is rejected

This does mean that, in general, clients will need to wait for one 
request to conclude before sending the next one, since they have to wait 
for the etag to know what to send in the next request's "If-Match" 
header field.

There /might/ be some clever tricks we can play with the 
"If-Unmodified-Since" header field (instead of using etags) to get 
around this property, but those are likely to be complex to reason 
about, and fragile to implement (especially considering both clock skew 
and the low resolution of the HTTP "Date" header field).

/a

---

From: Sergio Garcia Murillo <[email-masked]>
Date: Fri, 12 Nov 2021 19:07:28 +0100

Hi Adam,

So the idea is that the server sets a different Etag on the initial http
post and in each http patch for ice restarts and the client sends the
If-Match with the value of the latest Etag received, right?

The client would have to queue the candidates gathered after an ice restart
until the http patch response for the restart is received, but this is
something that the clients need to do already for the initial POST.

Also, in order to simplify the implementation on the server side, the Etag
could be the value of the server side ufrag, what do you think?

Best regards
Sergio

El vie, 12 nov 2021 a las 18:29, Adam Roach (<[email-masked]>) escribió:

> --
> Wish mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/wish
>

---

From: Juliusz Chroboczek <[email-masked]>
Date: Fri, 12 Nov 2021 20:03:46 +0100

>    except that its format is opaque to the client.

Does the ETag change after every new ICE candidate?  If so, then the
client cannot stream ICE candidates even when the UFrag doesn't change.
(This would mean that sending an initial offer plus four ICE candidates
costs an extra 5*RTT.)  The client would then need to have some logic for
batching ICE candidates, which IMHO is at odds with our desire for
simplicity on the client side.

If the ETag remains constant between ICE restarts, then it's essentially
en encoding of the ufrag, no?

-- Juliusz

---

From: Adam Roach <[email-masked]>
Date: Fri, 12 Nov 2021 19:30:58 -0600

On 11/12/21 12:07, Sergio Garcia Murillo wrote:
> Hi Adam,
>
> So the idea is that the server sets a different Etag on the initial 
> http post and in each http patch for ice restarts and the client sends 
> the If-Match with the value of the latest Etag received, right?

That's the idea, yes.

> The client would have to queue the candidates gathered after an ice 
> restart until the http patch response for the restart is received, but 
> this is something that the clients need to do already for the initial 
> POST.

right.

> Also, in order to simplify the implementation on the server side, the 
> Etag could be the value of the server side ufrag, what do you think?

I have a few different thoughts here.

The first is that we need to maintain the properties of ETags as defined 
in RFC 7232 -- meaning that we can't impose any protocol-level structure 
on them. That's probably what you mean ("is the server allowed to do 
this?") rather than asking if we can bake this kind of equivalency into 
the protocol, but I want to make sure everyone reading your suggestion 
is on the same page.

So keeping that in mind, I think your question resolves to "can we use 
the same ETag for any given round of ICE processing, and change it only 
for the next one?" I hadn't thought of that, and I /think/ the answer is 
yes. My understanding of the need for "weak ETags" has always been a bit 
fuzzy, but I think you're describing exactly the kind of use case that 
is described for them:

>     [A] "weak validator" is representation metadata that might
>     not change for every change to the representation data.  This
>     weakness might be due to ... a desire of the resource
>     owner to group representations by some self-determined set of
>     equivalency rather than unique sequences of data.  An origin server
>     SHOULD change a weak entity-tag whenever it considers prior
>     representations to be unacceptable as a substitute for the current
>     representation.

This seems to match: as long as we want the ETag to match "session 
state", independent of the state of ICE candidate transfer, then using a 
single weak ETag would seem to get us there. I'd want to run this by a 
serious HTTP expert before assuming it's okay (two potential issues: I 
may be misunderstanding the behavior of weak ETags, and it may not be 
considered good form for an HTTP-using protocol to specify how weak tags 
map to resource state). But if this is an okay way to do things, then I 
think it solves our ordering problem in a fairly elegant way.

/a

---

From: Adam Roach <[email-masked]>
Date: Fri, 12 Nov 2021 19:33:12 -0600

> simplicity on the client side.

As Sergio points out, you'll need to implement batching /anyway/, since 
you can't trickle your first candidate until you get a reply to the 
first POST (since that reply contains the URL to send the trickled 
candidates to).

Regarding the ETag behavior -- see my reply to Sergio's email for a 
treatment that might make all of this a bit easier.

/a