Re: [hybi] With deflate-stream, Close frame doesn't work as an end of data marker

Takeshi Yoshino <tyoshino@google.com> Wed, 09 March 2011 14:01 UTC

Return-Path: <tyoshino@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 298D13A69D5 for <hybi@core3.amsl.com>; Wed, 9 Mar 2011 06:01:26 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -105.722
X-Spam-Level:
X-Spam-Status: No, score=-105.722 tagged_above=-999 required=5 tests=[AWL=0.254, BAYES_00=-2.599, FM_FORGED_GMAIL=0.622, HTML_MESSAGE=0.001, 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 c3f9AqBKDSP1 for <hybi@core3.amsl.com>; Wed, 9 Mar 2011 06:01:24 -0800 (PST)
Received: from smtp-out.google.com (smtp-out.google.com [216.239.44.51]) by core3.amsl.com (Postfix) with ESMTP id 57BF13A69BE for <hybi@ietf.org>; Wed, 9 Mar 2011 06:01:24 -0800 (PST)
Received: from wpaz13.hot.corp.google.com (wpaz13.hot.corp.google.com [172.24.198.77]) by smtp-out.google.com with ESMTP id p29E2ela001062 for <hybi@ietf.org>; Wed, 9 Mar 2011 06:02:40 -0800
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=google.com; s=beta; t=1299679360; bh=3wheOmFkX0RB0KjQYtP5PRI39sY=; h=MIME-Version:In-Reply-To:References:From:Date:Message-ID:Subject: To:Cc:Content-Type; b=AjVDpBHaFCL8YrZLsNzT3/UjNN9nPC9TG6s2ssgopViw/Fi3brgBvfsKR6HMIowac fkX071+gqMh4V/y+bZolw==
Received: from iwn33 (iwn33.prod.google.com [10.241.68.97]) by wpaz13.hot.corp.google.com with ESMTP id p29E2crG022315 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <hybi@ietf.org>; Wed, 9 Mar 2011 06:02:38 -0800
Received: by iwn33 with SMTP id 33so601287iwn.13 for <hybi@ietf.org>; Wed, 09 Mar 2011 06:02:38 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=beta; h=domainkey-signature:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc:content-type; bh=5R58R1v0yOhYRkfD1pxd1M8kznkuXwJylv36NZTxrfc=; b=Vb/9V1q8s+UO+hTBgNxXKuXEcnJqsfkXVVodLqTaynSMjGaQZroTknsdxD53434VQO QOnOyb4gZopUuZEPK3/g==
DomainKey-Signature: a=rsa-sha1; c=nofws; d=google.com; s=beta; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type; b=Z8vTX3H23jN+HgYc9Jppl8NanzFClW6PIu0vE+xhDQdMMMIvNEOy37R8PHBusPI+G0 fabLRKh4RQw6R5sMZEZQ==
Received: by 10.42.146.131 with SMTP id j3mr3175861icv.505.1299679358175; Wed, 09 Mar 2011 06:02:38 -0800 (PST)
MIME-Version: 1.0
Received: by 10.231.14.141 with HTTP; Wed, 9 Mar 2011 06:02:18 -0800 (PST)
In-Reply-To: <4D777402.3010101@warmcat.com>
References: <OF27A0495D.2C32912B-ON8825784E.00342DCE-8825784E.00367A85@playstation.sony.com> <4D775D69.8010808@warmcat.com> <AANLkTi=4_jp_=QffTsTbrUxjzGTRTv5F4Ao=5ZBpc2FB@mail.gmail.com> <4D777402.3010101@warmcat.com>
From: Takeshi Yoshino <tyoshino@google.com>
Date: Wed, 09 Mar 2011 23:02:18 +0900
Message-ID: <AANLkTinJPtZ6Y9oVZt3cMm3rjRMM_EPryS+pNwmcB8hP@mail.gmail.com>
To: Andy Green <andy@warmcat.com>
Content-Type: multipart/alternative; boundary="90e6ba21243d7749be049e0d2e2e"
X-System-Of-Record: true
Cc: hybi@ietf.org, Yutaka_Takeda@playstation.sony.com
Subject: Re: [hybi] With deflate-stream, Close frame doesn't work as an end of data marker
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: Wed, 09 Mar 2011 14:01:26 -0000

Hi Andy,

On Wed, Mar 9, 2011 at 21:35, Andy Green <andy@warmcat.com> wrote:

> On 03/09/2011 12:06 PM, Somebody in the thread at some point said:
>
> Hi -
>
>
>     Having implemented this now, I don't see the problem using
>>    Z_PARTIAL_FLUSH as the standard seems to recommend normally, and
>>    then Z_FULL_FLUSH when sending the close packet, and disabling any
>>    further packet issue on that connection.  So I don't think Takeshi's
>>    issue is more than an implementation problem, I'd welcome being
>>    educated if I missed any point.
>>
>>
>> Maybe, exhaustive (to be strict, recv with big buffer) recv call in your
>> code drains all the deflated data arrived (everything including Huffman
>> codes for some preceding frames, ones for close frame, 3 bit header
>> BFINAL=0 BTYPE=00 and 00 00 ff ff) from the TCP stack.
>>
>
> Yes on both rx / inflate and tx / deflate case libwebsockets will always
> loop and go back to in/deflate() for the rest if the callback handling that
> indicates the zlib call filled its spill buffer (suggesting that it very
> likely has more to spill).  So if there are multiple buffers full of stuff
> to flush in both rx or tx path they will always all get sent on the wire or
> sent to the user callback as uncompressed rx data before moving on.
>
> You can see the loop here for the tx path
>
> http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/parsers.c#n1378
>
> After issuing specifically the CLOSE opcode packet like that, the
> connection state is changed so nothing more can be emitted on the socket,
> and this works reliably to issue the CLOSE to the far end for sure without
> further zlib housekeeping traffic or any other traffic going out.
>
>
I'm still not sure if we're on the same table. Please allow me to explain my
thoughts again. Sorry if i'm misunderstanding your point.

Sending a close frame is not a problem. What I'm taking as a (small, but)
problem is receiving a close frame. "Trailing bytes after Close frame" in
Yutaka's post doesn't mean "any further packet" or "any other traffic going"
on the WebSocket layer. It means trailing bytes generated by zlib.

Your code luckily drained the "close, 3 bit header, 00 00 ff ff" which
contains octets generated by zlib for performing Z_FULL_FLUSH. But please
imagine someone split them into two TCP packets e.g. "close codes, 3 bit
header" and "00 00 ff ff" and inserted some delay between them. Your
callback is run with eff_buf.token filled with "... close codes, 3 bit
header", and after that your callback is run again with eff_buf.token = "00
00 ff ff".

On the first run of callback, zlib can decompress all of close frame octets,
but there's 00 00 ff ff left in the TCP stack, so it's not ready to issue
close(2) on the socket.


>
>  Yes, since it's rare that octets for a single WebSocket frame are put in
>> separate TCP packets and delivered to application layer separately
>> (requiring separate recv-call), this is not a big problem. But with
>> in-frame compression, it becomes perfect.
>>
>
> I think you must handle extreme compression cases anyway to keep an eye on
> latency if nothing else, consider he sends 200K of 0x00 and the compressor
> run-length encodes it, you receive a handful of compressed code bytes but
> must sit looping through 200K of decompressed content that represents one
> message.  Or you pass in 1K of high quality random and 3K of codes comes out
> of the compressor.
>
> Like I say I think keeping framing out of compression is okay, just
> deflate-stream babbling after close isn't any reason for it AFAICS.
>
> -Andy
>