Re: [quicwg/base-drafts] Unidirectional Streams (#643)
ekr <notifications@github.com> Thu, 22 June 2017 19:10 UTC
Return-Path: <bounces+848413-a050-quic-issues=ietf.org@sgmail.github.com>
X-Original-To: quic-issues@ietfa.amsl.com
Delivered-To: quic-issues@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 4F32F1293DB for <quic-issues@ietfa.amsl.com>; Thu, 22 Jun 2017 12:10:02 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.021
X-Spam-Level:
X-Spam-Status: No, score=-2.021 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=0.001, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (1024-bit key) header.d=github.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id DC2ZLXZ6EEqH for <quic-issues@ietfa.amsl.com>; Thu, 22 Jun 2017 12:09:58 -0700 (PDT)
Received: from o11.sgmail.github.com (o11.sgmail.github.com [167.89.101.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 5A148129466 for <quic-issues@ietf.org>; Thu, 22 Jun 2017 12:09:58 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=github.com; h=from:reply-to:to:cc:in-reply-to:references:subject:mime-version:content-type:content-transfer-encoding:list-id:list-archive:list-post:list-unsubscribe; s=s20150108; bh=Bf9RKNfJnqmRK683BFElHbuIYtg=; b=Esqp+KfUpdnAkcu7 iz/SmvYiXX6gxIlsi+MGIGKNmNR8XWhGXx0Hcua6WGiWFk/kN2ewFv+ZlK1iGMmv XciNnMWi1XX45Uh+MD6hlf9CQVXyB6DcfGw7XafQOwfgvBDCgMk3qiQd9MDlh9bi SI917O/QKZwrkMJruC6mb9q1qyQ=
Received: by filter0617p1mdw1.sendgrid.net with SMTP id filter0617p1mdw1-24624-594C15E1-47 2017-06-22 19:09:21.63907822 +0000 UTC
Received: from github-smtp2a-ext-cp1-prd.iad.github.net (github-smtp2a-ext-cp1-prd.iad.github.net [192.30.253.16]) by ismtpd0002p1iad1.sendgrid.net (SG) with ESMTP id aEYcPARST_mn4k1ZpxwzsQ for <quic-issues@ietf.org>; Thu, 22 Jun 2017 19:09:21.580 +0000 (UTC)
Date: Thu, 22 Jun 2017 12:09:19 -0700
From: ekr <notifications@github.com>
Reply-To: quicwg/base-drafts <reply+0166e4aba6620a12518bdf639e5b1555f9f57740142b1bd692cf000000011563d7df92a169ce0e21ecbf@reply.github.com>
To: quicwg/base-drafts <base-drafts@noreply.github.com>
Cc: Subscribed <subscribed@noreply.github.com>
Message-ID: <quicwg/base-drafts/pull/643/review/45794120@github.com>
In-Reply-To: <quicwg/base-drafts/pull/643@github.com>
References: <quicwg/base-drafts/pull/643@github.com>
Subject: Re: [quicwg/base-drafts] Unidirectional Streams (#643)
Mime-Version: 1.0
Content-Type: multipart/alternative; boundary="--==_mimepart_594c15df2a7c3_7e6a3fc42e989c34582e6"; charset="UTF-8"
Content-Transfer-Encoding: 7bit
Precedence: list
X-GitHub-Sender: ekr
X-GitHub-Recipient: quic-issues
X-GitHub-Reason: subscribed
X-Auto-Response-Suppress: All
X-GitHub-Recipient-Address: quic-issues@ietf.org
X-SG-EID: l64QuQ2uJCcEyUykJbxN122A6QRmEpucztpreh3Pak3qsbUaRrDHTfK08O61bmos2RyN0i1ZC3aLEF PJoSd0aDGufogPGDi3LlF+kd+yR25ik0vUJfBCdMQXjwSBcDHwxJbJ29/FEnvY5VSZawCHYLPwMbKh 4SBbvYeLPosOkI6+pUzWEk7iq3kQr+YwnVHK1+wF+0b/JodtlkLTQ7s3Sg==
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic-issues/JXp1uSDAc5x-LSqwzvrxBaoZ0mg>
X-BeenThere: quic-issues@ietf.org
X-Mailman-Version: 2.1.22
List-Id: Notification list for GitHub issues related to the QUIC WG <quic-issues.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/quic-issues>, <mailto:quic-issues-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/quic-issues/>
List-Post: <mailto:quic-issues@ietf.org>
List-Help: <mailto:quic-issues-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/quic-issues>, <mailto:quic-issues-request@ietf.org?subject=subscribe>
X-List-Received-Date: Thu, 22 Jun 2017 19:10:02 -0000
ekr commented on this pull request.
This seems like a good start
> # Streams: QUIC's Data Structuring Abstraction {#streams}
-Streams in QUIC provide a lightweight, ordered, and bidirectional byte-stream
-abstraction modeled closely on HTTP/2 streams {{?RFC7540}}.
+Streams in QUIC provide a lightweight, ordered, and unidirectional byte-stream.
nit: "and" is unnecessary here.
>
-Stream ID 0 (0x0) is reserved for the cryptographic handshake. Stream 0 MUST
-NOT be used for application data, and is the first client-initiated stream.
+Stream ID 0 (0x0) in both directions is reserved for the cryptographic
Nit: "0x0" is unnecessary here. People know what 0 is.
>
-Stream ID 0 (0x0) is reserved for the cryptographic handshake. Stream 0 MUST
-NOT be used for application data, and is the first client-initiated stream.
+Stream ID 0 (0x0) in both directions is reserved for the cryptographic
+handshake. Both client and server send cryptographic handshake messages on
+their stream 0, which is bound into a bidirectional channel. Stream 0 MUST NOT
I'm not sure you need to say "bound into a bidirectional channel". you just send on one and receive on the other.
> @@ -2337,13 +2338,21 @@ Stream IDs are usually encoded as a 32-bit integer, though the STREAM frame
stream ID are zero.
-## Life of a Stream
+## Stream States
+
+Endpoints do not coordinate the creation of streams; they are created
+unilaterally by either endpoint.
by the endpoint which will be sending on them. I know you say that below.
> @@ -2337,13 +2338,21 @@ Stream IDs are usually encoded as a 32-bit integer, though the STREAM frame
stream ID are zero.
-## Life of a Stream
+## Stream States
+
+Endpoints do not coordinate the creation of streams; they are created
+unilaterally by either endpoint.
+
+A stream sender controls the state of its streams; the state of a stream is only
+affected by frames that are sent by the sending endpoint. However,
Isn't this going to be wrong if you are going to allow receiver RST?
> @@ -2337,13 +2338,21 @@ Stream IDs are usually encoded as a 32-bit integer, though the STREAM frame
stream ID are zero.
-## Life of a Stream
+## Stream States
+
+Endpoints do not coordinate the creation of streams; they are created
+unilaterally by either endpoint.
+
+A stream sender controls the state of its streams; the state of a stream is only
+affected by frames that are sent by the sending endpoint. However,
And in any case, isn't the window part of the state?
> | |
+--------+
+ |
+ send STREAM with FIN flag
+ send RST_STREAM
+ |
+ v
+ +--------+
+ | |
+ | closed |
+ | |
+ +--------+
+~~~
This seems like it's a bug in the current state machine too, but there's clearly a difference between FIN and RST because the sender still has to retransmit when it has sent FIN. I guess you could claim that these are substates, but now that you've simplified this piece of the state machine, I think adding them explicitly here would make sense.
>
-### idle
+### The "idle" State
I think I would write separate state descriptions for each side. Let me know if you want help.
> -described in {{stream-id}}. A RST_STREAM frame, or a STREAM frame with the FIN
-flag set also causes a stream to become "half-closed".
-
-An endpoint might receive MAX_STREAM_DATA or STREAM_BLOCKED frames on
-peer-initiated streams that are "idle" if there is loss or reordering of
-packets. Receiving these frames also causes the stream to become "open".
-
-An endpoint MUST NOT send a STREAM or RST_STREAM frame for a stream ID that is
-higher than the peers advertised maximum stream ID (see
-{{frame-max-stream-id}}).
-
+Sending a STREAM or RST_STREAM frame causes the identified stream to become
+"open" for a sending endpoint. New streams use the next available stream
+identifier, as described in {{stream-id}}. An endpoint MUST NOT send a STREAM
+or RST_STREAM frame for a stream ID that is higher than the peers advertised
+maximum stream ID (see {{frame-max-stream-id}}).
Can you say what the other side does in this case?
>
-### half-closed (remote) {#state-hc-remote}
+A stream becomes "closed" at the receiving endpoint when all data is received
+and a STREAM frame with a FIN flag is received or when a RST_STREAM frame is
+received.
I think it would be helpful to reorder these, i.e.,
"A stream becomes "closed" at the receiving endpoint
when an RST_STREAM frame is received. when all data is received
and a STREAM frame with a FIN flag is received"
Because as-is it is ambiguous if you just read this section in isolation
> -
-### closed {#state-closed}
-
-The "closed" state is the terminal state for a stream.
-
-Once a stream reaches this state, no frames can be sent that mention the stream.
-Reordering might cause frames to be received after closing, see
-{{state-hc-remote}}.
+An endpoint could continue receiving frames for the stream even after the stream
+is closed for sending if packets are reordered. At the receiving endpoint,
+retransmissions of data in STREAM frames, or retransmissions of STREAM_BLOCKED
+and RST_STREAM frames might arrive after the stream becomes "closed". At the
+sending endpoint, MAX_STREAM_DATA frames might be received after the stream
+becomes "closed". Frames received on a "closed" stream SHOULD be discarded. An
+endpoint MAY choose to limit the period over which it ignores frames and treat
+frames that arrive after this time as being in error.
This graf is a bit confusing, because you first say that you should discard frames on a closed stream and then you say that you may instead ignore them only after some time. Why would I want to do that? What would I do if I didn't ignore them?
> -treated as a connection error of type HTTP_RST_CONTROL_STREAM. When a message
-control stream terminates cleanly, if the last frame on the stream was
-truncated, this MUST be treated as a connection error (see HTTP_MALFORMED_* in
-{{http-error-codes}}).
-
-Pairs of streams must be utilized sequentially, with no gaps. The data stream
-is opened at the same time as the message control stream is opened and is closed
-after transferring the body. The data stream is closed immediately after
-sending the request headers if there is no body.
+the stream management. An HTTP request/response consumes a pair of streams in
+each direction.
+
+Aside from the connection control stream, the beginning of each stream starts
+with a short stream header. This stream header is used to identify the type of
+stream and to link the stream to another stream as necessary. See
+{{stream-header}} for more details on the stream header.
Nit: I would put this cite after the first sentence.
> -sending the request headers if there is no body.
+the stream management. An HTTP request/response consumes a pair of streams in
+each direction.
+
+Aside from the connection control stream, the beginning of each stream starts
+with a short stream header. This stream header is used to identify the type of
+stream and to link the stream to another stream as necessary. See
+{{stream-header}} for more details on the stream header.
+
+\[Editor's Note: the following is clearly busted. Requests and responses can't
+reliably be cancelled as a result of this change. We will need QPACK/QCRAM for
+this to work.] Request, response and push streams contain HPACK data which
+manipulates connection-level state. Therefore, these streams MUST NOT be closed
+with a stream-level error.
+
+Streams must be opened sequentially, with no gaps. Data streams SHOULD be
Isn't this already a QUIC invariant?
> -sending the request headers if there is no body.
+the stream management. An HTTP request/response consumes a pair of streams in
+each direction.
+
+Aside from the connection control stream, the beginning of each stream starts
+with a short stream header. This stream header is used to identify the type of
+stream and to link the stream to another stream as necessary. See
+{{stream-header}} for more details on the stream header.
+
+\[Editor's Note: the following is clearly busted. Requests and responses can't
+reliably be cancelled as a result of this change. We will need QPACK/QCRAM for
+this to work.] Request, response and push streams contain HPACK data which
+manipulates connection-level state. Therefore, these streams MUST NOT be closed
+with a stream-level error.
+
+Streams must be opened sequentially, with no gaps. Data streams SHOULD be
"New streams use the next available stream"
> +~~~~~
+
+After the stream header, response streams contain a sequence of frames (see
+{{http-framing-layer}}).
+
+If a response stream header identifies a stream that is not a request stream, or
+it references a request stream that already has an associated response stream,
+the connection MUST be terminated with an HTTP_UNMATCHED_RESPONSE error.
+
+
+### Data Streams {#stream-data}
+
+Data streams are opened by both client and server. Data streams carry the
+payload body of requests or responses.
+
+The stream header for a response stream contains the type octet, which is set to
I think you mean "data stream"
> +| Type (8) |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Stream ID (32) |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~~~
+
+After the stream header, data streams contain the octets of the payload body.
+Data streams do not carry frames.
+
+Data streams MUST reference a request or response stream. The referenced stream
+MUST include a HAS_BODY frame. If a data stream is received that references a
+stream of a different type, the referenced stream does not include a HAS_BODY
+frame, or another data stream already references the identified steam, then the
+connection MUST be terminated with a HTTP_UNMATCHED_BODY error. Note that due
+to reordering of packets, the referenced stream or HAS_BODY frame might not have
+been received when the data stream is opened.
So, the implementation here is:
- If has_body frame received, then process stream
- Else, block until either
(a) has_body frame received, in which case process stream
(b) fin/rst received in which case send error
> -
-An HTTP request/response exchange fully consumes a pair of streams. After
-sending a request, a client closes the streams for sending; after sending a
-response, the server closes its streams for sending and the QUIC streams are
-fully closed.
+response may contain zero or more header blocks on the response stream
+containing the message headers of informational (1xx) HTTP responses (see
+{{!RFC7230}}, Section 3.2 and {{!RFC7231}}, Section 6.2).
+
+A message that contains a payload body includes a HAS_BODY frame immediately
+after the first header block. This indicates that another stream will include
+the payload body. A data stream is opened to carry the payload body. The data
+stream MUST be closed immediately after sending the body. If the message does
+not contain a body, a data stream MUST NOT be opened and the HAS_BODY message
+MUST NOT be sent. The "chunked" transfer encoding defined in Section 4.1 of
+{{!RFC7230}} MUST NOT be used.
I wonder if it would make more sense to have the pointer to the body stream here rather than a back pointer for the dependency
> @@ -401,6 +538,17 @@ All frames have the following format:
## Frame Definitions {#frames}
+### HAS_BODY {#frame-has-body}
+
+The HAS_BODY frame (type=0x0) indicates that the HTTP message contains a payload
+body. It is sent after the initial header block on a request, response, or push
+stream.
+
+The HAS_BODY frame has no flags and is always empty. A HAS_BODY frame with a
+non-empty payload or flags that are set MUST be treated as a
+HTTP_MALFORMED_HAS_BODY error.
Might it be easier to just put this field in the header block
> +
+ Request Stream/Push ID:
+ : A 32-bit stream ID or Push ID that identifies the request. If the PUSH flag
+ is set, this refers to a Push ID included in a PUSH_PROMISE frame (see
+ {{frame-push-promise}}); if the PUSH flag is cleared, this refers to a
+ request by its stream ID.
+
+ Error Code:
+ : A 32-bit error code indicating why the response is not desired.
+
+A CANCEL_REQUEST frame always contains an 8 octet payload. A server MUST treat
+a CANCEL_REQUEST frame payload that is other than 8 octets in length, or a
+CANCEL_REQUEST frame that identifies a stream that doesn't carry a valid request
+as an HTTP_MALFORMED_CANCEL_REQUEST error. Note however that due to packet
+reordering, a CANCEL_REQUEST frame could arrive before the request stream that
+it references is opened.
This is weird text. Isn't it always the case that if you receive an unexpected frame structure you are sad?
> +ID MUST be treated as a HTTP_MALFORMED_PRIORITY error.
+
+The length of a PRIORITY frame is 9 octets. A PRIORITY frame with any other
+length MUST be treated as a connection error of type HTTP_MALFORMED_PRIORITY.
+
+
+### CANCEL_REQUEST {#frame-cancel-request}
+
+The CANCEL_REQUEST frame (type=0x3) is used to request cancellation of a request
+prior to the response stream being created. This frame can be used to cancel
+both outstanding requests initiated by a client and server push requests that
+are initiated with a PUSH_PROMISE.
+
+The frame identifies a client-initiated request by the stream ID that carried
+the request; a server push request is identified by Push ID (see
+{{frame-push-promise}}).
Don't you mean "request ID" that's what you are using for dependencies
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/quicwg/base-drafts/pull/643#pullrequestreview-45794120
- [quicwg/base-drafts] Unidirectional Streams (#643) Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… MikkelFJ
- Re: [quicwg/base-drafts] Unidirectional Streams (… MikkelFJ
- Re: [quicwg/base-drafts] Unidirectional Streams (… MikkelFJ
- Re: [quicwg/base-drafts] Unidirectional Streams (… MikkelFJ
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… MikkelFJ
- Re: [quicwg/base-drafts] Unidirectional Streams (… MikkelFJ
- Re: [quicwg/base-drafts] Unidirectional Streams (… MikkelFJ
- Re: [quicwg/base-drafts] Unidirectional Streams (… Lucas Pardue
- Re: [quicwg/base-drafts] Unidirectional Streams (… Lucas Pardue
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Mark Nottingham
- Re: [quicwg/base-drafts] Unidirectional Streams (… Mike Bishop
- Re: [quicwg/base-drafts] Unidirectional Streams (… Mark Nottingham
- Re: [quicwg/base-drafts] Unidirectional Streams (… Mike Bishop
- Re: [quicwg/base-drafts] Unidirectional Streams (… ekr
- Re: [quicwg/base-drafts] Unidirectional Streams (… Christian Huitema
- Re: [quicwg/base-drafts] Unidirectional Streams (… Mike Bishop
- Re: [quicwg/base-drafts] Unidirectional Streams (… Christian Huitema
- Re: [quicwg/base-drafts] Unidirectional Streams (… Subodh Iyengar
- Re: [quicwg/base-drafts] Unidirectional Streams (… MikkelFJ
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Mike Bishop
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Mike Bishop
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson
- Re: [quicwg/base-drafts] Unidirectional Streams (… Martin Thomson