W3C home > Mailing lists > Public > ietf-http-wg@w3.org > July to September 2014

Re: h2 frame layout

From: Matthew Kerwin <matthew@kerwin.net.au>
Date: Mon, 1 Sep 2014 11:57:48 +1000
Message-ID: <CACweHNCZGnDuFkGtkSv3i1yM-qiEjZ4ZrPCdf2g-VX8YEcjsXQ@mail.gmail.com>
To: Greg Wilkins <gregw@intalio.com>
Cc: "Roy T. Fielding" <fielding@gbiv.com>, HTTP Working Group <ietf-http-wg@w3.org>
On 1 September 2014 10:34, Greg Wilkins <gregw@intalio.com> wrote:

>
> On 1 September 2014 09:34, Matthew Kerwin <matthew@kerwin.net.au> wrote:
>
>> Repeating myself again, but: what do you think of an option C: remove
>> Flags from the general frame header, and add individual Flags fields to
>> whichever frame types require them?
>
>
> Matthew,   in general I think the framing layer should only know about
> framing concerns and should be neutral towards any semantics conveyed in
> the frame payloads.   So in principal, yes I agree than general flags (and
> probably frame types other than those needed by framing) can easily be put
> into the payload.
>
> However, END_STREAM is a-priori a framing concern, so I don't think it
> should be moved to the frame payload or be a function of frame type.   I
> would have preferred the framing layer was designed without HTTP semantic
> knowledge and was able to transport arbitrary bidirection flow controlled
> streams, perhaps with segments defined so that
> flushing/forwarding/segmentation behaviour can be guaranteed to a level
> needed.        Other than what is required to achieve that, I see no reason
> that the framing layer should know any more about what it is transporting,
> even to the extent that it really should not know the difference between a
> header and data frame.​
>
>
tl;dr: see the diagram below

Allow me to try to reconstruct what you're saying via my thought processes:

If the framing machine were frame-type-agnostic, all frame types could
carry the END_STREAM flag, but it would only have meaning when associated
with a non-zero stream id.

Of those types that can have a non-zero stream id:
* DATA and HEADERS define an END_STREAM flag.
* PRIORITY, RST_STREAM, PUSH_PROMISE and WINDOW_UPDATE don't.
* CONTINUATION is snafu so I'm not touching it

Of those that don't define the flag, it could be argued that it's because
it doesn't make much sense; RST_STREAM can't *not* end the stream, and a
WINDOW_UPDATE or PP that does is silly. Maybe there's some small value in
the case of PRIORITY, but it still smells a bit silly. So in theory we
could reword the spec to say: the flag is defined and MUST be zero -- which
may add more validation requirements to the receivers, but it doesn't
change the general thrust of framing/streams.

Thus, at one level of thinking we can say that all frame types that have a
non-zero stream id define the END_STREAM flag, so we're on our way to
writing a generic ​framer that doesn't need to delve too deeply into the
types.

Except that SETTINGS and PING have an ACK flag that occupies the same bit
as the END_STREAM flag. So the framer has to inspect either the frame type
or maybe the stream id before it can interpret the flag. So it's not
generic.

To move things forward we could borrow from Roy's option B and move the
END_STREAM bit from Flags to somewhere else, and then use my option C and
move the remaining flags to the payload. Since both END_STREAM and Stream
Identifier are stream-related parameters, and we happen to have a reserved
bit sitting right at the top of the stream identifier, why not shove
END_STREAM there?

I'll note that our generic framer may still have some responsibility in
inspecting END_HEADERS and barfing on bad CONTINUATIONing, but that whole
mess is, as I said earlier, AFU, so whatever. But at least with this
proposal, continuation becomes the only exception to an otherwise fairly
sensible system.

tl;dr:

```
  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |   Type (8)    |                 Length (24)                   |
 +-+-------------+-----------------------------------------------+
 |E|                 Stream Identifier (31)                      |
 +=+=============================================================+
 |                   Frame Payload (0...)                      ...
 +---------------------------------------------------------------+
                            Frame Layout

The fields of the frame header are defined as:

Length:
   The length of the frame payload expressed as an unsigned 24-bit
   integer. Values greater than 214 (16,384) MUST NOT be sent unless
   the receiver has set a larger value for SETTINGS_MAX_FRAME_SIZE.

   The 8 octets of the frame header are not included in this value.

Type:
   The 8-bit type of the frame. The frame type determines the format
   and semantics of the frame. Implementations MUST ignore and discard
   any frame that has a type that is unknown.

E:
   This bit being set indicates that this frame is the last that the
   endpoint will send for the identified stream. Setting this flag
   causes the stream to enter one of the "half closed" states or the
   "closed" state (Section 5.1).

   This bit MUST remain unset (0) when sending unless explicitly
   allowed by the frame type definition.

Stream Identifier:
   A 31-bit stream identifier (see Section 5.1.1). The value 0 is
   reserved for frames that are associated with the connection as a
   whole as opposed to an individual stream.

The structure and content of the frame payload is dependent entirely
on the frame type.
```

...and move the frame field (minus END_STREAM) to the payload, if and when
it's required.

-- 
  Matthew Kerwin
  http://matthew.kerwin.net.au/
Received on Monday, 1 September 2014 01:58:17 UTC

This archive was generated by hypermail 2.3.1 : Wednesday, 30 March 2016 09:57:10 UTC