/
346.txt
457 lines (354 loc) · 26.1 KB
/
346.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
[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接続]]の開始の時点では、[[ストリーム]]はありません。ただし
[[HTTP/1.1]] から [CODE(HTTP)@en[[[Upgrade:]] [[h2c]]]] で [[HTTP/2]]
で切り替えた場合は、[[ストリーム識別子]] [CODE[[[0x1]]]] が使われた状態となります。
;; [[HTTP/2接続]]参照。
[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]]
* 接続の切断
[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]]。