Re: [hybi] Framing Take VI (a compromise proposal)
Scott Ferguson <ferg@caucho.com> Sat, 14 August 2010 20:02 UTC
Return-Path: <ferg@caucho.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 2EA003A680B for <hybi@core3.amsl.com>; Sat, 14 Aug 2010 13:02:40 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -1.044
X-Spam-Level:
X-Spam-Status: No, score=-1.044 tagged_above=-999 required=5 tests=[AWL=-1.179, BAYES_00=-2.599, IP_NOT_FRIENDLY=0.334, J_CHICKENPOX_44=0.6, J_CHICKENPOX_54=0.6, J_CHICKENPOX_66=0.6, J_CHICKENPOX_83=0.6]
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 YmxtPuU7KG7d for <hybi@core3.amsl.com>; Sat, 14 Aug 2010 13:02:39 -0700 (PDT)
Received: from smtp114.biz.mail.sp1.yahoo.com (smtp114.biz.mail.sp1.yahoo.com [69.147.92.227]) by core3.amsl.com (Postfix) with SMTP id 1AC0B3A67EE for <hybi@ietf.org>; Sat, 14 Aug 2010 13:02:39 -0700 (PDT)
Received: (qmail 51157 invoked from network); 14 Aug 2010 20:03:13 -0000
Received: from [192.168.1.11] (ferg@66.92.8.203 with plain) by smtp114.biz.mail.sp1.yahoo.com with SMTP; 14 Aug 2010 13:03:13 -0700 PDT
X-Yahoo-SMTP: L1_TBRiswBB5.MuzAo8Yf89wczFo0A2C
X-YMail-OSG: diXhcMoVM1le0n8gkUK9RtUwGKq4Z0Luol8N2qnIiYaWgIA uZyfdHwSiifgzK.bRPHLIy9r.PWz1RX_SyHrOQj1ctmbA2FiQcxZZjfSxrqJ wZyDbuqwwkkCcBRWBueEzZy6waX__QIz9VE5JfZfSRGCstu7xFhb6mKjtBjc BtcbtnCMiqgEQGD.m8_95KsOR0xXyEh_sBp_v5XtErsUN_ifHOzYJCDJYGlI kpQPWgzAzivdYmngrXYpicowgvUcaHuoO40ILVlff3.I37b69hgr0X0qATPp GToxRNgKkBVfBAQa.QizX7oIjSF1aHP2kNyv4KV67jBAMqCHG6ok-
X-Yahoo-Newman-Property: ymail-3
Message-ID: <4C66F67C.2080406@caucho.com>
Date: Sat, 14 Aug 2010 13:03:08 -0700
From: Scott Ferguson <ferg@caucho.com>
User-Agent: Thunderbird 2.0.0.24 (X11/20100411)
MIME-Version: 1.0
To: John Tamplin <jat@google.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>
In-Reply-To: <AANLkTimqvQGJab-XdMuRFE8M2eB_xn_ipJZoNDuc28R2@mail.gmail.com>
Content-Type: text/plain; charset="UTF-8"; format="flowed"
Content-Transfer-Encoding: 8bit
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: Sat, 14 Aug 2010 20:02:40 -0000
John Tamplin wrote: > On Sat, Aug 14, 2010 at 5:09 AM, Anne van Kesteren <annevk@opera.com > <mailto:annevk@opera.com>> wrote: > > On Fri, 13 Aug 2010 23:16:14 +0200, Ian Hickson <ian@hixie.ch > <mailto:ian@hixie.ch>> wrote: > > 2010/8/12 Ian Fette (イアンフェッティ) <ifette@google.com > <mailto:ifette@google.com>>: > > > That said, here's the proposal: > > > This seems overly complex. [...] > > > Agreed. I would really like to avoid having so much features in > the initial deployment. > > > [The following is quick-and-dirty code I wrote on the spot, so don't > pick it apart -- it is just to illustrate the point that it isn't that > complicated] > > For a simple sender which doesn't negotiate any extensions and sends > only text in unfragmented frames, it looks like this: > > Connection::sendMessage(char* utf8, int utf8len) { 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: 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. 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 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 c) class BinaryMessageOutputStream { write(byte []buffer, int offset, int length); close(); } d) class TextMessageWriter { write(char []buffer, int offset, int length); close(); } 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); } 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. -- Scott > writeByte(0xC0 | TEXT_FRAME); > if (utf8len >= 127) { > writeByte(127); > writeUnsignedLong(utf8len); > } else { > writeByte(utf8len); > } > writeBytes(utf8, utf8len); > } > > For a receiver, there is additional complication because of the need > to support fragmented messages, but that has been accepted as a > requirement. It isn't much worse: > > Connection::readFrame) { > int frameType = getByte(); > int opcode = frameType & 0xF; > if (opcode != TEXT_FRAME) // error, discard, whatever > long length = getByte(); > if (length == 127) { > length = getUnsignedLong(); > } > switch (frameType & 0xC0) { > case 0x80: // initial frame of fragmented message > if (state == IN_MESSAGE) // error > state = IN_MESSAGE; > int messageLength = getUnsignedLong(); > bufLen = messageLength ? messageLength : DEFAULT_BUFFER_SIZE; > buf = new char[bufLen]; > bufIdx = 0; > // fallthrough > case 0x00: // intermediate frame of fragmented message > if (state != IN_MESSAGE) // error > growBufferIfNeeded(length); > getBytes(buf + bufIdx, length); > bufIdx += length; > break; > case 0x40: // final frame of fragmented message > if (state != IN_MESSAGE) // error > // fallthrough > case 0xC0: // unfragmented message > growBufferIfNeeded(length); > getBytes(buf + bufIdx, length); > deliverUtf8TextMessage(buf, bufIdx + length); // receiver is > responsible for freeing > state = NOT_IN_MESSAGE; > buf = 0; > bufLen = 0; > break; > } > } > > Connection::growBufferIfNeeded(int length) { > if (buf && bufLen >= bufIdx + length) return; > int newBufLen = (bufLen == 0) ? length : bufLen * 2; > char* newbuf = new char[newBufLen]; > if (buf) { > memcpy(newbuf, buf, bufIdx); > delete[] buf; > } > buf = newBuf; > bufLen = newBufLen; > } > > Given the requirement for fragmentation support, it isn't clear how > you make it a lot simpler. Note that the parts dealing with the frame > structure are just as simple as in the sender case. > > -- > John A. Tamplin > Software Engineer (GWT), Google > ------------------------------------------------------------------------ > > _______________________________________________ > hybi mailing list > hybi@ietf.org > https://www.ietf.org/mailman/listinfo/hybi >
- Re: [hybi] Framing Take VI (a compromise proposal) Patrick McManus
- Re: [hybi] Framing Take VI (a compromise proposal) Scott Ferguson
- [hybi] Framing Take VI (a compromise proposal) Ian Fette (イアンフェッティ)
- Re: [hybi] Framing Take VI (a compromise proposal) Ian Hickson
- Re: [hybi] Framing Take VI (a compromise proposal) Ian Fette (イアンフェッティ)
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Bjoern Hoehrmann
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Takeshi Yoshino
- Re: [hybi] Framing Take VI (a compromise proposal) Takeshi Yoshino
- Re: [hybi] Framing Take VI (a compromise proposal) Willy Tarreau
- Re: [hybi] Framing Take VI (a compromise proposal) Anne van Kesteren
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Greg Wilkins
- Re: [hybi] Framing Take VI (a compromise proposal) Ian Fette (イアンフェッティ)
- Re: [hybi] Framing Take VI (a compromise proposal) Greg Wilkins
- Re: [hybi] Framing Take VI (a compromise proposal) Takeshi Yoshino
- Re: [hybi] Framing Take VI (a compromise proposal) Greg Wilkins
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Dave Cridland
- Re: [hybi] Framing Take VI (a compromise proposal) Dave Cridland
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Greg Wilkins
- Re: [hybi] Framing Take VI (a compromise proposal) Patrick McManus
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Ian Fette (イアンフェッティ)
- Re: [hybi] Framing Take VI (a compromise proposal) Dave Cridland
- Re: [hybi] Framing Take VI (a compromise proposal) Douglas Otis
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Thomson, Martin
- Re: [hybi] Framing Take VI (a compromise proposal) gustav trede
- Re: [hybi] Framing Take VI (a compromise proposal) Ian Fette (イアンフェッティ)
- Re: [hybi] Framing Take VI (a compromise proposal) Thomson, Martin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Thomson, Martin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Scott Ferguson
- Re: [hybi] Framing Take VI (a compromise proposal) Scott Ferguson
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin
- Re: [hybi] Framing Take VI (a compromise proposal) Dave Cridland
- Re: [hybi] Framing Take VI (a compromise proposal) John Tamplin