Subject: [quicwg/base-drafts] Greasing for Unidirectional Stream Types (#1490)

From: Mike Bishop <[email-masked]>
Date: Wed, 27 Jun 2018 17:03:55 +0000 (UTC)

#1446 added greasing values for various elements in HTTP/QUIC (settings, frame types, etc.) where the peer is required to ignore unknown values.  #1359 added unidirectional stream types, and there was a suggestion from @LPardue to grease those as well.

However, given that an unknown stream type is defined to be an error (and implementations are cautioned that peers can promote these errors to connection errors), sending grease values and mandating that receivers not treat them any differently will be a bit fragile.

Options I see:
- Prohibit unknown unidirectional streams from being treated as an error at all; ignore them.  Unfortunate for wasted data transfer; you really want a STOP_SENDING here.  This is also an attack vector.  And if you expect some valid unidirectional streams, you can't just clamp down on the number of allowed unidirectional streams using MAX_STREAM_ID.
- Prohibit unknown unidirectional streams from being treated as a connection error.  This seems an unfortunate exception case, especially since it opens the same attack vector as the previous.
- Special-case the grease types on the receiver, which rather defeats the purpose of having grease at all.
- Don't grease these.

Unless someone has a bright idea, I'm currently inclined toward the last option.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 27 Jun 2018 10:16:19 -0700

To ask a silly question: ow is receiving and unknown frame type on a push promise stream any different to receiving a push promise frame on an unknown stream type?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400762114

---

From: Mike Bishop <[email-masked]>
Date: Wed, 27 Jun 2018 10:43:04 -0700

Because with an unknown stream type, you don't even know that it's using frames -- it's just a bytestream about which you have no context.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400770394

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 27 Jun 2018 10:49:24 -0700

Understood. 

So isn't the point of greasing to make it impractical to write code for the special cases while ignoring true extension?

Greased streams would not be expected to deliver any subsequent data. Could you specify for greased stream types to be reset by the sender? 

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400772215

---

From: Mike Bishop <[email-masked]>
Date: Wed, 27 Jun 2018 10:54:55 -0700

The point is to make it impractical to be intolerant of unknown values when the specified behavior is to ignore them and move on (frame types, settings, TLS extensions, etc.).  But here, we've specified intolerance of unknown values as the correct behavior.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400773933

---

From: Martin Thomson <[email-masked]>
Date: Wed, 27 Jun 2018 14:47:59 -0700

If we say that unknown stream types cause the stream to be ignored in total (w/ STOP_SENDING ideally), then frames and unknown stream types are equivalent.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400839895

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 27 Jun 2018 15:34:17 -0700

So taking Martin's point in mind, what about something like:

_Implementations SHOULD NOT send stream types that the peer is not already known to support. Recipients of unknown stream types MUST send a STOP_SENDING frame with an error code of HTTP_UNKNOWN_STREAM_TYPE. Greased stream types are always classed as unknown and unsupported._

This requires a receiver to only parse the first 8 bytes of a stream.

It would help to provide some guidance for HTTP/QUIC extension authors to make it clear that a mechanism (e.g. SETTINGS) for negotiating extension stream types is required, and that failure to do this will invoke the ignorant behaviour.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400850963

---

From: Kazuho Oku <[email-masked]>
Date: Wed, 27 Jun 2018 17:13:55 -0700

@LPardue 
> _Implementations SHOULD NOT send stream types that the peer is not already known to support. Recipients of unknown stream types MUST send a STOP_SENDING frame with an error code of HTTP_UNKNOWN_STR…

Sounds good to me. Though I might prefer using "MAY" instead of "MUST" for if STOP_SENDING should be sent. For example, if the entire flow of the unidirectional stream (i.e. from the beginning of the stream to EOS) fits in a single packet, I do not think that there is a strong reason to require the peer to send STOP_SENDING.

> It would help to provide some guidance for HTTP/QUIC extension authors to make it clear that a mechanism (e.g. SETTINGS) for negotiating extension stream types is required,

I am not sure if such requirement is necessary. In fact, I would argue that it would be beneficial allow extended stream types to be sent without negotiation.

For example, a server might send additional certificates before receiving the client's SETTINGS frame (i.e. by using in it's 0.5 RTT window, which would be idle time). Or, a client might send a cache digest before observing the server's SETTINGS frame.

To generalize the concept, I would argue that both frames and streams defined as extensions should be allowed to be sent without negotiation. The only differences are that streams can be reset by peer (by using STOP_SENDING), and that they would not suffer from HoLB (therefore it is sensible to use unidirectional streams with extended types for sending information that would have been exchanged using stream 0 of HTTP/2).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400869779

---

From: Mike Bishop <[email-masked]>
Date: Wed, 27 Jun 2018 17:17:17 -0700

I think that's reasonable.  Another point where I wish we had an API / interface specification for the transport:  I need a verb that clearly means "STOP_SENDING if the stream hasn't yet closed, but do nothing if it has."  Stating in the HTTP document that a particular QUIC frame needs to be generated is not good encapsulation.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400870272

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 27 Jun 2018 17:37:48 -0700

"ignore unicast stream reception"?

It could be argued that encapsulation is ready broken by in the document by the text that refers to generating RST_STREAM frames.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400873827

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 27 Jun 2018 17:53:17 -0700

@kazuho thanks for your thoughts.

I tend to agree about being less strict on negotiation but I think we are retreading some ground on SETTINGS HoL. 

A middle ground might say that stream extensions should be aware of the trade off in committing resource to data that could be ignored by the peer vs. negotiating at the cost of latency.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400876342

---

From: Kazuho Oku <[email-masked]>
Date: Wed, 27 Jun 2018 18:16:39 -0700

> A middle ground might say that stream extensions should be aware of the trade off in committing resource to data that could be ignored by the peer vs. negotiating at the cost of latency.

Yes. IMO, having a statement that suggests extensions to consider using SETTINGS for negotiation is a good idea, and that is what we have in https://httpwg.org/specs/rfc7540.html#extensibility for frames. My point is that there is no need to switch to a different approach for frames *and unidirectional streams* to be defined in hq.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400879652

---

From: Lucas Pardue <[email-masked]>
Date: Wed, 27 Jun 2018 18:38:53 -0700

Agreed.

On a tangent, on reading that H2 section, it strikes me that we may want some text that accommodates connection migration (or at least clarifies rules). Are SETTINGS transferable or do they need to be renegotiated? What about QPACK?

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400883364

---

From: Martin Thomson <[email-masked]>
Date: Wed, 27 Jun 2018 19:02:21 -0700

@LPardue, settings are protocol-specific.  That there is some apparent similarity is to ease the conceptual transition for people reading the spec, nothing more.  You shouldn't be able to take h2 settings from a server and expect the hq endpoint to respect them.  That is one reason why priming 0-RTT cross protocol is fraught.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400886964

---

From: Kazuho Oku <[email-masked]>
Date: Wed, 27 Jun 2018 19:04:06 -0700

> On a tangent, on reading that H2 section, it strikes me that we may want some text that accommodates connection migration (or at least clarifies rules). Are SETTINGS transferable or do they need to…

Migration is something that happens mid-connection, and there is no need to renegotiate.

If you are concerned about connection reestablishment, I think the required behavior is stated clearly in [section 4.2.6.3](https://quicwg.org/base-drafts/draft-ietf-quic-http.html#rfc.section.4.2.6.3).

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/issues/1490#issuecomment-400887249