Subject: Re: HTTP/2 Header Encoding Status Update

From: Nicolas Mailhot <[email-masked]>
Date: Fri, 1 Mar 2013 10:41:06 +0000 (UTC)

Mark Nottingham <mnot@...> writes:

> 
> One other thing - 
> 
> On 28/02/2013, at 8:16 AM, James M Snell <jasnell@...> wrote:
> 
> > Date values:
> > 
> >  1. Dates are encoded as the number of seconds since a new epoch
> > (Midnight GMT, Jan 1 1990)
> 
> So, how many bytes does changing the epoch save us?
> 
> I just get concerned about putting little landmines like this in...

I'd really *love* to see the whole epoch concept nuked in HTTP/2 and force
everyone to use an ISO 8601 profile like html instead
http://www.w3.org/TR/NOTE-datetime
(requiring UTC-only if necessary)

We've already been bitten by an http product that seemed to use the same epochs
as everyone else (even calling them "unix epochs") but actually counted epochs
in local dos/windows time. The problem was un-obvious till we needed to perform
some cross-system analysis and discovered they disagreed on time even though
they all used the "same" epoch format. Getting time right in an i18n context is
hard enough without obfuscating the format.

Do the benefits of an epoch really outweigh the benefits of avoiding time
mistakes in an http user?

-- 
Nicolas Mailhot

---

From: James M Snell <[email-masked]>
Date: Fri, 1 Mar 2013 07:37:44 -0800

> mistakes in an http user?

Iso8601 date times require a minimum of 20 ascii bytes at the second
precision level.  The uvarint epoch encoding requires a maximum of ten
bytes but will usually be around 5 or 6 for the reasonably foreseeable
future.  I have no problem with 8601 for general use but in encoding for
transmission, the epoch encoding is much more efficient.

---

From: Scott Schmit <[email-masked]>
Date: Sat, 2 Mar 2013 00:38:23 -0500

On Wed, Feb 27, 2013 at 01:16:16PM -0800, James M Snell wrote:
> Numeric values:
> 
>   1. Numeric values are encoded as variable-length, unsigned integers.
"Big-endian" or "little-endian"?

I've seen some references which state that the MSBs go first, others
that say the LSBs go first. (Wikipedia led me down the MSB path, which
confused me at first.  Google's protocol buffers does LSBs first.)

Based on your date example, it appears you're doing LSBs first (though
the date example appears skewed by 123 seconds?).

You'll need to define the uvarint format -- a search for "unsigned
variable-length integers" comes up with a number of very different
encodings--not that they all call themselves "uvarint" but still...

I assume that the uvarint length will be capped in some way?  Is that
per-field or is there an overall cap?

-- 
Scott Schmit

---

From: James M Snell <[email-masked]>
Date: Fri, 1 Mar 2013 21:47:32 -0800

> confused me at first.  Google's protocol buffers does LSBs first.)
​LSB.. I'm currently following the same scheme as protobufs but that's not
set in stone.

> the date example appears skewed by 123 seconds?).

​Shouldn't be, I'll double check.

> per-field or is there an overall cap?
​64-bit integers encode with a maximum of 10-bytes. If you run that out
you'll see that it gives us *plenty* of time ;-)

---

From: Scott Schmit <[email-masked]>
Date: Sat, 2 Mar 2013 01:34:01 -0500

On Wed, Feb 27, 2013 at 03:12:25PM -0800, James M Snell wrote:
> Using the original epoch, I think we use six bytes currently. The new
> epoch uses five.

Nope. Using an epoch of 1970-01-01T00:00:00Z currently gives a 5-byte
uvarint encoding.

We won't hit 6 bytes until 3058-10-26T03:46:08Z.

I hope we can afford the extra byte by then... :-)

For the record:
* We hit 4 bytes at only ~25 days after whatever epoch we set
* If we decided to make dates be signed varints, we still wouldn't
  hit 6 bytes until 2514.
* If we decide to count milliseconds since the epoch, we're already at 6
  bytes, but that would happen a little over a year after whatever epoch
  we set. (And we wouldn't hit 7 bytes until 2248. Signed milliseconds
  hits 7 bytes in 2109.)

Let's stick to the POSIX epoch.

-- 
Scott Schmit

---

From: Scott Schmit <[email-masked]>
Date: Sat, 2 Mar 2013 02:00:36 -0500

On Fri, Mar 01, 2013 at 09:47:32PM -0800, James M Snell wrote:
> On Fri, Mar 1, 2013 at 9:38 PM, Scott Schmit wrote:
> LSB.. I'm currently following the same scheme as protobufs but that's not
> set in stone.

An advantage of LSB first is that it's not as awkward to encode. A
disadvantage is that you can't be sure that someone is using an
intentionally-inefficient encoding until they finish the number, if they
ever do. (All the leading zeros are at the end.)

> 64-bit integers encode with a maximum of 10-bytes. If you run that out

Well, I assume we're going to use uvarints for more than just dates. :)

Besides, I was thinking about the problems people had with UTF-8 at
first with inefficient encodings, and with numbers I can imagine someone
playing games with overflows to achieve some effect too.

-- 
Scott Schmit

---

From: James M Snell <[email-masked]>
Date: Fri, 1 Mar 2013 23:14:01 -0800

Yes, we'll definitely need to look at the security issues on it. I haven't
spent too much time looking at that aspect. So far I am looking only at
date headers, status and content-length for the use of the uvarint
encoding. Content-length is the one with the primary issue as far as upper
range is concerned. Some limits will need to be applied.

- James

---

From: "Nicolas Mailhot" <[email-masked]>
Date: Sat, 2 Mar 2013 10:34:21 +0100

> transmission, the epoch encoding is much more efficient.

Sure, I never claimed it was more efficient. I don't care how header names
and other technical-only parts are encoded: go wild, be as efficient as
you want. However, IMHO this group should think twice before choosing
anything un-obvious to encode human-related info. So +10 for killing weird
text encodings and putting everything in UTF-8, -10 for using epochs for
time. Because time is based on human conventions, that we often do not get
right, so adding an obfuscation layer does not help (rockets have been
lost in the past because humans could not agree on units, there is the
ongoing trainwreck of KB/KiB and friends, anything unit-related must be
treated with extra care).

While a bit inefficient (in space) iso 8601 should not be too inefficient
at processing time. Do the space savings added by using a full epoch
outweigh the problems caused by wrong datetimes human operators do not
notice because they're hidden in an epoch, that looks like any other
epoch?

One of the main properties of the time format chosen is that it should
fail hard and fast when any network node get confused about DST or
country. Because the cleanup when such mistakes go unnoticed is expensive,
and they are very common.

Iso 8601 is the best we have right now, many smart humans spent a lot of
time defining a representation that was no error-prone yet reasonably easy
to process.

This proposal is very bad from this point of view: not only it uses an
epoch format which has already been misused in the wild, but it chooses a
reference start different from past formats. I find it very dangerous, it
will induce lots of mistakes.

Regards,

-- 
Nicolas Mailhot

---

From: Yoav Nir <[email-masked]>
Date: Sat, 2 Mar 2013 10:54:09 +0000

> treated with extra care).

Machines store date & time information in internal formats. Whatever bits-on-the-wire format we use, machines will convert their internal format to the protocol format on sending, and convert to their internal format when receiving. I see no reason why we should use on the wire a format that is readable by humans, when the communications is between machines. The ISO 8601 format takes more cycles to encoded and decode, and is much harder for calculating time differences. The exact length of any particular February has been a source of many errors in the past.

> notice because they're hidden in an epoch, that looks like any other

Operators need never look at the bits on the wire. Since we've already agreed to go to some kind of binary format, the days of eyeballing packet captures and using telnet to test web servers are gone anyway. You'll need a packet analyzer such as Wireshark. Wireshark will show you the date in a human readable format, just as it shows an interpretation of other fields. 

> and they are very common.

So you'd like endpoints to break a connection and log (or pop up) an error if the other side shows a time more than X minutes in the future? That's possible with any format.

> time defining a representation that was no error-prone yet reasonably easy

That representation was created for the benefit of humans. It would be fine, if somewhat geeky to publish the upcoming meeting date as 2013-03-15T13:00Z. But that is because this is meant for humans. It also makes sense for protocols and formats that are intentionally human readable, such as HTTP/1 and XML. It's just a burden for machines.

---

From: Eliot Lear <[email-masked]>
Date: Sat, 02 Mar 2013 12:01:54 +0100

Others have asked most of my questions, and so I have but one, for now:

> (Midnight GMT, Jan 1 1990)

Why a new epoch?  Can't we use an existing one?

Eliot

---

From: James Cloos <[email-masked]>
Date: Sat, 02 Mar 2013 17:03:18 -0500

>>>>> "JMS" == James M Snell <[email-masked]> writes:

JMS> ​LSB.. I'm currently following the same scheme as protobufs but that's not
JMS> set in stone.

IP itself is Big Endian.  No protocol over it should choose otherwise.

There is too much room for confusion otherwise.

If protobufs does so, that is a bug.

-JimC
-- 
James Cloos <[email-masked]>         OpenPGP: 1024D/ED7DAEA6

---

From: "Adrien W. de Croy" <[email-masked]>
Date: Sun, 03 Mar 2013 09:13:47 +0000

------ Original Message ------
From: "James Cloos" <[email-masked]>
To: "James M Snell" <[email-masked]>
Cc: "[email-masked]" <[email-masked]>
Sent: 3/03/2013 11:03:18 a.m.
Subject: Re: HTTP/2 Header Encoding Status Update
>IP itself is Big Endian. No protocol over it should choose otherwise.

what proportion of hardware processing HTTP is big-endian?

>There is too much room for confusion otherwise.

It's not actually that hard to get right.
you use library functions to get the information from TCP and lower 
anyway.

IME you're more likely to get errors when using big-endian data, when 
you omit a htonl / ntohl.

Adrien

---

From: James M Snell <[email-masked]>
Date: Sun, 3 Mar 2013 15:46:38 -0800

The LSB-ordered scheme used by protobufs is really drop dead simple to
implement. Extremely difficult to get wrong unless you forget to account
for signs. That's really the reason I chose it for the prototype.

On Sun, Mar 3, 2013 at 1:13 AM, Adrien W. de Croy <[email-masked]> wrote:

>> JMS> LSB.. I'm currently following the same scheme as protobufs but
>> that's not
>> JMS> set in stone.
>>
> you use library functions to get the information from TCP and lower anyway.
>
> IME you're more likely to get errors when using big-endian data, when you
> omit a htonl / ntohl.
>
> Adrien
>
>

---

From: Nicolas Mailhot <[email-masked]>
Date: Mon, 4 Mar 2013 11:23:15 +0000 (UTC)

Yoav Nir <ynir@...> writes:

> Machines store date & time information in internal formats. Whatever
bits-on-the-wire format we use,
> machines will convert their internal format to the protocol format on sending,
and convert to their
> internal format when receiving. I see no reason why we should use on the wire
a format that is readable by
> humans, when the communications is between machines. 

Yet so far implementors have been humans not machines. Posix timestamp is
efficient because it is simple. But it is so simple human implementors are not
careful and get it wrong. I have zero confidence anything using posix timestamps
will be correctly implemented in the wild.

If you want a binary format at least take something like ntp, which has not been
abused for years by php and windows developers that do not care if the result is
correct as long as it looks somewhat right.

-- 
Nicolas Mailhot

---

From: Nicolas Mailhot <[email-masked]>
Date: Mon, 4 Mar 2013 11:29:55 +0000 (UTC)

Also would if be possible to ask one of the IETF workgroups that worked on time
subjects to propose a time format safe wrt leap seconds and such? 

It is very clear embedded bits are moving to http as communication channels, so
http/2 should really be built to avoid embarrassments such as trains being
stopped at DST time because no one can vouch all the electronics and their
traffic is dst-safe.

-- 
Nicolas Mailhot

---

From: "Poul-Henning Kamp" <[email-masked]>
Date: Mon, 04 Mar 2013 14:21:09 +0000

Content-Type: text/plain; charset=ISO-8859-1
--------

>subjects to propose a time format safe wrt leap seconds and such? 

At present there are no relevant time formats which are leap-second safe.

To my knowledge nobody is seriously working on a remedy for that,
expecting leap-seconds to be killed in the next 10 years or so.

I think trying to fix it in HTTP/2 would be ill-advised if not
downright stupid, and we should just stick with POSIX, rather than
invent yet another time-format[1].

Poul-Henning

[1] The only standardized actually used format I can point to, which
can deal correctly with leap-seconds  is the "MJD" used by astronomers.

MJD counts in days + fractional days, and therefore isolates the
impact of leap-seconds to be non-accumulative, at the cost of noon
being

	X.4999942130299418

rather than

	X.5

on days which insert leap seconds.

Using MJD, with a 32 bit fraction, we get 20 microsecond resolution.

A 16 bit day-number would give us only 9180 days, 25 years, before
roll-over, but we could instigate a different epoch to buy us some
time there.

Conversions to/from POSIX/timeval/timespec would be mostly trivial,
but not without pitfalls.

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
[email-masked]         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe    
Never attribute to malice what can adequately be explained by incompetence.

---

From: Eliot Lear <[email-masked]>
Date: Mon, 04 Mar 2013 15:58:00 +0100

>From a *format* perspective, at least ISO-8601 and RFC-5322 (Message
Format) are examples where leap-seconds are supported.  I don't know all
time formats.  It's quite possible some standards have made it up as
they went along, and just blew that play.  When talking about seconds
from an epoch, it seems to me that if the second occurred it should be
counted, but I would suspect there already is a standard there as well,
and we should follow it.  What would Linux do? ;-)

Eliot

---

From: "Poul-Henning Kamp" <[email-masked]>
Date: Mon, 04 Mar 2013 15:08:14 +0000

In message <[email-masked]>, Eliot Lear writes:

>Format) are examples where leap-seconds are supported.

Both are standards for textual (aka: human readable) representation
of timestamps and involve a lot of text-processing to perform the
for HTTP usage necessary before/after comparisons on.

If HTTP/2 has any pretentions of being a high-performance protocol,
it must define an arithmetic time-representation, which allows
simple and cheap comparisons and the arithmetic operations necessary.

>When talking about seconds

UNIX, POSIX, Linux and Windows all pretends that leapseconds don't exist.