Subject: Design Issue: Frame Processing Model

From: James M Snell <[email-masked]>
Date: Thu, 25 Apr 2013 15:28:41 -0700

At the (very real) risk of adding a bit too much formalism to the
Frame processing model, I have noticed a number of areas in the
current -02 draft where references are made to an endpoint being
required to receive and accept frames but being permitted to ignore
them if necessary, etc. There is also a concern over where exactly in
the processing model steps such as header compression state management
ought to occur, whether or not that occurs before sending RST_STREAM
and GOAWAY frames, etc.

In thinking it over, I think it would be very beneficial in the long
term for us to define specific processing levels or tiers for Frames.
Below is a strawman example:

Tier 1: "Session Tier"
  A frame received and parsed. This is where basic validation of the
frame syntax occurs and where state management based on frame
structure (e.g. compressed headers) happens. Any processing errors
that occur here are considered to be Session Errors and will typically
be related to incorrect protocol support, malformed frames, malformed
headers, etc. At this tier, frames are examined individually and not
yet processed as being part of a stream.

Tier 2: "Stream Tier"
  The next tier is to process the frame in context of a stream. This
is where we look at things like whether the frame has a valid known
stream identifier, whether the associated stream is open, half-closed,
closed or whatever. The errors that occur here can be Session or
Stream errors.

Tier 3: "Application Tier"
  The Frame data is passed on for application-level handling. All of
the basic parsing and stream validation has occurred already. This is
where we start applying HTTP specific semantics. The errors that occur
here are typically HTTP level errors with associated HTTP status
codes.

Given these tiers, we can then begin speaking in very concrete terms
about what kinds of processing may be required at different points in
the session lifecycle.

For instance:
 - Protocol upgrade negotiation, SETTINGS frames, GOAWAY and flow
control are all handled in Tier 1. None of that ever passes on to
higher tiers.
 - When we say things like, "an endpoint MUST be continue to accept
frames after a RST_STREAM", we're really saying that Tier 1 processing
must still occur, but that frames may not have to be passed on to Tier
2
 - When we deal with HTTP specific semantics, we assume that all of
the Tier 1 and Tier 2 processing has been dealt with

I believe these layers already informally exist in the model we have,
even if it's not entirely obvious in the current design.

- James

---

From: Martin Thomson <[email-masked]>
Date: Thu, 25 Apr 2013 16:23:47 -0700

Semi-formally, the Tier 2/3 division is made.  The 1/2 split hasn't been.

We've been talking about a "framing layer", which refers to 1+2.  I
originally thought that the distinction would be 1=framing, 2=streams,
3=application (http).  You can go further and split the streams layer
into planes: control and data.  But I agree, formalism only gets you
so far.

Otherwise, I think that you have it.  I'm not sure whether the spec
needs to say anything.  Maybe you could save it for the book that you
are writing on HTTP/2.0.

---

From: James M Snell <[email-masked]>
Date: Fri, 26 Apr 2013 10:04:41 -0700

In reading through the current spec, I believe there would at least be
some value in briefly calling out the three tiers. Doing so helps in
three ways:

1. When dealing with error conditions, identifying the tiers, along
with what processing occurs in each, helps us to communicate what
steps are absolutely required. For instance, we say several times that
when a stream is half-closed in one direction, the closed end needs to
be prepared to accept frames but might be able to safely discard
those; we do not, however, ever explicitly define what it means to
"accept" a frame. This will be particularly important when dealing
with state management (header compression) and mitigation of denial of
service attacks.

2. Calling out the tiers gives us a very simple way of isolating
specific functions, such as error handling, upgrade negotiation, flow
control, header compression, stream management, etc. There is, for
instance, an open question about mixing HEADERS and DATA frames in a
single stream and allowing certain sets of HEADERS to "bleed through"
to higher levels. Defining the tiers explicitly would allow us to
speak more intelligently about where things belong.

3. Calling out the tiers gives us a more robust approach for dealing
with extensions to the protocol later on. For example, if I introduce
a new frame type at some point down the road, how does that frame type
necessarily impact the session? We've discussed in another thread that
unknown frame types ought to never require a change to session state,
which means that new frame types would never be Tier 1. New Frame
types might, however, impact things at a stream level (for instance,
imagine a checksum frame that includes a cryptographic hash of
previously sent data frames.. some bit of Tier 2 stream handling code
could automatically verify that without it ever being passed on to
Tier 3. Or, the new frame could be intended solely for the application
layer... Do we want to allow that? Honestly, I would argue that all
extension frames ought to be limited to Tier 2. Only changes to the
base protocol can introduce Tier 1 frames... if we do not call out the
Tiers explicitly, it becomes much more difficult to establish these
boundaries.

I believe that it should be possible to keep the description simple
and I can take a first stab at it. If, after reviewing that draft,
people think it adds too much complexity or confusion, we can drop the
silly idea ;-)

- James