昨日の記事で送付するヘッダーは作れたので、今日はメッセージの暗号化を書こうと思います。
WebSocketのハンドシェイクをエミュレートする
昨日も書きました、これらの処理はブラウザがやってくれるので
本来は自前でやる必要のない機能なので、笑い話としてみてもらえればと思います。
クライアントからサーバーに向かうメッセージはXOR暗号化(32ビットキー)を使用してマスクされます。
フォーマット
Frame format:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
え。。。
これやらないと、メッセージを送れないの??
まじか・・・
やるか・・・
/**
* @param {string} value
* @return {array}
* @public
*/
stringToArray = function (value)
{
const array = [];
const length = value.length;
for (let idx = 0; idx < length; ++idx) {
const code = value.charCodeAt(idx);
if (code > 127) {
const values = encodeURIComponent(value[idx]).split("%");
const length = values.length;
for (let idx = 1; idx < length; ++idx) {
array[array.length] = parseInt(values[idx], 16);
}
continue;
}
array.push(code);
}
return array;
};
/**
* @param {Event} event
* @return {void}
* @public
*/
function (event)
{
// ByteArrayクラスも自前する必要があるのですが、ここはまたいつか・・・
const byteArray = new ByteArray();
byteArray.writeByte(129); // fixed opcode 1 only
// 受け取ったメッセージを数値に変換
const values = stringToArray(event.data);
let length = values.length;
if (126 > length) {
// メッセージが126桁以下ならペイロードの長さをセット
byteArray.writeByte(length);
} else if (length > 125 && length < 65536) {
// 126以上なら固定値で126をセットして、次にペイロードの長さをセット
byteArray.writeByte(126);
byteArray.writeShort(length);
} else {
// 65536以上なら固定値で127をセットして、判定の0を入れてペイロードの長さをセット
byteArray.writeByte(127);
byteArray.writeUnsignedInt(0);
byteArray.writeUnsignedInt(length);
}
// 最後に文字列を数値化したデータをセット
byteArray.length += length;
byteArray.set(values, byteArray.position);
ヘッダーと一緒に送信して完了です。
メッセージを送るだけでも一苦労です。。。
これを、ブラウザは自動でやってくれるので本当に感謝です。。。
明日は何を書こうかな・・・