-
Notifications
You must be signed in to change notification settings - Fork 4
/
321.txt
244 lines (188 loc) · 12.9 KB
/
321.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
* 仕様書
[REFS[
- [1] '''[CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-5>'''
-- [49] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-5.8>
- [53] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-6.2>
]REFS]
* 構文
[8] [[フレーム]]は、次のような構造です [SRC[>>1]]。
[FIG(packet)[
:width:32
=1 [[FIN]]
=1 [[RSV1]]
=1 [[RSV2]]
=1 [[RSV3]]
=4 [[opcode]]
=1 [[マスク]]
=23 [[payload長]]
=32 [[マスクキー]]
=32... [[Payload Data]]
]FIG]
[FIG(list members)[
[FIGCAPTION[
[[フレーム]]
]FIGCAPTION]
:[DFN[[CODE[[[FIN]]]]]]:
[[メッセージ]]の最後の[RUBYB[断片]@en[fragment]]であるかどうかを示します。
[CODE[[[0]]]] は最後でないこと、 [CODE[[[1]]]] は最後であることを表します。
:[DFN[[CODE[[[RSV1]]]]]] ([DFN[[CODE[[[frame-rsv1]]]]]]):
[[拡張]]により規定される場合を除き、 [CODE[[[0]]]] でなければ[['''なりません''']]。
:[DFN[[CODE[[[RSV2]]]]]] ([DFN[[CODE[[[frame-rsv2]]]]]]):
[[拡張]]により規定される場合を除き、 [CODE[[[0]]]] でなければ[['''なりません''']]。
:[DFN[[CODE[[[RSV3]]]]]] ([DFN[[CODE[[[frame-rsv3]]]]]]):
[[拡張]]により規定される場合を除き、 [CODE[[[0]]]] でなければ[['''なりません''']]。
:[DFN[[CODE[[[opcode]]]]]]:
[[payload data]] の解釈を規定するものです。
:[DFN[[RUBYB[マスク]@en[mask]]]] ([DFN[[CODE[[[frame-masking-key]]]]]]):
[[payload data]] が[[マスク]]されるかどうかを示します。
[CODE[[[1]]]] は[[マスク]]されていること、[CODE[[[0]]]] は[[マスク]]されていないことを示します。
:[DFN[[RUBYB[payload長]@en[payload length]]]]:
[[payload data]] の長さを[[バイト]]単位で示します。
:[DFN[[RUBYB[[[マスクキー]]]@en[masking key]]]] ([DFN[[CODE[[[frame-masking-key]]]]]]):
[[マスク]]する際に使う32ビットの値です。[[マスク]]ビットが [CODE[[[1]]]]
であれば、本欄が存在します。 [CODE[[[0]]]] なら、存在しません。
:[DFN[[RUBYB[拡張データ]@en[extension data]]]]:
[[拡張]]により規定された長さと用途のデータです。[[拡張]]がなければ長さ0です。
:[DFN[[RUBYB[応用データ]@en[application data]]]]:
任意の[[応用]]のデータです。
]FIG]
[9] 次のような[[フレーム]]を受信したら、
[[WebSocket接続失敗]]を実行しなければ[['''なりません''']] [SRC[>>1]]。
[FIG(list)[
- [10] [CODE[[[RSV1]]]] が非 [CODE[[[0]]]] 値であり、[[拡張]]のいずれの規定にも拠っていない場合
- [11] [CODE[[[RSV2]]]] が非 [CODE[[[0]]]] 値であり、[[拡張]]のいずれの規定にも拠っていない場合
- [12] [CODE[[[RSV3]]]] が非 [CODE[[[0]]]] 値であり、[[拡張]]のいずれの規定にも拠っていない場合
- [13] 未知の [CODE[[[opcode]]]] の場合
]FIG]
* opcode
[14] [[データフレーム]] ([[非制御フレーム]]) の [[opcode]] には、
次のものがあります [SRC[>>1]]。
[FIG(list short)[
- [CODE[[[0]]]] - [[継続フレーム]]
- [CODE[[[1]]]] - [[テキストフレーム]]
- [CODE[[[2]]]] - [[バイナリーフレーム]]
- [CODE[[[3]]]] - 非制御フレームに予約
- [CODE[[[4]]]] - 非制御フレームに予約
- [CODE[[[5]]]] - 非制御フレームに予約
- [CODE[[[6]]]] - 非制御フレームに予約
- [CODE[[[7]]]] - 非制御フレームに予約
]FIG]
[44] [DFN[[RUBYB[[[制御フレーム]]]@en[control frame]]]]の [[opcode]] には、次のものがあります [SRC[>>1]]。
[FIG(list short)[
- [CODE[[[8]]]] - [[Closeフレーム]]
- [CODE[[[9]]]] - [[Pingフレーム]]
- [CODE[[[A]]]] - [[Pongフレーム]]
- [CODE[[[B]]]] - 制御フレームに予約
- [CODE[[[C]]]] - 制御フレームに予約
- [CODE[[[D]]]] - 制御フレームに予約
- [CODE[[[E]]]] - 制御フレームに予約
- [CODE[[[F]]]] - 制御フレームに予約
]FIG]
[45] [[制御フレーム]]は、状態を通信するために使うものです [SRC[>>1]]。
[51] 予約された [CODE[[[opcode]]]] は、[[拡張]]が使うことができます [SRC[>>49]]。
* payload
[18] [DFN[[RUBYB[payloadデータ]@en[payload data]]]]は、
[[拡張データ]]と[[応用データ]]を指します [SRC[>>1]]。
[47] [[payload長]]は、[[バイト]]単位の[[payloadデータ]]の長さを表すものです。
次のうち、最短の形を使わなければ[['''なりません''']]。 [SRC[>>1]]
[FIG(list)[
- [15] [CODE[0]]-[CODE[125]] なら、これが [[payload長]]です。
- [16] [CODE[126]] なら、次の2バイトが[[payload長]]の[[16ビット符号無し整数]]
([[ネットワークバイト順]]) です。
- [17] [CODE[127]] なら、次の8バイトが[[payload長]]の[[64ビット符号無し整数]]
([[ネットワークバイト順]]) です。
ただし[[最上位ビット]]は [CODE[0]] でなければ[['''なりません''']]。
]FIG]
[46] [[制御フレーム]]の [[payload長]]は、125バイト[[以下]]でなければ[['''なりません''']] [SRC[>>1]]。
* マスク
[19] [[フレーム]]は、[DFN[[RUBYB[[[マスク]]]@en[mask]]]]する場合と[[マスク]]しない場合があります。
[20] [[マスク]]した[[フレーム]]は、[[マスク]]欄の値が [CODE[[[1]]]] でなければ[['''なりません''']]
[SRC[>>1]]。
[21] [RUBYB[マスクキー]@en[masking key]]は、[[クライアント]]が[[無作為]]に選択した32ビット値です。
[[マスクキー]]は、[[マスク]]した[[フレーム]]内の[[マスクキー]]欄に示されます。 [SRC[>>1]]
[2] [[クライアント]]は、[[サーバー]]に送信するすべての[[フレーム]]を[[マスク]]しなければ[['''なりません''']] [SRC[>>1]]。
[5] [[サーバー]]は、[[クライアント]]に[[マスク]]した[[フレーム]]を送信しては[['''なりません''']]
[SRC[>>1]]。
[23] [[マスク]]する際に新鮮な値を[[マスクキー]]として選ばなければ[['''なりません''']] [SRC[>>1]]。
[[マスクキー]]は予測不能である必要がありますから、
強い[[エントロピー]]源から得なければ[['''なりません''']] [SRC[>>1]]。
前の[[フレーム]]から以後の[[フレーム]]の[[マスクキー]]を容易に予測できては[['''なりません''']]
[SRC[>>1]]。
;; [3] これは、[[プロキシ]]等の[[中間器]]の混乱を防ぐため、また[[セキュリティー]]のために必要な措置です
[SRC[>>1]]。
;; [22] [[RFC 4086]] に強い[[エントロピー]]源についての議論があります [SRC[>>1]]。
[24] [[マスク]]の適用と復元は、どちらも次の手順により行います [SRC[>>1]]。
[FIG(steps)[
= [25] 入力データの各[[オクテット]]について、
== [26] 出力の[[オクテット]] [VAR[i]] は、入力のオクテット [VAR[i]] と[[マスクデータ]]のオクテット [VAR[i]] [[mod]] 4 の [[XOR]] とします。
]FIG]
[4] [[サーバー]]は、[[マスク]]されていない[[フレーム]]を受信したら、
[[接続]]を閉じなければ[['''なりません''']] [SRC[>>1]]。
この場合[[サーバー]]は [CODE(HTTP)@en[[[Close]]]] [[フレーム]]を[[状態符号]]
[CODE(HTTP)[[[1002]]]] で送信して構いません [SRC[>>1]]。
[6] [[クライアント]]は、[[マスク]]された[[フレーム]]を受信したら、
[[接続]]を閉じなければ[['''なりません''']] [SRC[>>1]]。
この場合[[クライアント]]は [CODE(HTTP)@en[[[Close]]]] [[フレーム]]を[[状態符号]]
[CODE(HTTP)[[[1002]]]] で送信して構いません [SRC[>>1]]。
* 断片化
[27] [DFN[[RUBYB[断片化]@en[fragmentation]]]]により、
送信開始時点で送信データの大きさがわからない場合でも送信開始できます [SRC[>>1]]。
;; [28] [[断片化]]を使って、送信データの末端を待たずに適度にバッファーにデータが溜まった時点で送信できます [SRC[>>1]]。
[29] [[断片化]]は[RUBYB[[[多重化]]]@en[multiplexing]]により単一の[[WebSocket接続]]を複数の大きなメッセージで共有するために使うことができます。
ただし [[WebSocket]] 本体では[[多重化]]のための拡張は規定していません。 [SRC[>>1]]
[48] [[断片化]]された(かもしれない)状態のものが[[フレーム]]と呼ばれるのに対し、
そのデータを結合したものが[DFN[[RUBYB[[[メッセージ]]]@en[message]]]]
[SRC[>>1]] と呼ばれています。
[39] 受信者は[[断片化]]に対応しなければ[['''なりません''']] [SRC[>>1]]。
[31] 1つのメッセージが単一[[フレーム]]で表現される時は、
[CODE[[[FIN]]]] が [CODE[1]] に設定され [CODE[[[opcode]]]] は [CODE[0]] 以外となります
[SRC[>>1]]。
[FIG(railroad)[
= ([CODE[[[FIN]]]] = [CODE[[[1]]]], [CODE[[[opcode]]]] ≠ [CODE[[[0]]]])
]FIG]
[32] 1つのメッセージが複数[[フレーム]]で表現される時は、
[CODE[[[FIN]]]] が [CODE[0]] に設定され [CODE[[[opcode]]]] は [CODE[0]] 以外となる[[フレーム]]、
0個以上の [CODE[[[FIN]]]] が [CODE[[[0]]]] に設定され [CODE[[[opcode]]]] が [CODE[[[0]]]]
の[[フレーム]]、
[CODE[[[FIN]]]] が [CODE[[[0]]]] に設定され [CODE[[[opcode]]]] が [CODE[[[0]]]]
のフレームの列となります [SRC[>>1]]。
[FIG(railroad)[
= ([CODE[[[FIN]]]] = [CODE[[[0]]]], [CODE[[[opcode]]]] ≠ [CODE[[[0]]]])
= *
== ([CODE[[[FIN]]]] = [CODE[[[0]]]], [CODE[[[opcode]]]] = [CODE[[[0]]]])
= ([CODE[[[FIN]]]] = [CODE[[[1]]]], [CODE[[[opcode]]]] = [CODE[[[0]]]])
]FIG]
[33] [[制御フレーム]]は、断片化しては[['''なりません''']] [SRC[>>1]]。
[[中間器]]は[[制御フレーム]]の断片化状態を変更しては[['''なりません''']] [SRC[>>1]]。
[35] 断片は、送信者が送信した順序で受信者に配送しなければ[['''なりません''']] [SRC[>>1]]。
[34] [[制御フレーム]]を他の断片化された[[メッセージ]]の[[フレーム]]間に注入しても構いません
[SRC[>>1]]。受信者はこれを扱えなければ[['''なりません''']] [SRC[>>1]]。
;; [42] 大きなメッセージの転送中に [[ping]] の遅延が大きくなることを防ぐためです [SRC[>>1]]。
[36] [[拡張]]により特に規定される場合を除き、
断片を他の断片化された[[メッセージ]]の[[フレーム]]間に注入しては[['''なりません''']]
[SRC[>>1]]。
[30] [[拡張]]で特に規定される場合を除き、[[フレーム]] (の境界) は意味を持ちません。
1つの大きなメッセージも、複数に分割された[[フレーム]]を順に連結したものも、等価です。
送信者は任意の大きさに分割できます。 [SRC[>>1]]
[37] [[中間器]]は、[[拡張]]が適用されない場合や、
すべての適用される[[拡張]]を理解し問題ないと判断できる場合には、
[[フレーム]]を分割したり結合したりするかもしれません。 [SRC[>>1]]
[CODE[[[RSV1]]]], [CODE[[[RSV2]]]], [CODE[[[RSV3]]]]
のいずれかが設定されているか[[拡張]]が用いられていて、その意味を理解できなければ、
[[断片化]]の状態を変更しては[['''なりません''']] [SRC[>>1]]。
[40] [[WebSocket handshake]] を見ていない[[中間器]]は、
[[断片化]]の状態を変更しては[['''なりません''']] [SRC[>>1]]。
;; [41] どういう状況でしょうか? [[WebSocket接続の確立]]とそれ以後の処理を別の[[中間器]]で行う場合??
[38] [[拡張]]によっては、各[[フレーム]]にのみ[[拡張データ]]を含められる、
最初の[[フレーム]]にのみ含められるといったような規定があるかもしれません。 [SRC[>>1]]
* 受信
[54] 受信したデータは、[[WebSocketフレーム]]として構文解析しなければ[['''なりません''']]
[SRC[>>54]]。
[55] [[制御フレーム]]なら、そのように処理しなければ[['''なりません''']] [SRC[>>54]]。
[56] [[データフレーム]]なら、
その [CODE[[[opcode]]]] を種別、[[応用データ]]をデータとする
[RUBYB[WebSocketメッセージを受信]@en[A WebSocket Message Has Been Received]]したといいます。
ただし[[断片化]]されている場合には、以後の断片の[[応用データ]]もデータに連結してゆき、
最後の[[フレーム]]分まで連結した時をいいます。 [SRC[>>54]]
[58] [[サーバー]]は、[[マスク]]を除去しなければ[['''なりません''']] [SRC[>>54]]。
[57] ただし、[[拡張]]により別途規定がある場合は、それに拠ります [SRC[>>54]]。