Re: [hybi] Framing Take VI (a compromise proposal)

John Tamplin <jat@google.com> Sun, 15 August 2010 04:03 UTC

Return-Path: <jat@google.com>
X-Original-To: hybi@core3.amsl.com
Delivered-To: hybi@core3.amsl.com
Received: from localhost (localhost [127.0.0.1]) by core3.amsl.com (Postfix) with ESMTP id 26B833A69B2 for <hybi@core3.amsl.com>; Sat, 14 Aug 2010 21:03:16 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -105.226
X-Spam-Level:
X-Spam-Status: No, score=-105.226 tagged_above=-999 required=5 tests=[AWL=-0.450, BAYES_00=-2.599, FM_FORGED_GMAIL=0.622, HTML_MESSAGE=0.001, J_CHICKENPOX_44=0.6, J_CHICKENPOX_54=0.6, RCVD_IN_DNSWL_MED=-4, USER_IN_WHITELIST=-100]
Received: from mail.ietf.org ([64.170.98.32]) by localhost (core3.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id S++6ejVyVfrZ for <hybi@core3.amsl.com>; Sat, 14 Aug 2010 21:03:14 -0700 (PDT)
Received: from smtp-out.google.com (smtp-out.google.com [216.239.44.51]) by core3.amsl.com (Postfix) with ESMTP id 6CD583A69A2 for <hybi@ietf.org>; Sat, 14 Aug 2010 21:03:14 -0700 (PDT)
Received: from wpaz24.hot.corp.google.com (wpaz24.hot.corp.google.com [172.24.198.88]) by smtp-out.google.com with ESMTP id o7F43n4J007737 for <hybi@ietf.org>; Sat, 14 Aug 2010 21:03:49 -0700
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=google.com; s=beta; t=1281845030; bh=Io02PcV01uSHKRhLJW1Ist5vcZ4=; h=MIME-Version:In-Reply-To:References:From:Date:Message-ID:Subject: To:Cc:Content-Type; b=AUlsbM/f6YrWfVtrvu/Ber5B9aHv8W9OmY5pZLne/MI5HpB9mm/8la5++W95zNME+ XzamMeq9f/D1K3N7MdXxw==
DomainKey-Signature: a=rsa-sha1; s=beta; d=google.com; c=nofws; q=dns; h=mime-version:in-reply-to:references:from:date:message-id: subject:to:cc:content-type:x-system-of-record; b=Hn12/rtVzQxyW4Os1BTk8bO08eH5PP6CXpLksKANvEam1xFNREuzG/GseGeTOazjv Wja4NaAleq8ssCNB17fvw==
Received: from yxk30 (yxk30.prod.google.com [10.190.3.158]) by wpaz24.hot.corp.google.com with ESMTP id o7F43muP000459 for <hybi@ietf.org>; Sat, 14 Aug 2010 21:03:48 -0700
Received: by yxk30 with SMTP id 30so1658779yxk.30 for <hybi@ietf.org>; Sat, 14 Aug 2010 21:03:48 -0700 (PDT)
Received: by 10.151.1.4 with SMTP id d4mr3916076ybi.433.1281845028306; Sat, 14 Aug 2010 21:03:48 -0700 (PDT)
MIME-Version: 1.0
Received: by 10.151.60.3 with HTTP; Sat, 14 Aug 2010 21:03:24 -0700 (PDT)
In-Reply-To: <4C66F67C.2080406@caucho.com>
References: <AANLkTi=TBXO_Cbb+P+e2BVfx69shkf8E1-9ywDh_Y+Kz@mail.gmail.com> <AANLkTimJOGWgV6rx5JJYSJMC26OzQzskzVtkYz0L_EAg@mail.gmail.com> <op.vhe7qtmu64w2qv@anne-van-kesterens-macbook-pro.local> <AANLkTimqvQGJab-XdMuRFE8M2eB_xn_ipJZoNDuc28R2@mail.gmail.com> <4C66F67C.2080406@caucho.com>
From: John Tamplin <jat@google.com>
Date: Sun, 15 Aug 2010 00:03:24 -0400
Message-ID: <AANLkTikY_ujn4rxuEPTidktL4Rwc1RizGBaa0-dpAhJP@mail.gmail.com>
To: Scott Ferguson <ferg@caucho.com>
Content-Type: multipart/alternative; boundary="000e0cd6755891c7f0048dd4cd85"
X-System-Of-Record: true
Cc: hybi@ietf.org
Subject: Re: [hybi] Framing Take VI (a compromise proposal)
X-BeenThere: hybi@ietf.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: Server-Initiated HTTP <hybi.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/hybi>
List-Post: <mailto:hybi@ietf.org>
List-Help: <mailto:hybi-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=subscribe>
X-List-Received-Date: Sun, 15 Aug 2010 04:03:16 -0000

On Sat, Aug 14, 2010 at 4:03 PM, Scott Ferguson <ferg@caucho.com> wrote:

> Well, the complexity is more of a spec issue than a coding one because none
> of these proposals are hugely complicated to implement. (Implementing them
> efficiently is a different matter.)
>
> A Jamie-style proposal less complex because it leaves the basic frame clean
> without needing the extension length or the extension payload and without
> the extra complete-length field. The frame would look like:


There were objections raised about exactly this sort of thing before:

   - a receiver would prefer to allocate the buffer at once for a message
   rather than having to reallocate/copy it, which means the sender should send
   the complete message length with the first fragment if it is available
   - having a short length that was "mostly enough" would encourage buggy
   implementations that don't support or test the long length case


> 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
> +-+-+-+---------+-------------------------------+---------------+
> |I|F|B|opcode(5)| length(16)                    |               |
> |N|I|I|         |                               |               |
> |I|N|G|         |                               |               |
> +-+-+-+---------+-------------------------------+ - - - - - - - +
> | big-length(48) if BIG = 1                                     |
> + - - - - - - - +-----------------------------------------------+
> |               | payload(length)                               |
> +---------------+                                               |
> |                                                               |
> +---------------------------------------------------------------+
>
> As a measure of complexity, compare the features that can vary the
> frame-header size:
>
>  a) short/long payload length
>  b) extension data
>  c) short/long extension length
>  d) complete message-length
>
> A Jamie-style extension only has the single complexity-feature (a) to the
> frame-header, while your proposal adds 3 more (b,c,d). Since the Jamie-style
> extension supports all the extension capabilities that yours does, there's
> no added capabilities with the extra complexity added by b,c,d.
>

The point of having a specified way of passing extension data in the framing
is so intermediaries can know where the payload data is even if they don't
understand the extensions that were negotiated.  I personally don't feel
terribly strongly about this.

Regarding d, as mentioned above those arguing against fragmentation objected
to not having the full message length, and after proposing that addition
they seemed happy with the compromise.  As fragmentation support has been
accepted as a requirement


> As a separate issue, your code's signature doesn't capture the essence of
> the problem, because you really need to consider all the APIs when
> evaluating a framing proposal, not just one that happens to be easy to
> implement for the proposal. Your example was a specialized API that really
> only works for utf-8 encoded 8-bit C-strings.
>
> The basic sender APIs that framing needs to support are:
>
> a)  sendTextMessage(char []buffer, int offset, int length); // JavaScript
> 16-bit text send
>

The complication of UTF16->UTF8 conversion is the same in any other
length-based framing options, though supporting fragmentation means you can
have a fixed-size send buffer rather than having to allocate all of it at
once.


> a*) sendTextMessage(byte []buffer, int offset, int length); // utf-8
> encoded text (like PHP)
>
> b)  sendBinaryMessage(byte []buffer, int offset, int length); // binary
> single-buffer send
>

Other than the choice of opcode, these are identical, right?


> c)  class BinaryMessageOutputStream {
>   write(byte []buffer, int offset, int length);
>   close();
>  }
>
> d)  class TextMessageWriter {
>   write(char []buffer, int offset, int length);
>   close();
>  }
>

Again, I don't see these as showing any differences between the various
framing proposals, and fragmentation makes it easier to support streams as
you just write a fragment when the buffer fills.


> The receiver variations are
>
> a) char []receiveTextMessage()
>
> b) byte []receiveBinaryMessage() // if returning utf-8 8-bit strings, this
> is the text receive
>
> c) class BinaryMessageInputStream {
>     int read(byte []buffer, int offset, int length);
>   }
>
> d) class TextMessageReader {
>     int read(char []buffer, int offset, int length);
>   }
>

I would think there would also be an event-driven API, since that is what
the JS API is going to look like -- where there is an onMessage event called
with a complete message after it has been received.  The only public
server-side API I know of (Jetty7) also operates this way.


> A good frame design will support all 5 sender API styles and 4 receiver API
> styles in a straightforward/efficient manner. You can't just pick one API
> that happens to make a frame proposal work.
>

Can you explain how your proposed framing is any different for any of these
APIs?  The difference is about the size of the short frame length, leaving
out the extension information which isn't going to be used in the base
protocol anyway, and leaving out the overall message length which means you
have to guess a buffer size for fragmented messages and grow it if necessary
(or fail the receive if using a too-small caller-supplied buffer).

-- 
John A. Tamplin
Software Engineer (GWT), Google