Re: Implicitly opened streams and exposing stream IDs

Dmitri Tikhonov <> Thu, 05 April 2018 14:34 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 8197B12D94A for <>; Thu, 5 Apr 2018 07:34:46 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.9
X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (2048-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id ISXADeqXgtpr for <>; Thu, 5 Apr 2018 07:34:44 -0700 (PDT)
Received: from ( [IPv6:2607:f8b0:400d:c0d::22d]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by (Postfix) with ESMTPS id CCEE112D7F9 for <>; Thu, 5 Apr 2018 07:34:43 -0700 (PDT)
Received: by with SMTP id l18so27138944qtj.1 for <>; Thu, 05 Apr 2018 07:34:43 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20150623; h=date:from:to:cc:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to:user-agent; bh=vZsQAoISp2RfYF0xYySwZmO8RkJ3pPJaAxE6FCQvR8c=; b=TlZ7nSEDZvMMFQRai2IeK0S0VkwoLbFP6X2R0dLWp6JtVkC//SNGqHP9GHWZW76iBd W83/jnoGqZcmCBKL+h3KbntrpKiRy/2GKoJwTa86k+/9h8FgcQ9ndMqiJGKv0ptS/ZI2 WMy5DxLhaqURTMEq5x8gfV1nvbErXdoobi9TuQGQ85/NWhaQBEzE/9wmjvoUIr+AeVO6 jYjiU8MwlYbjH0trn8FUgy3t/YQTk35whEGvA2q6MQJ+/E7kyfEQtHBuGm4rj/jLtLTR kSbrKHs18zGGkhJCxOPVlaSxlbvVRNntWZ8js5AsPVRKYV2a4oekFVfWxd8Bq0tLlhsa zJXw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id :mail-followup-to:references:mime-version:content-disposition :in-reply-to:user-agent; bh=vZsQAoISp2RfYF0xYySwZmO8RkJ3pPJaAxE6FCQvR8c=; b=fi6rpwZ5JWNQ5tyAGz1nDzAU+jWXVI/umWUCLC1r4uVr8djqquAJTRxPFobTY+CHqY wgZ125kiCqWXh4gsWedRu/l+JA1k1OvnCS+hp0IU8oT+3jgQuAOFt9HYtttguQtXHGOM RS/iorPozEkCwmQZTBb/zrJlU1vGWJaeUr7mkX7H589wzOOJ2vu+pbTd3LMHaj8ERaaz vJY5Ml+PFE0tiC+5X0i469bdNfm1tRdHZzSqzLYz6wZZuKovUN6MUgNeig2qZ1saA+Ue iyl4We1vqQuAchUa1KQ3W0fcZfVrf+gi7N+4aE6xRHiZ29JcTpvQ2w6XtUzlmDuBypZ/ RPAw==
X-Gm-Message-State: ALQs6tAS2q2gWZF3iU7DpKDSHDRmpTY5W7cwKVd0yPqUhwguN4BJiJxM Ih/OZqY7mI1T232Qgr7c1IFPxg==
X-Google-Smtp-Source: AIpwx4+ssIlHiswmMlzuYd5YPRuTzyIZYbzxBemE61pK7lO98mI9v1W7ngjDwVPVqxva8/imxVz9Zw==
X-Received: by with SMTP id m90mr33779677qtd.33.1522938882796; Thu, 05 Apr 2018 07:34:42 -0700 (PDT)
Received: from ubuntu-dmitri ( []) by with ESMTPSA id n30sm6364296qtb.93.2018. (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 Apr 2018 07:34:42 -0700 (PDT)
Date: Thu, 05 Apr 2018 10:34:37 -0400
From: Dmitri Tikhonov <>
To: "Lubashev, Igor" <>
Cc: "" <>, "" <>
Subject: Re: Implicitly opened streams and exposing stream IDs
Message-ID: <20180405143436.GA19079@ubuntu-dmitri>
Mail-Followup-To: "Lubashev, Igor" <>, "" <>, "" <>
References: <> <> <> <>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <>
User-Agent: Mutt/1.5.24 (2015-08-30)
Archived-At: <>
X-Mailman-Version: 2.1.22
Precedence: list
List-Id: Main mailing list of the IETF QUIC working group <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Thu, 05 Apr 2018 14:34:46 -0000

The switch to MUST would cater to a single use case: a control stream
opened at the beginning of the connection.  Presumably, the following
streams would not be useable without the control stream (as is the case
with HQ), so waiting for the control stream frames is OK.

The downside is that the stream creator no longer has the flexibility
to use its legit set of Stream IDs as it sees fit, precluding some use
cases (see issue #634 [1]) -- perhaps even the very use of QUIC for
some protocols!

The API problem Marten describes seems like a non-issue:  There are
two sets of APIs:
    - User code / HQ; and
    - HQ / QUIC.

Stream IDs do not have to be exposed in the former:  The user does not
care about them, as these things are just your regular HTTP messages.
In the HQ / QUIC API, on the other hand, expose away!  Streams have
IDs, the QUIC transport draft talks about them, the IDs have meanings --
it only makes sense that the layer that uses the QUIC objects directly
can use Stream IDs.  Why not?!

  - Dmitri.


On Thu, Apr 05, 2018 at 02:06:12PM +0000, Lubashev, Igor wrote:
> I agree. I would like to see MUST there as well.
> -----Original Message-----
> From: Marten Seemann []
> Received: Thursday, 05 Apr 2018, 8:51AM
> To: Lubashev, Igor []
> CC: []
> Subject: Re: Implicitly opened streams and exposing stream IDs
> Hi Igor,
> This is exactly the change I'm proposing. Currently, the draft says that you SHOULD create streams in order (section 9.2). I'd like to change that SHOULD to a MUST.
> Only if in order stream creation is a requirement, this question becomes an API design question.
> Regards,
> Marten
> On Thu, Apr 5, 2018 at 7:14 PM Lubashev, Igor <<>> wrote:
> This is not a QUIC transport draft concern. This is a question of QUIC library API design. Your API may choose to have Accept return streams in order. My API may choose to have Accept return streams as they come in (and expose steam IDs). As long as the transport draft requires that streams are CREATED in order (as it does now), both API designs are valid.
> It would be a matter of a very different draft to standardize QUIC APIs (like we have for POSIX) so an application can be easily ported to use a different vendor's QUIC libraries.
> - Igor
> -----Original Message-----
> From: Marten Seemann [<>]
> Received: Monday, 02 Apr 2018, 7:43AM
> To: QUIC WG [<>]
> Subject: Implicitly opened streams and exposing stream IDs
> Recently, the implicit opening of streams (i.e. that when a receiver receives a frame for stream N+4, it can assume that stream N was already opened, but the packet might have been reordered) was removed from the draft. I think this change has some consequences that we haven't discussed so far.
> For the purpose of writing some pseudocode, I'm assuming a QUIC API that provides an AcceptStream() method, but the conclusions will be the same for a callback-based API.
>   *   If QUIC has implicit stream opening, AcceptStream() would return the streams in order (and if a frame opening stream N+4 is received before stream n is opened, AcceptStream() will first return stream N and then stream N+4).
>   *   Without implicit stream opening, AcceptStream() just returns whatever stream is received first. Streams might be returned in arbitrary order, if the peer doesn't open streams consecutively or if packets are reordered.
> Now imagine an application protocol where the first unidirectional stream opened by the client is a control stream, and all higher unidirectional streams are data streams. The application on the server side needs to find out which stream is the control stream, because it needs to be handled separately.
> With implicit stream opening, the server code would be:
>     control_stream = AcceptStream() // is guaranteed to open the first stream
>     // handle the control stream
>      while true:
>          stream = AcceptStream()
>          // handle the data stream
> and without implicit stream opening:
>     while true:
>         stream = AcceptStream()
>         if stream.ID() == kControlStreamID:
>             // handle the control stream
>         else:
>             // handle the data stream
> In this case, after accepting a stream, we first have to check the stream ID, since there's no guarantee if the control stream will actually be received first.
> For this stream mapping, it seems like the removal of implicitly opened streams implies that QUIC has to expose stream IDs to the application layer. I'm not sure if this was intended when making the change, especially since we're considering to change HQ such that it doesn't rely on QUIC stream IDs any more.
> We only manage to avoid the problem described here in our HTTP mapping, because the HTTP control streams are unidirectional and the request streams are bidirectional, and can therefore be told apart by their directionality. However, as a general transport protocol, other applications built on top of QUIC will have to find some way to deal with it.