[2] [DFN[[RUBYB[[[ストリーム]]]@en[stream]]]]は、[[HTTP/2接続]]中の独立した[[フレーム]]の[RUBYB[双方向の流れ]@en[bidirectional flow]] (列) です [SRC[>>1, >>3]]。
一組の[[要求]]と[[応答]]を送受信するために使います。
[[ストリーム]]は [[HTTP/2]] で新たに導入された概念です。

;; [136] 一つの[[接続]]内で複数の[[ストリーム]]を使うことにより、
複数の[[要求]]を[[並行]]して処理できます。

* 仕様書

[REFS[
- [1] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-2.2>
- [3] '''[CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-5>'''
-- [71] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-5.4.2>
-- [75] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-5.5>
- [126] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.1>
- [128] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.2>
- [77] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.5.2>
- [130] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.8>
- [134] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-6.9>
- [82] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-7>
- [85] [CITE@en[RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)]] ([TIME[2015-05-15 10:14:54 +09:00]] 版) <https://tools.ietf.org/html/rfc7540#section-8.3>
]REFS]

* プロトコル

[4] [[HTTP/2接続]]は、[[並行]]して複数の[[フレーム]]を開くことができます。
つまり複数の[[ストリーム]]の[[フレーム]]を混在させて送受信できます。 [SRC[>>3]]

[5] [[ストリーム]]は、[[サーバー]]と[[クライアント]]のどちらからも確立したり閉じたりできますし、
一方だけで使ったり、両方で使ったりできます。 [SRC[>>3]]

[7] [[HTTP/2接続]]の開始の時点では、[[ストリーム]]はありません。

[HISTORY[
[86] ただし理論上は
[[HTTP/1.1]] から [CODE(HTTP)@en[[[Upgrade: h2c]]]] で [[HTTP/2]]
で切り替えた場合は、[[ストリーム識別子]] [CODE[[[0x1]]]] が使われた状態となります。

;; [[HTTP/2接続]]参照。
]HISTORY]

[65] [[エンドポイント]]は、各[[ストリーム]]の次の情報を保持します。
[FIG(list members)[
:[[ストリーム識別子]] [SRC[>>3]]:[[符号無し]]31ビット[[整数]]。
:開始した [[peer]]:[[ストリーム識別子]]が[[奇数]]なら[[クライアント]]、
[[偶数]]なら[[サーバー]]です [SRC[>>3]]。
:状態:状態遷移図上の状態のいずれかです (>>8)。 [[closed]] 状態には付随していくつかのフラグがあります。
:[[親ストリーム]]:[[依存性木]]上の[[親]]です。必ず1つ存在します。
[[依存ストリーム]]の逆方向の関係です。
:[[依存ストリーム]]群:[[依存性木]]上の[[子]]の[[集合]]です。
0個[[以上]]の[[ストリーム]]が含まれます。
:[[重み]]:[[親ストリーム]]から本[[ストリーム]]への[[依存性木]]上の[[枝]]に割り当てられた、
優先度を表す値です。
:処理開始済み:データを[[アプリケーション層]]に伝えたかどうかを表すフラグです。
[CODE(HTTP)@en[[[GOAWAY]]]] [[フレーム]]送信時に使います。
:[CODE(HTTP)@en[[[RST_STREAM]]]] タイムスタンプ:[CODE(HTTP)@en[[[RST_STREAM]]]]
[[フレーム]]再送判定に使います。
:[[ストリームフロー制御窓]]:
]FIG]

[6] [[ストリーム]]における[[フレーム]]の順序には意味があり、
[[受信者]]は受信した順序で処理する必要があります。 [SRC[>>3]]

[FIG(short list)[
- [[ストリーム識別子]]
- [[ストリームエラー]]
- [[フロー制御]]
- [[ストリーム優先度]]
]FIG]

* 状態

[8] [[エンドポイント]]は、[[ストリーム]]の[RUBYB[状態]@en[state]]を保持します。
[SRC[>>3]]

[9] [[ストリーム]]の状態は、[[エンドポイント]]がそれぞれ保持しているもので、
[[フレーム]]の転送中は [[peer]] と異なることがあります。 [SRC[>>3]]
また (local) と (remote) のような対となる状態になっていることもあります。

[50] 状態は、[[フレーム]]の送受信で遷移します。単一の[[フレーム]]で複数の状態遷移が発生することもあります。

[63] 未知の[[フレーム型]]の[[フレーム]]は無視して捨てなければ[['''なりません''']]
[SRC[>>3, >>75]]。しかし後述の通り、
指定された[[フレーム]]の種類以外はエラーとなるとの規定もあります。
どちらの規定が優先されるのかは不明ですが、この両文が [[RFC]]
では隣に並んでいるので、無視が優先されると[[エスパー]]できます。

;; [76] 捨てられる[[フレーム]]も、他の要件には影響することがあります。
[[ヘッダーリスト]]や[[フレーム]]を参照。

[144] [CODE[[[GOAWAY]]]] [[フレーム]]を受信したら、
その[[最終ストリーム識別子]]よりも大きな[[ストリーム]]について
[CODE[[[RST_STREAM]]]] [[フレーム]]を受信したものとして処理するべきと思われます。

[66] 次の状態があります。
[FIG(list short)[
- [[idle]]
- [[reserved (local)]]
- [[reserved (remote)]]
- [[open]]
- [[half-closed (local)]]
- [[half-closed (remote)]]
- [[closed]]
]FIG]

[FIG(flow)[
:idle:[[idle]]
:v:
:>>:1
:->:reserved.local
:->:reserved.remote
:->:open
:->:closed

:reserved.local:[[reserved (local)]]
:->:half.remote
:->:closed

:reserved.remote:[[reserved (remote)]]
:>>:4
:->:half.local
:->:closed

:open:[[open]]
:v:
:>>:1
:->:half.local
:->:half.remote
:->:closed

:half.remote:[[half-closed (remote)]]
:v:
:->:closed

:half.local:[[half-closed (local)]]
:>>:4
:->:closed

:closed:[[closed]]
:v:
:>>:2
]FIG]

[89] 状態毎に、送信できる[[フレーム型]]の制約があります。
[FIG(list)[
,*状態,*[CODE(HTTP)@en[[[DATA]]]],*[CODE(HTTP)@en[[[HEADERS]]]],*[CODE(HTTP)@en[[[PRIORITY]]]],*[CODE(HTTP)@en[[[RST_STREAM]]]],*[CODE(HTTP)@en[[[SETTINGS]]]],*[CODE(HTTP)@en[[[PUSH_PROMISE]]]],*[CODE(HTTP)@en[[[PING]]]],*[CODE(HTTP)@en[[[GOAWAY]]]],*[CODE(HTTP)@en[[[WINDOW_UPDATE]]]],*[CODE(HTTP)@en[[[CONTINUATION]]]],*その他
,*[[idle]]                ,×,○,○,×,×,×,×,×,×,×,×
,*[[reserved (local)]]    ,×,○,○,○,×,×,×,×,×,×,×
,*[[reserved (remote)]]   ,×,×,○,○,×,×,×,×,○,×,×
,*[[open]]                ,○,○,○,○,×,○,×,×,○,○,×
,*[[half-closed (local)]] ,×,×,○,○,×,×,×,×,○,△,×
,*[[half-closed (remote)]],○,○,○,○,×,○,×,×,○,○,×
,*[[closed]]              ,×,×,○,×,×,×,×,×,×,△,×
,*[[接続]]                ,×,×,×,×,○,×,○,○,○,×,×
]FIG]

;; 各状態においても更に細かい制約があるかもしれません。

** idle

[10] [[ストリーム]]は、作成されると [DFN[[[idle]]]] 状態となります [SRC[>>3]]。

;; [11] [[エンドポイント]]は、[[peer]] と協調せずとも自身で[[ストリーム]]を作成できます
[SRC[>>3]]。相手に伝わるまでは、一方のみに[[ストリーム]]が存在する状態となります。

[22] 送信できる[[フレーム]]の種類の制約は明記されていませんが、
[CODE[[[HEADERS]]]] と [CODE[[[PRIORITY]]]] しか送信できないと見られます。

[12] 送受信する[[フレーム]]の種類により、次のような状態遷移があります [SRC[>>3]]。
[FIG(list)[
- [13] [CODE[[[HEADERS]]]] [[フレーム]]を送信または受信すると、 [[open]]
に遷移します。
- [14] 他の[[ストリーム]]で [CODE[[[PUSH_PROMISE]]]] [[フレーム]]を送信し、
その [[Promised Stream ID]] で本[[ストリーム]]が示されていれば、 [[reserved (local)]]
に遷移します。
- [15] 他の[[ストリーム]]で [CODE[[[PUSH_PROMISE]]]] [[フレーム]]を受信し、
その [[Promised Stream ID]] で本[[ストリーム]]が示されていれば、 [[reserved (remote)]]
に遷移します。
- [64] 本[[ストリーム]]を開始した [[peer]] がより大きな[[ストリーム識別子]]の[[ストリーム]]を使用
([[フレーム]]を送受信) したら、 [[closed]] に遷移します。
]FIG]

[16] [CODE[[[HEADERS]]]] と [CODE[[[PRIORITY]]]] 以外の[[フレーム]]を受信したら、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>3]]。

;; [137] [CODE[[[RST_STREAM]]]] や [CODE[[[WINDOW_UPDATE]]]] も[[接続エラー]]となるようです。

[139] 実際には [CODE[[[WINDOW_UPDATE]]]] を受信したら [[Firefox]] は[[ストリームエラー]]
[CODE[[[PROTOCOL_ERROR]]]] とし、 [[Chrome]] は無視するようです。
[TIME[2015-10-10T09:02:08.700Z]]

[142] [[Firefox]] も [[Chrome]] も [CODE[[[RST_STREAM]]]]
を受信してもエラーとはしないようです。 ([[closed]] に遷移しているものと思われます。)
[TIME[2015-10-10T11:59:21.100Z]]

** reserved (local)

[17] [CODE[[[PUSH_PROMISE]]]] [[フレーム]]で約束すると、
[[ストリーム]]は [DFN[[[reserved (local)]]]] 状態となります [SRC[>>3]]。

[23] [CODE[[[HEADERS]]]], [CODE[[[RST_STREAM]]]], [CODE[[[PRIORITY]]]] 
以外を送信しては[['''なりません''']] [SRC[>>3]]。

[19] 送受信する[[フレーム]]の種類により、次のような状態遷移があります [SRC[>>3]]。
[FIG(list)[
- [20] [CODE[[[HEADERS]]]] [[フレーム]]を送信すると、 [[half-closed (remote)]] に遷移します。
- [21] [CODE[[[RST_STREAM]]]] [[フレーム]]を送信または受信すると、 [[closed]] に遷移します。
]FIG]

[24] [CODE[[[RST_STREAM]]]], [CODE[[[PRIORITY]]]], [CODE[[[WINDOW_UPDATE]]]] 以外の[[フレーム]]を受信したら、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>3]]。

** reserved (remote)

[25] [DFN[[[reserved (remote)]]]] 状態は、[[ストリーム]]が [[peer]] により予約されていることを表します [SRC[>>3]]。

[29] [CODE[[[RST_STREAM]]]], [CODE[[[WINDOW_UPDATE]]]], [CODE[[[PRIORITY]]]]
以外を送信しては[['''なりません''']] [SRC[>>3]]。

[26] 送受信する[[フレーム]]の種類により、次のような状態遷移があります [SRC[>>3]]。
[FIG(list)[
- [27] [CODE[[[HEADERS]]]] [[フレーム]]を受信すると、 [[half-closed (local)]] に遷移します。
- [28] [CODE[[[RST_STREAM]]]] [[フレーム]]を送信または受信すると、 [[closed]] に遷移します。
]FIG]

[30] [CODE[[[HEADERS]]]], [CODE[[[RST_STREAM]]]], [CODE[[[PRIORITY]]]]
以外の[[フレーム]]を受信したら、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>3]]。

** open

[31] [DFN[[[open]]]] 状態では、任意の[[フレーム]]の送受信ができます。

[34] 送信できる[[フレーム]]の種類の制約はありません [SRC[>>3]]。

[32] 本状態に遷移することになった[[フレーム]]の種類や本状態で送受信する[[フレーム]]の種類により、次のような状態遷移があります [SRC[>>3]]。
[FIG(list)[
- [33] [CODE[[[END_STREAM]]]] フラグが設定された[[フレーム]]を送信すると、
[[half-closed (local)]] 状態に遷移します。
- [35] [CODE[[[END_STREAM]]]] フラグが設定された[[フレーム]]を受信すると、
[[half-closed (remote)]] 状態に遷移します。
- [36] [CODE[[[RST_STREAM]]]] [[フレーム]]を送信または受信すると、 [[closed]] に遷移します。
]FIG]

** half-closed (local)

[37] [DFN[[[half-closed (local)]]]] 状態では、メッセージを送信できませんが、受信するかもしれません。

[38] [CODE[[[WINDOW_UPDATE]]]], [CODE[[[PRIORITY]]]], [CODE[[[RST_STREAM]]]]
以外の[[フレーム]]を送信することはできません [SRC[>>3]]。

;; [42] こちらは閉じた (送信しない) 状態ですが、 [[peer]] はまだ送信できる状態ですから、
データを受信する準備は継続しなければなりません。
すなわち、 [CODE(HTTP)@en[[[WINDOW_UPDATE]]]] [[フレーム]]を適宜送信する必要があります
[SRC[>>3]]。

;; [122] 本状態へ遷移させた [CODE(HTTP)@en[[[END_STREAM]]]] フラグ付き
[CODE(HTTP)@en[[[HEADERS]]]] [[フレーム]]の続きの [CODE(HTTP)@en[[[CONTINUATION]]]]
[[フレーム]]を送信することはできます。

[39] 本状態で送受信する[[フレーム]]の種類により、次のような状態遷移があります [SRC[>>3]]。
[FIG(list)[
- [40] [CODE[[[END_STREAM]]]] フラグが設定された[[フレーム]]を受信すると、
[[closed]] 状態に遷移します。
- [41] [CODE[[[RST_STREAM]]]] [[フレーム]]を送信または受信すると、 [[closed]] に遷移します。
]FIG]

** half-closed (remote)

[43] [DFN[[[half-closed (remote)]]]] 状態は、 [[peer]] が[[フレーム]]の送信をもう行わない[[ストリーム]]を表します [SRC[>>3]]。

[46] 任意の[[フレーム]]を送信できます [SRC[>>3]]。 

[44] この状態になると、[[受信者フロー制御窓]]を維持する義務はありません [SRC[>>3]]。

[47] 本状態で送受信する[[フレーム]]の種類により、次のような状態遷移があります [SRC[>>3]]。
[FIG(list)[
- [48] [CODE[[[END_STREAM]]]] フラグが設定された[[フレーム]]を送信すると、
[[closed]] 状態に遷移します。
- [49] [CODE[[[RST_STREAM]]]] [[フレーム]]を送信または受信すると、 [[closed]] に遷移します。
]FIG]

[45] [CODE[[[WINDOW_UPDATE]]]] [SRC[>>3, >>134]], [CODE[[[RST_STREAM]]]], [CODE[[[PRIORITY]]]]
以外の[[フレーム]]を受信したら、
[[ストリームエラー]] [CODE[[[STREAM_CLOSED]]]] としなければ[['''なりません''']] [SRC[>>3]]。

;; [120] ただし、本状態に遷移させた [CODE(HTTP)@en[[[HEADERS]]]] [[フレーム]]に引き続き
[CODE(HTTP)@en[[[CONTINUATION]]]] [[フレーム]]を受信する場合は除きます。

** closed

[51] [DFN[[[closed]]]] 状態は、最終的な状態です [SRC[>>3]]。

[93] この状態での動作は、次の各フラグによって変わります。
[FIG(list)[
- [94] [CODE[[[RST_STREAM]]]] 送信 (タイムスタンプ)
- [95] [CODE[[[END_STREAM]]]] 送信 (タイムスタンプ)
- [98] [CODE(HTTP)@en[[[RST_STREAM]]]] 受信済み
- [105] [CODE(HTTP)@en[[[END_STREAM]]]] 受信済み
]FIG]

[96] この状態に遷移したら、次のようにします。
[FIG(steps)[
= [90] [CODE(HTTP)@en[[[RST_STREAM]]]] [[フレーム]]を自身が送信したことにより遷移した場合は、「[CODE(HTTP)@en[[[RST_STREAM]]]] 送信」タイムスタンプを[[現在時刻]]に設定します。
= [91] [CODE(HTTP)@en[[[END_STREAM]]]] フラグが設定された[[フレーム]]を自身が送信したことにより遷移した場合は、「[CODE(HTTP)@en[[[END_STREAM]]]] 送信」タイムスタンプを[[現在時刻]]に設定します。
= [97] [CODE(HTTP)@en[[[RST_STREAM]]]] [[フレーム]]を受信したことにより遷移した場合は、
「[CODE(HTTP)@en[[[RST_STREAM]]]] 受信済み」フラグを設定します。
= [104] [CODE(HTTP)@en[[[END_STREAM]]]] フラグが設定された[[フレーム]]を受信したことにより遷移した場合は、
「[CODE(HTTP)@en[[[END_STREAM]]]] 受信済み」フラグを設定します。
]FIG]

[99] この状態で[[フレーム]]を受信したら、次のようにします。
[FIG(steps)[
= [106] 「[CODE(HTTP)@en[[[END_STREAM]]]] 受信済み」フラグが設定されていれば、
== [54] [[接続エラー]] [CODE[[[STREAM_CLOSED]]]] としなければ[['''なりません''']] [SRC[>>3]]。
停止します。
= [102] 「[CODE(HTTP)@en[[[RST_STREAM]]]] 受信済み」フラグが設定されていれば、
== [103] [CODE(HTTP)@en[[[PRIORITY]]]] 以外の[[フレーム]]なら、
=== [53] [[ストリームエラー]] [CODE[[[STREAM_CLOSED]]]] としなければ[['''なりません''']] [SRC[>>3]]。停止します。
= [100] [CODE(HTTP)@en[[[RST_STREAM]]]] [[フレーム]]なら、
== [101] 「[CODE(HTTP)@en[[[RST_STREAM]]]] 受信済み」フラグを設定します。
= [107] [CODE(HTTP)@en[[[DATA]]]] [[フレーム]]か [CODE(HTTP)@en[[[HEADERS]]]] [[フレーム]]なら、
== [108] [CODE(HTTP)@en[[[END_STREAM]]]] フラグが設定されていれば、
=== [109] 「[CODE(HTTP)@en[[[END_STREAM]]]] 受信済み」フラグを設定します。
= [112] 「[CODE[[[END_STREAM]]]] 送信」タイムスタンプが設定されていれば、
== [114] [CODE(HTTP)@en[[[WINDOW_UPDATE]]]] [[フレーム]] [SRC[>>3, >>134]] か
[CODE(HTTP)@en[[[RST_STREAM]]]] [[フレーム]]なら、
=== [92] 十分な時間が経過していれば、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としても構いません [SRC[>>3]]。
=== [113] そうでなければ、無視しなければ[['''なりません''']] [SRC[>>3]]。停止します。
= [57] 「[CODE[[[RST_STREAM]]]] 送信」タイムスタンプが設定されている場合、
== [115] 十分な時間が経過していれば、
=== [116] エラーとしても構いません [SRC[>>3]]。
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] が適切そうです。停止します。
== [58] 1[[RTT]] を過ぎているなら、
=== [72] 改めて [CODE[[[RST_STREAM]]]] [[フレーム]]を送信しても構いません [SRC[>>71]]。
== [59] [[フロー制御]]対象の[[フレーム]] ([CODE[[[DATA]]]]) なら、
=== [119] [[接続フロー制御窓]]の計算に含めます。 [SRC[>>3]]
([[フレーム]]が無視されるとしても、相手が [CODE[[[RST_STREAM]]]]
を受信する前に[[フロー制御窓]]で数えてから送信しているはずだからです。 [SRC[>>3]])
== [61] [CODE[[[PUSH_PROMISE]]]] [[フレーム]]なら、
=== [60] 指定された[[ストリーム]]を [[reserved (remote)]] 状態とします。
(そちらの[[ストリーム]]は不要なら別途 [CODE[[[RST_STREAM]]]] が必要です。) [SRC[>>3]]
== [55] 無視しなければ[['''なりません''']] [SRC[>>3]] 。停止します。
= [110] [CODE(HTTP)@en[[[PRIORITY]]]] [[フレーム]]なら、
== [124] [[依存性木]]から[[ストリーム]]が削除済みなら、無視します [SRC[>>3]]。
== [111] 処理する[['''べき''']]です [SRC[>>3]]。
= [117] それ以外なら、
== [118] [[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] とする[['''べきです''']] [SRC[>>3]]。
]FIG]

[138] [[Chrome]] も [[Firefox]] も、 [CODE[[[STREAM_CLOSED]]]]
は送信せずに無視するだけのように見えます。 [TIME[2015-10-03T12:06:36.700Z]]

[52] [CODE[[[PRIORITY]]]] [[フレーム]]以外を送信しては[['''なりません''']] [SRC[>>3]]。

;; [123] 本状態へ遷移させた [CODE(HTTP)@en[[[END_STREAM]]]] フラグ付き
[CODE(HTTP)@en[[[HEADERS]]]] [[フレーム]]の続きの [CODE(HTTP)@en[[[CONTINUATION]]]]
[[フレーム]]を送受信することはできます。

;; [18] [CODE[[[RST_STREAM]]]] [[フレーム]]の送信によって [[closed]] に遷移すると、
[[peer]] との状態遷移の時間差が原因で、
この状態となった後に[[フレーム]]を受信する可能性もあります [SRC[>>3]]。
[[peer]] が既に送信したり、
送信準備をしたりして、取り消せなかった[[フレーム]]が到着する場合があります [SRC[>>3]]。
[CODE[[[RST_STREAM]]]] [[フレーム]]送信後も[[フレーム]]を受信する準備をしておかなければ[['''なりません''']] [SRC[>>71]]。

;; [56] 自身が [CODE[[[END_STREAM]]]] や [CODE[[[RST_STREAM]]]]
を送信してから相手が受信するまでの時間差があるため、その間に
[CODE[[[WINDOW_UPDATE]]]] や [CODE[[[RST_STREAM]]]] を受信する可能性があります。 [SRC[>>3]]

;; [62] [[RFC]] は [[closed]] を1つの状態として表していますが、
実際には何により遷移してきたかで処理を分ける必要があり、また時間経過などで処理が変わる可能性があり、
複雑です。しかも [[RFC]] は「無視する (無視するとは言っていない)」のような変な書き方になっていて難解です。
>>99 は [[RFC]] の規定を出来る限り矛盾せずに整理した結果ですが、
これ以外の解釈もあり得るかもしれません。

[73] (>>58 を除き) [CODE[[[RST_STREAM]]]] [[フレーム]]を複数送信する[['''べきではありません''']] [SRC[>>71]]。

[140] [[Firefox]] は [CODE[[[HEADERS]]]] を受信する前に [CODE[[[RST_STREAM]]]] 
を受信したら[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] とします。
[[Chrome]] はそれ自体はエラーとせずに無視しますが、その直後に
[CODE[[[HEADERS]]]] を受信したら[[ストリームエラー]] [CODE[[[PROTOCOL_ERROR]]]]
とします。 [TIME[2015-10-10T11:46:38.200Z]]

[141] [[Firefox]] も [[Chrome]] も [CODE[[[END_STREAM]]]] 後の
[CODE[[[RST_STREAM]]]] は無視するようです。相当する[[要求]]に対する[[応答]]も、
[[ネットワークエラー]]とはなりません。 [TIME[2015-10-10T11:47:36.400Z]]

[125] [[closed]] 状態の[[ストリーム]]は、一定時間後、[[依存性木]]から削除できます。

;; [[依存性木]]を参照。

* 並行性

[67] [[設定]] [DFN[[CODE[[[SETTINGS_MAX_CONCURRENT_STREAMS]]]]]] ([CODE[[[0x3]]]])
は、[[送信者]]が認める並行[[ストリーム]]の最大数を表します [SRC[>>77, >>3]]。

[79] 初期状態は無制限です [SRC[>>77]]。

[78] 不必要に並列性を損なわないため、
この値を 100 [[未満]]とする[RUBYB[べきではありません]@en[recommend]]。 [SRC[>>77]]

[80] 値0は、特別な意味は持ちません。新しい[[ストリーム]]の生成が認められないことを表します。
しかし[[サーバー]]は短い時間に限ってのみ 0 を使う[['''べきです''']]。
[[要求]]を受け付けたくない時は、[[接続]]を閉じる方が適切です。 [SRC[>>77]]

[68] この設定は、[[受信者]]が開始することを認められた[[ストリーム]]の数を示しています。
従って[[クライアント]]は[[サーバー]]の開始する[[ストリーム]]の最大数を指定でき、
[[サーバー]]は[[クライアント]]の開始する[[ストリーム]]の最大数を指定できます。 [SRC[>>3, >>77]]

[81] ここで数に含まれるのは、 [[open]], [[half-closed (local)]], [[half-closed (remote)]]
のいずれかの状態にある[[ストリーム]]です [SRC[>>3]]。

[69] [CODE[[[HEADERS]]]] [[フレーム]]を受信した時、
[[ストリーム]]数上限を超えるなら、
[CODE[[[PROTOCOL_ERROR]]]] または [CODE[[[REFUSED_STREAM]]]]
の[[ストリームエラー]]としなければ[['''なりません''']]。
どちらを選ぶかは、自動的な再試行を有効にしたいかに依ります。 [SRC[>>3]]

[70] [CODE[[[SETTINGS_MAX_CONCURRENT_STREAMS]]]] の値が現在の[[ストリーム]]の数よりも小さくなる場合は、
新しい値を超えた[[ストリーム]]を閉じることもできますし、
[[ストリーム]]が完了するまで待つこともできます。 [SRC[>>3]]

[84] [[Chrome]] は[[接続序文]]で 1000 を値として設定します。
[TIME[2015-10-20T08:19:27.400Z]]

[87] [[プッシュメッセージ購読集合資源]]で使うことがあります。

* 接続の切断

[74] [[HTTP/2接続]]を参照。

[131] [CODE(HTTP)@en[[[GOAWAY]]]] [[フレーム]]を受信したら、以後新しい[[ストリーム]]を作成しては[['''なりません''']] [SRC[>>130]]。

;; [132] しかし既存の[[ストリーム]]の送受信処理は、継続できます。

[133] [CODE(HTTP)@en[[[GOAWAY]]]] [[フレーム]]の送信後であっても、
受信して処理を継続しなければなりません。無視する[[ストリーム]]の[[フレーム]]も、
[[ヘッダーブロック]]や[[フロー制御]]の処理は行わなければなりません [SRC[>>130]]。

* [CODE[END_STREAM]] フラグ

[127] [CODE(HTTP)@en[[[DATA]]]] [[フレーム]]や
[CODE(HTTP)@en[[[HEADERS]]]] [[フレーム]]の
[DFN[[CODE[[[END_STREAM]]]]]] ([CODE[[[0x1]]]] = 第0ビット)
フラグは、設定されていれば当該[[ストリーム]]の当該[[送信者]]からの最後の[[フレーム]]であることを表します。 [SRC[>>126, >>128]]

;; [129] 実際には [CODE(HTTP)@en[[[CONTINUATION]]]] [[フレーム]]も直後に送信されるかもしれません
[SRC[>>128]]。

[121] [CODE(HTTP)@en[[[END_STREAM]]]] フラグが設定された[[フレーム]]を送受信すると、
[[closed]] 状態に遷移します [SRC[>>3]]。本フラグの送受信が他の[[フレーム]]の処理にも影響します。

;; 状態遷移の項を参照。

[135] [CODE(HTTP)@en[[[CONNECT]]]] では、 [[TCP]] [CODE[[[FIN]]]]
フラグに相当します [SRC[>>85]]。

* 誤り符号 [CODE[STREAM_CLOSED]]

[83] [DFN[[CODE[[[STREAM_CLOSED]]]]]] ([CODE[[[0x5]]]]) は、
[[ストリーム]]が [[half-closed]] の後に[[フレーム]]を受信したことを示します [SRC[>>82]]。
