Re: Feedback from first read of QUIC/HTTP draft 08

Mikkel Fahnøe Jørgensen <mikkelfj@gmail.com> Fri, 08 December 2017 14:40 UTC

Return-Path: <mikkelfj@gmail.com>
X-Original-To: quic@ietfa.amsl.com
Delivered-To: quic@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 20274126C25 for <quic@ietfa.amsl.com>; Fri, 8 Dec 2017 06:40:09 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.698
X-Spam-Level:
X-Spam-Status: No, score=-2.698 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_LOW=-0.7, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Q7dUa3CJiQym for <quic@ietfa.amsl.com>; Fri, 8 Dec 2017 06:40:06 -0800 (PST)
Received: from mail-it0-x22e.google.com (mail-it0-x22e.google.com [IPv6:2607:f8b0:4001:c0b::22e]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 61158124D37 for <quic@ietf.org>; Fri, 8 Dec 2017 06:40:06 -0800 (PST)
Received: by mail-it0-x22e.google.com with SMTP id u62so5258778ita.2 for <quic@ietf.org>; Fri, 08 Dec 2017 06:40:06 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:in-reply-to:references:mime-version:date:message-id:subject:to :cc; bh=gbD6WxgC1tFnyIop2gRCWxdHOP94Rn1seTPfYMGFst8=; b=IYJLiXTxK/rxIH+m9boUwAR8woP+X7pLAa0afSa6u4qbfju6aSyS5UqZpGjakvjxqN WQKP0BIB0dDFmAsbXI0n5xm6ylLsgrzx5WSVUeTYkaCYrkxaVFBPBYCjDv1Y5fdINML+ waJ9Z4+QbVoj6MynXfL/MCGVX7F9nqrD2ekKoBQg5EgzvCPgY7duNvz799UESD6U6ILR phibtUJHnDlG28N+s0f07cMvuSS1ohWgiM5riXM1L2nato/uc0Qq/g0E8fWCkrEWfamW lwcOIQ6Rn+qLr0/rmm7R5Qb/+ZLdtOhtNGRhlJ4w7uzXJreWGCuQ0UIpqJ7skIplI+gN mjhg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:in-reply-to:references:mime-version:date :message-id:subject:to:cc; bh=gbD6WxgC1tFnyIop2gRCWxdHOP94Rn1seTPfYMGFst8=; b=inDFsH352UjF18WAlYAEML+2L8Ld2TZwZlE1ONE8FJOb3zdtzgUwOsHVWdZmfPLUJs uTiMfgc8uooVHDeAxVg/aZhUcUcCR0KHGq0Us+T6CC18qe4UoztGI7doD+4+EEXrSOz9 LQNzEVZjfttsSWDHSBVzQHqj9dxmjC0B0i54EZqH0rAjQCWe69sa4hz/dMGjeX8qYqn6 RUhRE5z1o+j9EU7vkGklEvPGxb4fOXunNxUwcaP+fUJDYM2vvu8JoBEOX7E/5oL5PSX8 2pJzUp4LDY1JSCfJqsOvnvoKN+ouBDqSuTHi9FnYwog9uJe/4yENDp6zFEfam4Tr0dPS UtZg==
X-Gm-Message-State: AJaThX7pLMuRMRCVrT605pzeYHIWZ6OCnCKaKkaaXrqfrk0eRwJvDWA2 gKUg4CgvLYRrEbvppBEtYC2vNtVlsTE44uU69KI=
X-Google-Smtp-Source: AGs4zMYjAfAZU5PQg7U0h/JnrEJK4Kpsk7BheeAErkR4Zj2KNrRK4W6WU/kHxJYEyiiOcPOV//nFYvnIaTlBabjj8P0=
X-Received: by 10.107.83.24 with SMTP id h24mr44578480iob.239.1512744005525; Fri, 08 Dec 2017 06:40:05 -0800 (PST)
Received: from 1058052472880 named unknown by gmailapi.google.com with HTTPREST; Fri, 8 Dec 2017 09:40:05 -0500
From: Mikkel Fahnøe Jørgensen <mikkelfj@gmail.com>
In-Reply-To: <20171208130122.GA8878@ubuntu-dmitri>
References: <CAN1APdcNRyJJToL5Ym8T9v2svCfiJLekqmbbEzkVNdMbGZUfAQ@mail.gmail.com> <20171208130122.GA8878@ubuntu-dmitri> <20171208130122.GA8878@ubuntu-dmitri>
X-Mailer: Airmail (420)
MIME-Version: 1.0
Date: Fri, 08 Dec 2017 09:40:05 -0500
Message-ID: <CAN1APdej-MT1nqvScqWV5fupvgAz7bBDpFdhCrfM7kuXh_VScg@mail.gmail.com>
Subject: Re: Feedback from first read of QUIC/HTTP draft 08
To: Dmitri Tikhonov <dtikhonov@litespeedtech.com>
Cc: IETF QUIC WG <quic@ietf.org>
Content-Type: multipart/alternative; boundary="089e08284d9015e3f2055fd529a8"
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic/xjJIw_AqoWNNrjSAeXn-KbbE2HQ>
X-BeenThere: quic@ietf.org
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: Main mailing list of the IETF QUIC working group <quic.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/quic>, <mailto:quic-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/quic/>
List-Post: <mailto:quic@ietf.org>
List-Help: <mailto:quic-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/quic>, <mailto:quic-request@ietf.org?subject=subscribe>
X-List-Received-Date: Fri, 08 Dec 2017 14:40:09 -0000

> 8. The HPACK, to be replaced, doc is hard to parse


There are three HPACK replacement proposals (neither of which is
referenced by [draft-ietf-quic-http-08]): QPACK, QCRAM, and QMIN.
Which one are you referring to?

I’m just referring to the fact that I’m aware the HPACK is not the long
term solution, but this was the document I was referring to. I have not
been looking into Q* yet.

> and it doesn't sound like it is as complicated as it reads.
> Hopefully a future QUIC equivalent would be a bit easier to
> digest.

If you offered some specific examples, I think it would be appreciated:
we want to make the documents comprehensible on the first read.


My intuition is that HPACK could largely be described by the following
text, although details may be a bit off as I haven’t digged into all the
details:

HPACK represents HTTP headers in a compact form. Every valid name string
and value string can be stored as a HPACK field. A valid name or value
string conforms to HTTP 1.1 strings without space, ‘:’ and CRLF delimited.
A name may also be a pseudo-name starting with ‘:’ for example ‘:method’
used in HTTP/2.

The fields are conceptually ordered similar to how the text representation
is ordered in HTTP 1.1 such that a similar header can be recreated after
decoding. The result of decoding a HPACK stream is exactly such a list, and
updated internal state which makes the next exchange smaller in size. This
internal state is kept in the dynamic name table discussed below.

Some header names are used often and have a dedicated encoding in a static
table. Some names are less general but may still be reused across requests,
such names can be stored in a dynamic table for reuse. And finally some
names should not compressed for security reasons or because it is not
deemed efficient. The sender (encoder) decides which form to use, but can
only choose the static form if the name is in the static table. Names are
always case insensitive.

The header values are always just explicit strings that are not compressed
(or are they? - did not get that far in the text). We refer to such a
string as ValueString.

For security reasons and implementation simplicity, the format is simple
and not extensible. Instead HPACK as a whole may be replaced by another
compression if needed. HPACK depends on the sender (encoder) sending all
operations in a specific order such that the decoder can reverse the
encoding unambiguously.

In the following the three forms of name encoding are discussed further,
followed by how the entire list is encoded.

The static table is list of known names that is a assigned an index between
1 and K, where K is the length of the static table. Each name is
represented as an integer index into this table. We call this value
StaticName.

The following may not be exactly correct, but this is how I imagine it work
from a quick skim.

The dynamic table has a fixed size which is negotiated. The size may
change, but always in a way that both sender and receiver is aware of it
and only in a way the receiver permits. If the sender grows the table
beyond the granted limit, this is a fatal error. The current size of the
dynamic table is N. The table may not use all entries. If a name is stored
in the table it is represented by the integer DynamicName which is in the
range (1 + K … N + K). The size N may be zero in which case no names are
encoded as a dynamic name. Otherwise the table is filled up such that the
first name is given the value N + K, the next name the value N + K - 1
until the table fills up. After that, the process starts over with the next
value again being N + K and so forth. The decoder has enough information to
maintain the table as it changes. The encoded issues commands to add names
to the table but does not explicitly evict names. The encoder can grow or
shrink the table with a single command. In either case the new size takes
effect once the table wraps the next time around. We refer to the dynamic
table size N as the integer DynamicTableSize.

When an encoder adds a name to the dynamic table, it does not send the name
explicitly but via a huffman compression scheme based on static huffman
codes. The net effect is a command with a bit string containing the
compressed name to be added to the dynamic table. No index information is
needed because the decoder is in sync. The encoder, by definition, does not
need to add names to static table so there is no corresponding operation.
We refer to the huffman encoded name as DynamicNameString.

Finally the name can be stored explicitly without compression. There is no
update command for this. We refer to an explicit string as ExplicitName.

The encoding is a stream of commands which we list below, followed by a
wire format representation.

PushDynamicHeader(DynamicNameSring)

ResizeDynamicTable(DynamicTableSize)

AddImplicitHeader(StaticName | DynamicName, ValueString)

AddExplicitHeader(ExplicitName, ValueString)

Done()


The encoder sends a list of commands in a very specific order. An
implementation is free to choose how it orders these commands, except
Done() comes last and AddImplicitHeader must only be called when there is a
valid entry in the table being addressed.

The decoder processes these commands in order and aborts the operation in
case of any violation. The result of the decoding process is an order list
of name/value pairs with exactly one field for each AddImplicit/Explicit
commands. In addition the decoder now potentially has a populated dynamic
table that can be reused by the next request which must be handled strictly
after the previous in order to maintain sync. If the decoder wants to
reduce or increase its dynamic table it can send this information to the
decoder via command X (TBD). This is an async operation. The decoder cannot
require the sender to go below a previous sent limit, but it can allow it
to grow larger and advise it to shrink. The initial dynamic table size is
an out of band parameter similar to the huffman table and the static table.


An example is the following HTTP1.1 header where the status line with the
GET method is replaced by HTTP/2 pseudo names:

… example to follow …

The dynamic table then looks like: ...


The Huffman encoding is the list of symbols in appendix A along with the
huffman algorithm,

The static table is the list names in appendix B, or another set of names
if agreed out of band.

The wire format of ValueString is …

The wire format of  DynamicName is …

The wire format of ExplicitString is ….

The wire format of command X header is …

Appendix...