[47] [[HTTP/2]] の[DFN[[RUBYB[[[設定]]]@en[setting]]]]は、[[エンドポイント]]におけるプロトコルの動作に関する[[引数]]を [[peer]] に共有する仕組みです。

* 仕様書

[REFS[
- [43] [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>
- [36] [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-3.2>
- [37] [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-3.5>
- [44] [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-4.1>
- [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-4.2>
- [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-5.5>
- [4] '''[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>'''
- [28] [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>
- [29] [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-10.5>
- [31] [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-10.8>
- [33] [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-11.3>
- [46] [CITE[Hypertext Transfer Protocol version 2 (HTTP/2) Parameters]] ([TIME[2015-05-20 07:51:31 +09:00]] 版) <https://www.iana.org/assignments/http2-parameters/http2-parameters.xml#settings>
]REFS]

* 意味

[5] [CODE[[[SETTINGS]]]] [[フレーム]] ([[フレーム型]] [CODE[[[0x4]]]])
は、通信に関わる引数の設定情報を伝達するものです [SRC[>>4]]。またその[RUBYB[返答]@en[acknowledge]]にも使います [SRC[>>4]]。

[6] [CODE[[[SETTINGS]]]] の[[引数]]を[DFN[[RUBYB[設定]@en[setting]]]]ともいいます [SRC[>>4]]。

[7] [[設定]]は、[[エンドポイント]]の性質を説明するものであり、[[折衝]]するものではありません。
両 [[peer]] は同じ[[引数]]の違う値を使うこともあります。 [SRC[>>4]]

[27] なお[[設定]]の値や[[設定]]に依存した機能の挙動は、[[fingerprinting vector]] です [SRC[>>31]]。

* 構文

[16] [[ストリーム識別子]]は、 [CODE[[[0x0]]]] でなければ[['''なりません''']] [SRC[>>4]]。
[[ストリーム]]にのみ[[設定]]を適用することはできません。

[12] 次の[[フラグ]]があります。
[FIG(list members)[
:[13] [DFN[[CODE[[[ACK]]]]]] フラグ ([CODE[[[0x1]]]] = 第0ビット):
設定されていれば、 [[peer]] の [CODE[[[SETTINGS]]]] [[フレーム]]を受信し適用したことを
[[acknowledge]] することを表します。 [SRC[>>4]]
]FIG]

[45] 他の[[フラグ]]は 0 にしなければ[['''なりません''']]。
[[受信者]]は無視しなければ[['''なりません''']]。 [SRC[>>44]]

[FIG(packet)[
:width:8

= 1 [[ACK]]
= 1 0
= 1 0
= 1 0
= 1 0
= 1 0
= 1 0
= 1 0
]FIG]

[20] [[payload]] は、0個以上の[[引数]]の列です。各[[引数]]は、
[[符号無し]]16ビットの[RUBYB[識別子]@en[identifier]]欄と、
[[符号無し]]32ビットの[RUBYB[値]@en[value]]欄で構成されます。 [SRC[>>4]]
いずれも[[ネットワークバイト順]]です [SRC[>>43]]。

[FIG(railroad)[
= *
== 識別子
== 値
]FIG]

[14] [CODE[[[ACK]]]] フラグが設定されている場合は、 [[payload]] は空でなければ[['''なりません''']] [SRC[>>4]]。

;; [39] フラグが設定されていなくても空でも構いません。通常は意味がありませんが、
[[接続序文]]や [CODE(HTTP)@en[[[HTTP2-Settings:]]]] [[ヘッダー]]では空であっても
[CODE(HTTP)@en[[[SETTINGS]]]] [[フレーム]]が必須となっています。

* 文脈

[8] [CODE[[[SETTINGS]]]] [[フレーム]]は、[[接続]]の確立直後に両[[エンドポイント]]が[[接続序文]]の一部として送信しなければ[['''なりません''']] [SRC[>>37, >>4]]。

;; [[HTTP/2接続]]、[[HTTPS]]、[[接続序文]]も参照。

[38] [CODE(HTTP)@en[[[Upgrade: h2c]]]] [[要求メッセージ]]は、
[CODE(HTTP)@en[[[HTTP2-Settings:]]]] [[ヘッダー]]の値として
[CODE(HTTP)@en[[[SETTINGS]]]] [[フレーム]]をちょうど1つ送信しなければ[['''なりません''']]
[SRC[>>36]]。

[9] [CODE[[[SETTINGS]]]] [[フレーム]]は、
[[接続]]中必要に応じて送ることができます [SRC[>>4]]。

* 設定 (引数)

[22] 次の標準の[[設定]]があります。実装は、これらの[[設定]]すべてに対応しなければ[['''なりません''']]
[SRC[>>4]]。
[FIG(list)[
- [CODE[[[SETTINGS_HEADER_TABLE_SIZE]]]] ([CODE[[[0x1]]]])
- [CODE[[[SETTINGS_ENABLE_PUSH]]]] ([CODE[[[0x2]]]])
- [CODE[[[SETTINGS_MAX_CONCURRENT_STREAMS]]]] ([CODE[[[0x3]]]])
- [CODE[[[SETTINGS_INITIAL_WINDOW_SIZE]]]] ([CODE[[[0x4]]]])
- [CODE[[[SETTINGS_MAX_FRAME_SIZE]]]] ([CODE[[[0x5]]]])
- [CODE[[[SETTINGS_MAX_HEADER_LIST_SIZE]]]] ([CODE[[[0x6]]]])
]FIG]

[3] (新たな) [[設定]]を[[拡張]]の[[折衝]]に使う場合、既定値は当該拡張を無効としなければ[['''なりません''']] [SRC[>>1]]。

[34] [[IANA登録簿]] [SRC[>>46]] があります [SRC[>>33]]。
次の[[設定]]が登録されています。

[FIG(list)[
- [CODE[SETTINGS_ENABLE_CONNECT_PROTOCOL]] ([CODE[0x8]])
- [CODE(HTTP)@en[[[TLS_RENEG_PERMITTED]]]] ([CODE[[[0x10]]]])
]FIG]

[35] [CODE[0xf000]]-[CODE[0xffff]] は[[実験用]]に予約されています [SRC[>>33]]。

[48] [[IANA登録簿]]は [CODE[0x0000]] を [[RFC 7540]] を出典に予約しています [SRC[>>46]]。
しかし [[RFC 7540]] にそのような規定は見当たりません。

;; [50] >>49 に [[JSON]] 形式の一覧データファイルがあります。
[REFS[
- [49] [CITE@en[data-web-defs/http-frames.txt at master · manakai/data-web-defs]] ([TIME[2015-05-28 00:33:14 +09:00]] 版) <https://github.com/manakai/data-web-defs/blob/master/doc/http-frames.txt>
]REFS]

* 処理

[81] [[受信者]]は、[[設定]] [CODE[[[SETTINGS_MAX_FRAME_SIZE]]]]
より長いなら、[[接続エラー]] [CODE[[[FRAME_SIZE_ERROR]]]] としなければ[['''なりません''']]
[SRC[>>82]]。

[15] [[受信者]]は、 [CODE[[[SETTINGS]]]] [[フレーム]]の [CODE[[[ACK]]]] フラグが設定されていて、
[[payload]] の長さ欄の値が 0 でなければ、[[接続エラー]] [CODE[[[FRAME_SIZE_ERROR]]]]
としなければ[['''なりません''']] [SRC[>>4]]。

[17] [[受信者]]は、[[ストリーム識別子]]が [CODE[[[0x0]]]] でなければ、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]]
としなければ[['''なりません''']] [SRC[>>4]]。

[18] [[受信者]]は、[CODE[[[SETTINGS]]]] [[フレーム]]の形式が誤っているか不完全なら、
[[接続エラー]] [CODE[[[PROTOCOL_ERROR]]]] としなければ[['''なりません''']] [SRC[>>4]]。

[19] [[受信者]]は、[CODE[[[SETTINGS]]]] [[フレーム]]の [[payload]]
が 6 の[[倍数]]でなければ、
[[接続エラー]] [CODE[[[FRAME_SIZE_ERROR]]]] としなければ[['''なりません''']] [SRC[>>4]]。

[10] [CODE[[[SETTINGS]]]] [[フレーム]]の受信者は、
[CODE[[[ACK]]]] フラグが設定されていなければ、
可能な限りすぐに指定された[[引数]]を適用しなければ[['''なりません''']] [SRC[>>4]]。
新しい値により、既存の値を置き換えます [SRC[>>4]]。

[2] 未知の[[設定]]は、無視しなければ[['''なりません''']] [SRC[>>1, >>4]]。

[21] [[設定]]によっては、指定できる値に制約があり、
それを満たさなければ ([[RFC]] 上では) [[接続エラー]]となることがあります。
実際には黙って無視されるだけかもしれません。

;; 各[[設定]]の項を参照。

[11] [[設定]]は出現順に処理します。 [SRC[>>4]]

[23] [[設定]]の更新中に他の[[フレーム]]を処理しては[['''なりません''']] [SRC[>>4]]。

[24] すべての[[設定]]の処理を終えたら、直ちに [CODE[[[ACK]]]] フラグを設定した
[CODE[[[SETTINGS]]]] [[フレーム]]を送信しなければ[['''なりません''']] [SRC[>>4]]。

;; [40] [[接続序文]]の一部である [CODE(HTTP)@en[[[SETTINGS]]]]
[[フレーム]]でも必要です [SRC[>>37]]。

;; [41] [CODE(HTTP)@en[[[HTTP2-Settings:]]]] [[ヘッダー]]の [CODE(HTTP)@en[[[SETTINGS]]]]
[[フレーム]]に対しては、 [CODE(HTTP)@en[[[Upgrade: h2c]]]] に対する
[CODE(HTTP)[[[101]]]] [[応答]]をもって暗示的な [[acknowledgement]]
とみなされるため、送信しなくて構いません。送信は禁止されていませんが、
送信すると次の[[接続序文]]の [CODE(HTTP)@en[[[SETTINGS]]]]
[[フレーム]]に対する [[acknowledgement]] と解釈されてしまうと思われます。

[53] 未知の設定が指定された (そして無視された) 場合や、設定が1つも指定されなかった場合も、
[OODE[[[ACK]]]] を送る必要があります。 (そうしないとどの [CODE[[[SETTINGS]]]]
に対する [CODE[[[ACK]]]] か相手にわからなくなります。)

[25] [CODE[[[ACK]]]] フラグが設定された [CODE[[[SETTINGS]]]] [[フレーム]]を受信したら、
設定が適用されたことに依存できるようになります [SRC[>>4]]。

[42] どの [CODE(HTTP)@en[[[SETTINGS]]]] [[フレーム]]に対する [[acknowledgement]]
かを明示する方法はありません。[[送信者]]は、送信したことを覚えておき、
どれが [[acknowledge]] されたか判断する確認する必要があります。

[26] 十分な時間内に [[acknowledgement]] を受信しなければ、
[[接続エラー]] [DFN[[CODE[[[SETTINGS_TIMEOUT]]]]]] ([CODE[[[0x4]]]])
としても構いません [SRC[>>4, >>28]]。

[51] [[Chrome]] も [[Firefox]] も ([[接続序文]]も含め) そのようなタイムアウトは無いように見えます。
[TIME[2015-10-11T11:35:36.300Z]]

[52] [CODE[[[SETTINGS]]]] を送信していないのに [CODE[[[ACK]]]] 付き
[CODE[[[SETTINGS]]]] を受信したときどうするべきなのかは明記されていませんが、
[[Chrome]] でも [[Firefox]] でも黙って無視されます。 [TIME[2015-10-12T03:00:15.900Z]]

[30] [CODE[[[SETTINGS]]]] [[フレーム]]は、
意味もなく[[引数]]を変更したり、未定義の[[引数]]を設定したり、
同じ[[引数]]を何度も変更したりして無駄な処理をさせるために濫用できます。
[[エンドポイント]]は利用状況を監視して制限する[['''べきです''']]。
[[接続エラー]] [CODE[[[ENHANCE_YOUR_CALM]]]] としても構いません。 [SRC[>>29]]

[32] [CODE[[[SETTINGS]]]] [[フレーム]]の返信によって [[peer]] までの[[遅延]]が測定されると、
[[プライバシー]]上問題となることもあるかしれません [SRC[>>31]]。

* 実装

[54] [[Chrome]] も [[Firefox]] も[[接続序文]]と [CODE[[[ACK]]]]
以外では [CODE[[[SETTINGS]]]] を送らないように見えます。

;; [55] それ以外で送りたくなる場面はあるのでしょうか。
実装が無駄に複雑になるだけの気がしますが。。。