-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
95 lines (83 loc) · 2.41 KB
/
main.go
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
/**
* For education purpose only, by Mihai Dragusin
* Do NOT copy
*/
package ws
import (
"encoding/binary"
"fmt"
)
// Parses the websocket masked frame decoding it using
//
// `D_i = E_i XOR M_(i mod 4)` or `returnData[i] = encodedData[i] ^ mask32bit[i%4]`
func ParseFrame(p []byte) Frame {
firstByte := p[0]
fin := p[0]&FIN == FIN
secondByte := p[1]
maskSet := secondByte&HasMask == HasMask
// fmt.Println("mask set is ", maskSet)
msgLen := uint64(secondByte & 0b01111111)
startOfPayload := 2 // after first two bytes we already parsed
decoded := make([]byte, msgLen+1)
masks := make([]byte, 4)
if msgLen < 126 {
// fmt.Println("msg len is ", msgLen)
if maskSet {
masks = p[2:6] // 2 - 5 inclusive - 4 bytes, 32 bit
}
// fmt.Println("mask is ", masks)
startOfPayload += len(masks)
} else if msgLen == 126 {
// fmt.Println("second byte len is", msgLen)
// if 126 then the actual msg len is next 2 bytes as 16 bit uint
msgLen = uint64(binary.BigEndian.Uint16(p[2:4])) // network data is always in big endian
if maskSet {
masks = p[4:8]
}
startOfPayload += (len(masks) + len(p[2:4])) // start of payload data should be after mask and length bytes, at the first byte after
decoded = make([]byte, msgLen+1)
} else if msgLen > 126 {
// if over 126 then we need to parse the next eight bytes as an unsigned integer 64 bit
msgLen := binary.BigEndian.Uint64(p[2:10])
if maskSet {
masks = p[10:14]
}
startOfPayload += (len(masks) + len(p[2:10])) + 1
decoded = make([]byte, msgLen+1)
}
for i := 0; i < int(msgLen); i++ {
decoded[i] = p[startOfPayload+i] ^ masks[i%4]
}
return Frame{
Byte0: Byte0{
FIN: fin,
RSV1: (firstByte&RSV1 != RSV1),
RSV2: (firstByte&RSV2 != RSV2),
RSV3: (firstByte&RSV3 != RSV3),
},
Byte1: Byte1{
HasMask: maskSet,
InitialLength: (secondByte & 0b01111111),
},
DecodedPayload: decoded,
PayloadLength: msgLen,
}
}
// SendNewFrame assembles an unmasked server frame with data as payload
func SendSerializedFrame(data []byte) []byte {
var payload []byte
payloadLen := len(data)
if payloadLen < 126 {
payload = make([]byte, payloadLen+2)
payload[0] ^= FIN
payload[0] ^= OPCODE_TEXT
// FIN and OPCODE_TEXT combination informs it is a full frame with text
payload[1] ^= uint8(payloadLen)
offset := 2
for i := 0; i < payloadLen; i++ {
payload[offset+i] = data[i]
}
}
fmt.Println("sending", string(payload))
return payload
}