* 仕様書

[REFS[
- [10] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-5>
- [54] [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>
- [36] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-7.1.7>
- [21] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-8>
- [50] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-10.4>
- [59] [CITE@en[RFC 6455 - The WebSocket Protocol]] ([TIME[2015-03-11 20:42:50 +09:00]] 版) <http://tools.ietf.org/html/rfc6455#section-10.7>
- [1] [CITE@en-GB-x-hixie[HTML Standard]] ([TIME[2015-05-06 10:42:35 +09:00]] 版) <https://html.spec.whatwg.org/#feedback-from-the-protocol>
]REFS]

* 処理

[6] [[WebSocket接続の確立]]により[[WebSocket接続]]の状態が [CODE[[[OPEN]]]]
になると、以後の受信データは次のように処理されることになります。

;; [5] [[WebSocket]] の規定に従わない[[クライアント]]は、 [[WebSocket handshake]]
における[[サーバー]]からの[[応答]]を待たずに[[フレーム]]
(や[[フレーム]]になっていないデータ) を送信するかもしれません。[[サーバー]]はそれに特別な対処を行う必要はありませんが、 >>60 を根拠に切断しても良いのかもしれません。

[53] 受信したデータは、次のように処理しなければ[['''なりません''']]。
[FIG(steps)[
= [37] [[WebSocket接続]]の[[WebSocket接続失敗]]が[[真]]であれば、停止します [SRC[>>36]]。
= [9] [[WebSocketフレーム]]として構文解析します [SRC[>>54]]。
== [40] [[フレーム]]の長さを決定します。[[WebSocketフレーム]]の項を参照。ここで接続が閉じられることもあります。
= [60] 不正なデータなら、[[TCP接続]]を切断して構いません。
次のようにする[['''べきです''']]。 [SRC[>>59]]
== [7] [[[CODE[Close]]フレーム]]を送信します。
== [8] [[WebSocket接続を閉じる]]処理を実行します。
== [15] 停止します。
= [13] 自身が[[サーバー]]であり、[[フレーム]]が[[マスク]]されていないか、
自身が[[クライアント]]であり、[[フレーム]]が[[マスク]]されているなら、
== [19] [[[CODE[Close]]フレーム]]を[[状態符号]] [CODE(HTTP)[[[1002]]]] で送信して構いません
[SRC[>>10]]。
== [18] [[接続]]を閉じます [SRC[>>10]]。
= [41] [CODE[[[FIN]]]] が 0 で [[opcode]] が 0x8, 0x9, 0xA なら、
[[WebSocket接続失敗]]を実行し、停止します。
= [14] 次の場合は、[[WebSocket接続失敗]]を実行し、停止します。 [SRC[>>10]]。
[FIG(list)[
- [16] [CODE[[[RSV1]]]] が非 [CODE[[[0]]]] 値であり、[[拡張]]のいずれの規定にも拠っていない場合
- [17] [CODE[[[RSV2]]]] が非 [CODE[[[0]]]] 値であり、[[拡張]]のいずれの規定にも拠っていない場合
- [11] [CODE[[[RSV3]]]] が非 [CODE[[[0]]]] 値であり、[[拡張]]のいずれの規定にも拠っていない場合
]FIG]
= [12] 未知の [CODE[[[opcode]]]] の場合は、[[WebSocket接続失敗]]を実行し、停止します。 [SRC[>>10]]。
= [58] 自身が[[サーバー]]なら、[[マスク]]を除去します [SRC[>>54]]。
= [55] [[制御フレーム]]なら、その規定により処理します [SRC[>>54]]。
([[[CODE[Close]]フレーム]], [[[CODE[Ping]]フレーム]], [[[CODE[Pong]]フレーム]]を参照。)
= [22] [[継続フレーム]]なら、
== [23] [VAR[不完全なメッセージ]]が無いなら、
[[WebSocket接続失敗]]を実行し停止するべきと思われます。
== [24] [VAR[不完全なメッセージ]]の [[payloadデータ]]に[[フレーム]]の[[payloadデータ]]を連結します。
[[拡張]]により規定がある場合は、その方法によります [SRC[>>54]]。
= [25] [[テキストフレーム]]か[[バイナリーフレーム]]なら、
== [26] [VAR[不完全なメッセージ]]があるなら、
[[WebSocket接続失敗]]を実行し停止するべきと思われます。
== [27] [VAR[不完全なメッセージ]]を、本[[フレーム]]に設定します。
= [28] [[フレーム]]の[CODE[[[FIN]]]] が [CODE[[[1]]]] なら、
== [29] [VAR[不完全なメッセージ]]の[[payloadデータ]]を[[拡張]]の規定 (あれば) により処理します [SRC[>>54]]。
== [30] [VAR[不完全なメッセージ]]が[[テキストフレーム]]なら、
=== [31] [[応用データ]]を [[UTF-8]] として[[復号]]します。
=== [32] [[復号]]に失敗したら、[[WebSocket接続失敗]]を実行し、停止します [SRC[>>21]]。
== [56] [DFN[[RUBYB[WebSocketメッセージを受信]@en[A WebSocket Message Has Been Received]]]]を実行します。[[テキストフレーム]]なら[[復号]]した[[文字列]]を、[[バイナリーフレーム]]なら[[応用データ]]を引き渡します。 [SRC[>>54]]
== [33] [VAR[不完全なメッセージ]]を、 [[null]] に設定します。
]FIG]

;; [20] [[RFC]] はエラー処理を曖昧にしか規定していません。 ([[IETF]] ではよくあることです。)

;; [35] [[RFC]] は閉じ方が規定毎に違う説明になっていますが、何か意図的なのか、
すべて[[WebSocket接続失敗]]と同じとみなして良いのか不明です。

[38] [[Chrome]] は[[マスク]]フラグ → [[RSV]] フラグ → [[opcode]]
の順に検査するようです。 [TIME[2015-08-16T09:11:16.100Z]]

[39] [[Chrome]] は[[マスク]]されている場合、予約ビットが立っている場合、未知 [[opcode]]
が使われている場合に、[[状態符号]]が [CODE[[[1002]]]] の [[Closeフレーム]]を送信します。
理由はそれぞれ  [CODE[Masked frame from server]], 
[CODE[Invalid reserved bit]], [CODE[Unknown opcode]] です。
[[Firefox]] はこれらの場合に何も送信せずに[[接続]]を閉じるようです。 [TIME[2015-08-16T13:10:44.700Z]]

[52] 扱える[[フレーム]]のサイズや[[断片化]]を結合した[[メッセージ]]のサイズに上限がある実装は、
それを超えないよう自身を保護しなければ[['''なりません''']] [SRC[>>50]]。

[2] [[利用者エージェント]]は、種別[VAR[種別]]のデータ[VAR[メッセージデータ]]の
[[WebSocketメッセージを受信]]したら、
[CODE(DOMi)@en[WebSocket]] [[オブジェクト]][VAR[オブジェクト]]について、
次の[[タスク]]を[[タスクキュー]]に追加しなければ[MUST[なりません]] [SRC[>>1]]。
[FIG(list members)[ [43] [[タスク]]

:[F[タスク源]]:[[WebSocketタスク源]]
: [F[処理]] :
[FIG(steps)[
= [46] [VAR[オブジェクト]]の [CODE(DOMa)@en[[[readyState]]]] が [CODE(DOM)[[[OPEN]]]] ([CODE[[[1]]]])
でなければ、停止します。
= [48] [VAR[種別]]により、
[FIG(switch)[
: [[テキスト]] : [VAR[データ]]を、[VAR[メッセージデータ]]に設定します。
: [[バイナリー]] :
[VAR[オブジェクト]]の [F[[CODE(DOMa)@en[binaryType]]]] により、
[FIG(switch)[
: [CODE[blob]] :
[VAR[データ]]を、[VAR[オブジェクト]]の[F[関連Realm]]における、
[F[生データ]]が[VAR[メッセージデータ]]である新しい [CODE(DOMi)@en[Blob]] に設定します。
: [CODE[arraybuffer]] :
[VAR[データ]]を、[VAR[オブジェクト]]の[F[関連Realm]]における、
[F[内容]]が[VAR[メッセージデータ]]である新しい [CODE(DOMi)@en[ArrayBuffer]] に設定します。
]FIG]

]FIG]
= [44] [[イベント]]を[[発火]]します。
[FIG(list members middle)[ [45] [[イベント]]

:[[インターフェイス]]:[CODE(DOMi)@en[[[MessageEvent]]]]
:[[イベント型]]:[CODE(DOMe)@en[[[message]]]]
: [F[対象][イベント対象]] : [VAR[オブジェクト]]
:[[trusted]]:[[真]]
:[[bubbles]]:[[偽]]
:[[取り消し可能]]:[[偽]]
: [F[[CODE(DOMa)@en[origin]]]] :
[VAR[オブジェクト]]の [F[[CODE(DOMa)@en[url]]]]
の[[起源][URLの起源]]の[F[直列化][ASCII直列化]]
: [F[[CODE(DOMa)@en[data]]]] : [VAR[data]]

]FIG]

]FIG]

]FIG]

[3] [[利用者エージェント]]は、本[[タスク]]の実行の時に効率的に実行する条件が満たされていなければ、実行を遅延させて他の[[タスクキュー]]の[[タスク]]を実行することが[RUBYB[推奨]@en[encouraged]]されています。 [SRC[>>1]]

[EG[
[4] 例えば、受信したデータが[[ディスク]]にあり、[[タスク]]実行時点で
[CODE(DOMa)@en[[[binaryType]]]] が [CODE[[[arraybuffer]]]] になっていれば、
データを[[メモリー]]に読み込む処理を実行し、その完了まで他の[[タスク]]を実行していることができます。 [SRC[>>1]]
]EG]

[34] [[サーバー]]は、[[WebSocketメッセージを受信]]したら、適宜必要な処理を実行できます。

* 歴史

[42] [CITE@en[Editorial: more minor event creation/dispatch cleanup]]
([[domenic]]著, [TIME[2016-10-26 02:20:58 +09:00]])
<https://github.com/whatwg/html/commit/5fafa73c8ad57f2d98e9c978200e11199fb26bdc>

[47] [CITE@en[Specify the realm used for WebSocket-created Blobs and ArrayBuffers]]
([[domenic]]著, [TIME[2016-10-25 05:51:11 +09:00]])
<https://github.com/whatwg/html/commit/6bf5e4414af4bc2d5fd723443b21f5ada45532fb>

[49] [CITE@en[Remove Unicode serialization of an origin]]
([[annevk]]著, [TIME[2017-05-18 13:24:49 +09:00]])
<https://github.com/whatwg/html/commit/59ebd9c094d9d532458a9ee61f307bf41bc70811>