Re: notes on http2 draft

Excellent review... a few brief responses...

On Tue, May 21, 2013 at 8:01 AM, Patrick McManus <pmcmanus@mozilla.com> wrote:
>[snip]
> 1.2
>
> message:A complete sequence of frames.
>
> I'm not sure that does a lot for me as a definition. It should at least say
> something about them sharing the same stream ID.. or am I describing a
> stream? Is a message a unidirectional stream? as I said.. it doesn't do a
> lot as a definition. The document refers to "window update messages" and
> "goaway messages" but I think it means frames in those cases.. it also talks
> about "receiver of a message" sending WINDOW_UPDATE which makes it sound
> like a message is any data frame (not the complete sequence of them)... and
> then again we also talk about "HTTP Messages" which are something distinct..
>
> I suggest we scrub the term message from the document (and this section)
> except when it refers to HTTP messages.
>

Agree. The term "message" used in the framing layer is confusing and
meaningless and ought to be reserved specifically for the HTTP
semantic layer discussion.

>[snip[
> Implementations MUST ignore unsupported and unrecognized frame types.
>
> I think invalid frame types should be session errors of the MUST NOT send
> variety. I know the list has been talking about this lately and I haven't
> had an opportunity to chime in. Be liberal in what you receive is overrated
> and often fraught with security problems - we can rev the protocol with ALPN
> at Internet scale in order to sanely guide extensions as needed. I know
> design committees love open ended extensions so my view won't pervail, but
> this is exactly the kind of thing that leads to interop doom.
>

There are generally three categories here depending on how you
characterize the framing layer...

1. Malformed/Invalid Frames ... which yes, ought to be rejected with a
connection error
2. Unknown protocol frames (hop-by-hop frames). Given that these may
or may not affect the connection state, it would likely be better to
reject these rather than silently ignore them and go with Roberto's
option of requiring a new protocol version id when they're used.
3. Unknown data frames (end-to-end frames). These do not affect the
connection state at all. These are safe for an endpoint to ignore and
pass thru with the assumption that the a higher layer will deal with
them.

Right now, the spec draws absolutely no distinction between 2 and 3
and just says to ignore everything you don't understand.

Alternatively, if you view the framing layer as being essentially a
black box to the higher application levels and require that any and
all application data be transferred using DATA frames (ruling out the
use of framing for anything other than hop-by-hop protocol level
stuff) then I agree that MUST NOT send is significantly safer than
MUST IGNORE.

> 3.3.2
>
> Implementations with limited resources might not be capable of processing
> large frame sizes. Such implementations MAY choose to place additional
> limits on the maximum frame size. However, all implementations MUST be
> capable of receiving and processing frames containing at least 8192 octets
> of data.
>
> I'm pretty confident we are just inventing complexity here for no good
> reason. The tiny universe of implementations that can cope with 8KB but not
> 64KB is not worth the complexity. One of the advantages of going with a 16
> bit frame size is that it should be small enough for everything to handle
> it.
>
> If there is reason to believe 64KB is too big for a population large enough
> to care about (remembering of course that HTTP/2 is not a ticket to Internet
> admission - if you're really so small that you can't read 64KB frames the
> muxing of HTTP/2 is going to be a real challenge too; you're probably best
> left using a different protocol. Just coap :)), then let's lower the max
> frame size instead of reinventing Path MTU Discovery complexity. But I think
> we can just drop this section and require everyone to deal with 64KB.
>

After experimenting with this further, I'm +1 on this for now but I
want to see a lot more experimentation with flow control. Any
configurable limits that we place on frame size is going to introduce
a Path MTU problem and could force "reframing" to occur at various
points in the message flow.

> 3.4
>
> A "stream" is an independent, bi-directional sequence of frames
>
> Due to the (expected) compression requirements the frames aren't really
> independent of other streams. I know this mistake comes up pretty commonly
> on spdy-dev from new implementers of that protocol, so it probably helps to
> avoid saying independent here. (section 5.3 does it too).
>

Well... streams themselves are independent of one another, it's the
serialization of the individual frames that is dependent on a shared
context state. I agree that this ought to be explained better.

> 3.4.1
>
> Rather, new streams are established by sending a frame whose stream
> identifier field references a previously unused stream identifier.
>
> That's a little too loose. Streams are created by the client through
> HEADERS+PRIORITY (4.2.2) and by the server through PUSH_PROMISE. The text
> as-is makes it sound more free flowing than that.
>
> The identifier of a newly established stream MUST be numerically greater
> than all previously established streams from that endpoint within the
> HTTP/2.0 connection, unless the identifier has been reserved using a
> PUSH_PROMISE (Section 3.8.5) frame.
>
> Likewise, PUSH_PROMISE really creates the stream (4.3.1) from the server.. I
> don't see a reason for the caveat here.
>

This is up for debate, apparently.

I agree with you that H, H+P and P_P ought to be the only ways to
create new streams but others (such as Roberto) have argued that any
time you send any frame with an unused stream identifier, it
initializes that stream.

>
> 3.4.2
>
> I thought one of the takeaways at Tokyo was to define a change-priority
> frame.. Can we do that now? is the intention to use a H+P without any
> headers at any point in the stream? If so, I think that should be called out
> so that server implementation's don't freak out at seeing H+P at strange
> points in the stream.. and I think there is some language in 4.2.2 that
> could be interpreted as meaning certain colon headers are required to be in
> every H+P
>

Truthfully, I'd rather see us define a distinct PRIORITY frame and
remove H+P from the picture altogether.

To create the stream, I would send a HEADERS frame. Then to set the
priority for the stream, I would send a separate PRIORITY frame. This
would resolve any possible ambiguity and confusion with regards to
when to use HEADERS vs HEADERS+PRIORITIES vs any new CHANGE-PRIORITY
frame.

Yes, I get the argument that sending HEADERS+PRIORITY vs. HEADERS and
a PRIORITY frame allows creation of the stream and setting of the
priority in a single operation, but the added complexity of having
separate HEADERS, HEADERS+PRIORITY, CHANGE-PRIORITY frames just
doesn't seem like a worth while tradeoff to me.

>
> 3.8.5
>
> The PUSH_PROMISE frame (type=0x5) is used to notify the peer endpoint in
> advance of streams the sender intends to initiate.
>
> I think I must have missed something on list about this. Why is the language
> here general (peer, sender).. why define this so that clients can generate
> PUSH_PROMISE ?
>

This also appears to be up for debate. There is a theoretical use case
for clients sending PUSH_PROMISE frames and sending multiple
associated streams to a server.. but, it's purely theoretical. For
now, I think using more specific language that restricts PUSH_PROMISE
use to the server is more than appropriate.

>[snip]
> 4.2.2
>
> User-agents MUST support gzip compression. Regardless of the Accept-Encoding
> sent by the user-agent, the server may always send content encoded with gzip
> or deflate encoding. [rfc.comment.11: Still valid?]
>
> I support that still being valid. This is an important performance property
> to rely on.
>

Actually, this bit needs to be clarified, and I believe we ought to be
able to simplify this significantly.

For instance, for all DATA frames, we can introduce a GZIP flag (0x2)
that indicates that the data contained in that frame has been
compressed. Doing so really eliminates the need to specify anything at
the HTTP semantic layer and eliminates the need for the
accept-/transfer-/content-encoding header mechanism completely.

- James

Received on Tuesday, 21 May 2013 16:00:49 UTC