These are my own notes from reading [The Websocket Protocol](https://datatracker.ietf.org/doc/html/rfc6455) specification. Here I will just note down things I think I may forget or just want to have in writing for future reference.
The protocol consists of an opening handshake followed by message framing layered over [[TCP]]. It is state the the goal of the protocol is to not have to rely on opening multiple [[HTTP]] connections like using [[XMLHttpRequest]], iframes, and [[Long polling]].
## Protocol Overview
The protocol consists of two parts: a handshake and the data transfer.
The client initiates a handshake with:
```
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
```
The server may then respond with:
```
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
```
A websocket message does not correspond to any network layer framing. The message may be split or coalesced by intermediary transports.
Frames have a type. Each frame belong to the same message contains the same type of data. The different types of frames are:
- Textual data interpreted as [[UTF-8]]
- Binary data
- Control frames for protocol-level signaling
### Completing the handshake
The server has to prove that it has received the handshake. It does so by:
1. Pick out the `Sec-WebSocket-Key` header of the request
2. Concatenate it with the value `258EAFA5-E914-47DA-95CA-C5AB0DC85B11`.
1. This value is globally unique
3. Take the [[SHA-1]] hash of the concatenated value
4. [[Base64]] encode the hash
5. Return back to client in the `Sec-WebSocket-Accept` header
Example:
```go
// 1. Pick out the `Sec-WebSocket-Key` header of the request
secWebsocketKey := "dGhlIHNhbXBsZSBub25jZQ=="
// 2. Concatinate
concatenated := secWebsocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
// 3. SHA-1 hash
hash := sha1.Sum(concatenated)
// 4. Base64 encode
b64 := base64.EncodeToString(hash)
// 5. Send back response
// ...
```