Start with packet header parsing
This commit is contained in:
parent
ad60b3f368
commit
17047eac70
56
packet.go
Normal file
56
packet.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
packetFlagControl = 1
|
||||||
|
packetFlagResend = 2
|
||||||
|
packetFlagCompression = 4
|
||||||
|
packetFlagConnless = 8
|
||||||
|
)
|
||||||
|
|
||||||
|
type PacketFlags struct {
|
||||||
|
connless bool
|
||||||
|
compression bool
|
||||||
|
resend bool
|
||||||
|
control bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketHeader struct {
|
||||||
|
flags PacketFlags
|
||||||
|
ack int
|
||||||
|
numChunks int
|
||||||
|
token [4]byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (header *PacketHeader) unpack(packet []byte) {
|
||||||
|
header.flags.unpack(packet)
|
||||||
|
header.ack = (int(packet[0]&0x3) << 8) | int(packet[1])
|
||||||
|
header.numChunks = int(packet[2])
|
||||||
|
copy(header.token[:], packet[3:7])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (flags *PacketFlags) unpack(packetHeaderRaw []byte) {
|
||||||
|
flagBits := packetHeaderRaw[0] >> 2
|
||||||
|
flags.control = (flagBits & packetFlagControl) != 0
|
||||||
|
flags.resend = (flagBits & packetFlagResend) != 0
|
||||||
|
flags.compression = (flagBits & packetFlagCompression) != 0
|
||||||
|
flags.connless = (flagBits & packetFlagConnless) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (flags *PacketFlags) pack() []byte {
|
||||||
|
data := 0
|
||||||
|
|
||||||
|
if flags.control {
|
||||||
|
data |= packetFlagControl
|
||||||
|
}
|
||||||
|
if flags.resend {
|
||||||
|
data |= packetFlagResend
|
||||||
|
}
|
||||||
|
if flags.compression {
|
||||||
|
data |= packetFlagCompression
|
||||||
|
}
|
||||||
|
if flags.connless {
|
||||||
|
data |= packetFlagConnless
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte{byte(data)}
|
||||||
|
}
|
172
packet_test.go
Normal file
172
packet_test.go
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// pack
|
||||||
|
|
||||||
|
func TestPackFlagsUnset(t *testing.T) {
|
||||||
|
flags := PacketFlags{
|
||||||
|
connless: false,
|
||||||
|
compression: false,
|
||||||
|
resend: false,
|
||||||
|
control: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
got := flags.pack()
|
||||||
|
want := []byte{0b0000}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPackFlagsCompressionSet(t *testing.T) {
|
||||||
|
flags := PacketFlags{
|
||||||
|
connless: false,
|
||||||
|
compression: true,
|
||||||
|
resend: false,
|
||||||
|
control: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
got := flags.pack()
|
||||||
|
want := []byte{0b0100}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPackFlagsAllSet(t *testing.T) {
|
||||||
|
flags := PacketFlags{
|
||||||
|
connless: true,
|
||||||
|
compression: true,
|
||||||
|
resend: true,
|
||||||
|
control: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
got := flags.pack()
|
||||||
|
want := []byte{0b1111}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unpack
|
||||||
|
|
||||||
|
func TestUnpackFlagsAllSet(t *testing.T) {
|
||||||
|
got := PacketFlags{}
|
||||||
|
want := PacketFlags{
|
||||||
|
connless: true,
|
||||||
|
compression: true,
|
||||||
|
resend: true,
|
||||||
|
control: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
got.unpack([]byte{0b00111100})
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnpackFlagsControlSet(t *testing.T) {
|
||||||
|
got := PacketFlags{}
|
||||||
|
want := PacketFlags{
|
||||||
|
connless: false,
|
||||||
|
compression: false,
|
||||||
|
resend: false,
|
||||||
|
control: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
got.unpack([]byte{0b00000100})
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnpackFlagsUnset(t *testing.T) {
|
||||||
|
got := PacketFlags{}
|
||||||
|
want := PacketFlags{
|
||||||
|
connless: false,
|
||||||
|
compression: false,
|
||||||
|
resend: false,
|
||||||
|
control: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
got.unpack([]byte{0b00000000})
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// packet header unpack
|
||||||
|
|
||||||
|
func TestUnpackCloseWithReason(t *testing.T) {
|
||||||
|
got := PacketHeader{}
|
||||||
|
want := PacketHeader{
|
||||||
|
flags: PacketFlags{
|
||||||
|
connless: false,
|
||||||
|
compression: false,
|
||||||
|
resend: false,
|
||||||
|
control: true,
|
||||||
|
},
|
||||||
|
ack: 10,
|
||||||
|
numChunks: 0,
|
||||||
|
token: [4]byte{0xcf, 0x2e, 0xde, 0x1d},
|
||||||
|
}
|
||||||
|
|
||||||
|
got.unpack(slices.Concat([]byte{0x04, 0x0a, 0x00, 0xcf, 0x2e, 0xde, 0x1d, 0x04}, []byte("shutdown"), []byte{0x00}))
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnpackHeaderFlagsControlSet(t *testing.T) {
|
||||||
|
got := PacketHeader{}
|
||||||
|
want := PacketHeader{
|
||||||
|
flags: PacketFlags{
|
||||||
|
connless: false,
|
||||||
|
compression: false,
|
||||||
|
resend: false,
|
||||||
|
control: true,
|
||||||
|
},
|
||||||
|
ack: 0,
|
||||||
|
numChunks: 0,
|
||||||
|
token: [4]byte{0xff, 0xff, 0xff, 0xff},
|
||||||
|
}
|
||||||
|
|
||||||
|
got.unpack([]byte{0b00000100, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff})
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnpackHeaderFlagsAllSet(t *testing.T) {
|
||||||
|
got := PacketHeader{}
|
||||||
|
want := PacketHeader{
|
||||||
|
flags: PacketFlags{
|
||||||
|
connless: true,
|
||||||
|
compression: true,
|
||||||
|
resend: true,
|
||||||
|
control: true,
|
||||||
|
},
|
||||||
|
ack: 0,
|
||||||
|
numChunks: 0,
|
||||||
|
token: [4]byte{0xff, 0xff, 0xff, 0xff},
|
||||||
|
}
|
||||||
|
|
||||||
|
got.unpack([]byte{0b00111100, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff})
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Errorf("got %v, wanted %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package teeworlds
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package teeworlds
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
Loading…
Reference in a new issue