I'm having a blast reinventing the wheel and playing with bits to implement a simple server. It's almost functional, but I'm not sure if this issue is my client or my server. Here is the function where I pass the resulting byte array from net.Conn Read
func readWsFrame(p []byte) {
// process first byte
b := p[0]
fmt.Printf("first byte: %b
", b)
fin := b & 128 // hopefully 128, for fin
op := b & 15 // hopefully 1, for text
fmt.Printf("fin: %d
op: %d
", fin, op)
// process second byte
b = p[1]
fmt.Printf("second byte: %b
", b)
masked := b & 128 // whether or not the payload is masked
length := b & 127 // payload length
fmt.Printf("masked: %d
length: %d
", masked, length)
// process bytes 3-7 (masking key)
key := p[2:6]
// payload
d := p[6:]
if length == 126 {
key = p[4:8]
d = p[8:]
fmt.Println("med key")
} else if length == 127 {
key = p[10:14]
d = p[14:]
fmt.Println("big key")
} else {
fmt.Println("lil key")
}
fmt.Printf("masking key: %b
", key)
fmt.Printf("masked data: %b
", d)
var decoded []byte
for index := 0; index < int(length); index++ {
decoded = append(decoded, d[index]^key[index%4])
}
fmt.Printf("unmasked data: %b
", decoded)
payload := string(decoded)
fmt.Println("payload: ", payload)
}
The client code is me having the dev console open right off this web page and running
var ws = new WebSocket("ws://localhost:16163");
ws.send("a".repeat(125))
ws.send("a".repeat(126))
ws.send("a".repeat(127))
ws.send("a".repeat(400))
My server is doing what I expect until I reach 127 characters. At that point, and every amount over 126, my 2nd byte is 11111110 and the length is 126. I can see the unmasked/encoded/magic message doesn't go beyond 126 a's.
I'm sure my go code is sub-par and there might be something obvious here, but I'm looking at the bits themselves, and I can see a 0 where I am expecting a 1, please help me, thank you!
I saw a similar question about writing messages larger than 126 bytes and how I'll need extra bytes for payload size, but in this case my client is the chrome web browser.
--edit:
I realize that I will never see more than 126 characters based on the loop I have there, but I should still see a 1 in the final bit in the second byte for these larger messages, right?
--edit:
Came across this how to work out payload size from html5 websocket
I guess I misunderstood everything else I was searching for. Can someone confirm this? If the length is <126, the length is byte & 127. If the length is 126, the length is the value of the next 2 bytes. If the length is 127, the length is the next 4 bytes.
I thought initially that the length would be 127 if it payload length was 127+ hah, oops. So when the length is 126 or 127, the 2nd byte is not part of the actual length? I'll probably confirm all of this with testing, but I thank you all for resolving this issue before the weekend so I can finish this side project.
The code should update the length property after realizing it's 127 or 126 by reading the length data in the bytes that follow the initial length indicator.
I would consider those 7 "length" bits slightly differently. They don't really indicate length as much as they indicate encoding.
If the length is encoded using 64bits (8 bytes), than the length indicator == 127.
If the length is encoded in 2 bytes, than the indicator == 126.
Otherwise, the length is encoded in the 7 bits of the indicator itself.
For example, the length 60 can be encoded in all three ways (albeit, some use more space).
There's a C Websocket implementation here if you want to read an example decoding of the length.
Good Luck!